• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / team4-wed-spring25 / 391

08 Apr 2025 07:09PM UTC coverage: 97.251% (+0.3%) from 96.976%
391

push

travis-pro

divya603
Fix formatting: autoformat with Black and fix flake8 blank lines issue

955 of 982 relevant lines covered (97.25%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

87.6
/parks/views.py
1
from django.shortcuts import render, get_object_or_404, redirect
1✔
2
from django.http import (  # noqa: F401  # Ignore "imported but unused"
1✔
3
    HttpResponseForbidden,
4
    HttpResponse,
5
)
6
from django.db.models import OuterRef, Subquery, CharField, Q, Avg, Count
1✔
7
from django.db.models.functions import Cast
1✔
8
from .models import DogRunNew, Review, ParkImage, ReviewReport, ImageReport
1✔
9
from django.forms.models import model_to_dict
1✔
10
from django.contrib.auth import login
1✔
11
from django.contrib.auth.decorators import login_required
1✔
12

13
import folium
1✔
14
from folium.plugins import MarkerCluster
1✔
15

16
from .utilities import folium_cluster_styling
1✔
17
from .forms import RegisterForm
1✔
18

19
import json
1✔
20

21

22
def register_view(request):
1✔
23
    if request.method == "POST":
1✔
24
        form = RegisterForm(request.POST)
1✔
25
        if form.is_valid():
1✔
26
            # Save but don't commit yet
27
            user = form.save(commit=False)
1✔
28
            # If they chose Admin, mark them as staff
29
            if form.cleaned_data["role"] == "admin":
1✔
30
                user.is_staff = True
1✔
31
            user.save()
1✔
32

33
            # Log the user in immediately
34
            login(request, user)
1✔
35
            request.session.save()
1✔
36
            return redirect("home")
1✔
37
    else:
38
        form = RegisterForm()
1✔
39

40
    return render(request, "parks/register.html", {"form": form})
1✔
41

42

43
def park_list(request):
1✔
44
    query = request.GET.get("query", "")
1✔
45
    parks = DogRunNew.objects.all()  # Fetch all dog runs from the database
1✔
46

47
    if query:
1✔
48
        parks = parks.filter(
×
49
            Q(name__icontains=query)
50
            | Q(google_name__icontains=query)
51
            | Q(zip_code__icontains=query)
52
        )
53

54
    return render(request, "parks/park_list.html", {"parks": parks, "query": query})
1✔
55

56

57
def home_view(request):
1✔
58
    return render(request, "parks/home.html")
×
59

60

61
def map(request):
1✔
62

63
    NYC_LAT_AND_LONG = (40.730610, -73.935242)
1✔
64
    # Create map centered on NYC
65
    m = folium.Map(location=NYC_LAT_AND_LONG, zoom_start=11)
1✔
66

67
    icon_create_function = folium_cluster_styling("rgb(0, 128, 0)")
1✔
68

69
    marker_cluster = MarkerCluster(icon_create_function=icon_create_function).add_to(m)
1✔
70

71
    # Fetch all dog runs from the database
72
    parks = DogRunNew.objects.all()
1✔
73

74
    # Mark every park on the map
75
    for park in parks:
1✔
76
        park_name = park.name
×
77

78
        folium.Marker(
×
79
            location=(park.latitude, park.longitude),
80
            icon=folium.Icon(icon="dog", prefix="fa", color="green"),
81
            popup=folium.Popup(park_name, max_width=200),
82
        ).add_to(marker_cluster)
83

84
    # represent map as html
85
    context = {"map": m._repr_html_()}
1✔
86
    return render(request, "parks/map.html", context)
1✔
87

88

89
def park_and_map(request):
1✔
90
    # Get filter values from GET request
91
    query = request.GET.get("query", "").strip()
1✔
92
    filter_value = request.GET.get("filter", "").strip()
1✔
93
    accessible_value = request.GET.get("accessible", "").strip()
1✔
94
    borough_value = request.GET.get("borough", "").strip().upper()
1✔
95

96
    thumbnail = ParkImage.objects.filter(park_id=OuterRef("pk")).values("image")[:1]
1✔
97

98
    # Fetch all dog runs from the database
99
    parks = (
1✔
100
        DogRunNew.objects.all()
101
        .order_by("id")
102
        .prefetch_related("images")
103
        .annotate(
104
            thumbnail_url=Cast(Subquery(thumbnail), output_field=CharField()),
105
            average_rating=Avg("reviews__rating"),
106
            review_count=Count("reviews"),
107
        )
108
    )
109

110
    # Search by ZIP, name, or Google name
111
    if query:
1✔
112
        parks = parks.filter(
×
113
            Q(name__icontains=query)
114
            | Q(google_name__icontains=query)
115
            | Q(zip_code__icontains=query)
116
        )
117

118
    # Filter by park type (e.g., "Off-Leash")
119
    if filter_value:
1✔
120
        parks = parks.filter(dogruns_type__iexact=filter_value)
×
121

122
    # Filter by accessibility only if explicitly set to "True" or "False"
123
    if accessible_value == "True":
1✔
124
        parks = parks.filter(accessible=True)
×
125
    elif accessible_value == "False":
1✔
126
        parks = parks.filter(accessible=False)
×
127

128
    if borough_value:
1✔
129
        parks = parks.filter(borough=borough_value)
1✔
130

131
    # Convert parks to JSON (for JS use)
132
    parks_json = json.dumps(list(parks.values()))
1✔
133

134
    # Render the template
135
    return render(
1✔
136
        request,
137
        "parks/combined_view.html",
138
        {
139
            "parks": parks,
140
            "parks_json": parks_json,
141
            "query": query,
142
            "selected_type": filter_value,
143
            "selected_accessible": accessible_value,
144
            "selected_borough": borough_value,
145
        },
146
    )
147

148

149
def park_detail(request, slug, id):
1✔
150
    park = get_object_or_404(DogRunNew, id=id)
1✔
151
    images = ParkImage.objects.filter(park=park)
1✔
152
    reviews = park.reviews.all()
1✔
153
    average_rating = reviews.aggregate(Avg("rating"))["rating__avg"]
1✔
154

155
    if request.user.is_authenticated and request.method == "POST":
1✔
156
        form_type = request.POST.get("form_type")
1✔
157

158
        if form_type == "upload_image" and request.FILES.getlist("images"):
1✔
159
            for image in request.FILES.getlist("images"):
×
160
                ParkImage.objects.create(park=park, image=image, user=request.user)
×
161
            return redirect("park_detail", slug=park.slug, id=park.id)
×
162

163
        elif form_type == "submit_review":
1✔
164
            review_text = request.POST.get("text", "").strip()
1✔
165
            rating_value = request.POST.get("rating", "").strip()
1✔
166

167
            if not rating_value.isdigit():
1✔
168
                return render(
×
169
                    request,
170
                    "parks/park_detail.html",
171
                    {
172
                        "park": park,
173
                        "images": images,
174
                        "reviews": reviews,
175
                        "error_message": "Please select a valid rating!",
176
                        "average_rating": average_rating,
177
                    },
178
                )
179

180
            rating = int(rating_value)
1✔
181
            if rating < 1 or rating > 5:
1✔
182
                return render(
×
183
                    request,
184
                    "parks/park_detail.html",
185
                    {
186
                        "park": park,
187
                        "images": images,
188
                        "reviews": reviews,
189
                        "error_message": "Rating must be between 1 and 5 stars!",
190
                        "average_rating": average_rating,
191
                    },
192
                )
193

194
            Review.objects.create(
1✔
195
                park=park, text=review_text, rating=rating, user=request.user
196
            )
197
            return redirect("park_detail", slug=park.slug, id=park.id)
1✔
198
        # report reviews
199
        elif form_type == "report_review":
1✔
200
            if request.user.is_authenticated:
1✔
201
                review_id = request.POST.get("review_id")
1✔
202
                reason = request.POST.get("reason", "").strip()
1✔
203
            if review_id and reason:
1✔
204
                review = get_object_or_404(Review, id=review_id)
1✔
205
                ReviewReport.objects.create(
1✔
206
                    review=review, reported_by=request.user, reason=reason
207
                )
208
                return redirect("park_detail", slug=park.slug, id=park.id)
1✔
209

210
    park_json = json.dumps(model_to_dict(park))
1✔
211

212
    return render(
1✔
213
        request,
214
        "parks/park_detail.html",
215
        {
216
            "park": park,
217
            "images": images,
218
            "reviews": reviews,
219
            "park_json": park_json,
220
            "average_rating": average_rating,
221
        },
222
    )
223

224

225
@login_required
1✔
226
def delete_review(request, review_id):
1✔
227
    review = get_object_or_404(Review, id=review_id)
1✔
228
    if request.user == review.user:
1✔
229
        review.delete()
1✔
230
        return redirect("park_detail", slug=review.park.slug, id=review.park.id)
1✔
231
    else:
232
        return HttpResponseForbidden("You are not allowed to delete this review.")
×
233

234

235
@login_required
1✔
236
def delete_image(request, image_id):
1✔
237
    image = get_object_or_404(ParkImage, id=image_id)
1✔
238
    if image.user == request.user:
1✔
239
        park_id = image.park.id
1✔
240
        image.delete()
1✔
241
        return redirect("park_detail", slug=image.park.slug, id=park_id)
1✔
242
    return HttpResponseForbidden("You are not allowed to delete this image.")
×
243

244

245
def contact_view(request):
1✔
246
    return render(request, "parks/contact.html")
1✔
247

248

249
@login_required
1✔
250
def report_image(request, image_id):
1✔
251
    image = get_object_or_404(ParkImage, id=image_id)
1✔
252
    if request.method == "POST":
1✔
253
        reason = request.POST.get("reason", "").strip()
1✔
254
        if reason:
1✔
255
            ImageReport.objects.create(user=request.user, image=image, reason=reason)
1✔
256
            return redirect("park_detail", slug=image.park.slug, id=image.park.id)
1✔
257
    return redirect("park_detail", slug=image.park.slug, id=image.park.id)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc