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

gcivil-nyu-org / INT2-Monday-Spring2024-Team-3 / #619631681

23 Mar 2024 10:05PM UTC coverage: 89.789%. First build
#619631681

Pull #126

travis-ci

Pull Request #126: Group Chat using Django Channel

98 of 180 new or added lines in 16 files covered. (54.44%)

1275 of 1420 relevant lines covered (89.79%)

0.9 hits per line

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

81.18
/backend/views/base.py
1
import re
1✔
2
import ast
1✔
3
from django.conf import settings
1✔
4
from django.http import Http404, JsonResponse
1✔
5
from django.shortcuts import render, redirect, get_object_or_404
1✔
6
from django.contrib.auth import authenticate, login, logout, get_user_model
1✔
7
from django.contrib.auth.decorators import login_required
1✔
8
from django.contrib import messages
1✔
9
from django.template.loader import render_to_string
1✔
10
from ..models import (
1✔
11
    Event,
1✔
12
    UserEvent,
1✔
13
    SearchHistory,
1✔
14
    Review,
1✔
15
    BannedUser,
1✔
16
    SuspendedUser,
1✔
17
    User,
1✔
18
    Room3,
1✔
19
)
20
from ..forms import UserRegistrationForm
21
from ..tokens import account_activation_token
1✔
22
from django.contrib.sites.shortcuts import get_current_site
×
23
from django.utils.encoding import force_bytes, force_str
×
24
from django.core.mail import EmailMessage
25
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
26
from django.views.decorators.http import require_POST
1✔
27
from django.views.decorators.csrf import csrf_exempt
1✔
28
from django.utils import timezone
1✔
29
from django.db.models import Avg, Count, Q, Value, FloatField
1✔
30
from django.db.models.functions import Coalesce
31

32
EVENT_CATEGORIES = [
33
    "Musical",
34
    "Original",
35
    "Play",
36
    "Drama",
37
    "Revival",
38
    "Comedy",
1✔
39
    "Puppets",
40
]
1✔
41

42

1✔
43
def index_with_categories_view(request):
44
    availability_filter = request.GET.get("availability", "All")
1✔
45
    sort_by = request.GET.get("sort_by", "")
46
    now = timezone.now()
1✔
47

1✔
NEW
48
    events = Event.objects.all().order_by("title")
×
49

50
    # Filter events based on availability
1✔
51
    if availability_filter == "Past":
52
        events = events.filter(close_date__isnull=False, close_date__lt=now)
1✔
53
    elif availability_filter == "Current":
54
        events = events.filter(
1✔
55
            Q(open_date__lte=now, close_date__gte=now)
56
            | Q(open_date__lte=now, close_date__isnull=True)
1✔
57
        )
1✔
58
    elif availability_filter == "Upcoming":
59
        events = events.filter(open_date__gt=now)
1✔
60

×
61
    # Sort events based on user selection
×
62
    if sort_by == "Average Rating":
×
63
        events = events.annotate(
64
            adjusted_avg_rating=Coalesce(
1✔
65
                Avg("reviews__rating"), Value(0), output_field=FloatField()
66
            )
67
        ).order_by("-adjusted_avg_rating")
68
    elif sort_by == "Popularity":
69
        events = events.annotate(review_count=Count("reviews")).order_by(
70
            "-review_count"
71
        )
72

73
    categories = EVENT_CATEGORIES
74

75
    context = {
76
        "events": events,
77
        "categories": categories,
78
        "current_availability": availability_filter,
1✔
79
        "current_sort": sort_by,
1✔
80
    }
1✔
81
    return render(request, "index.html", context)
1✔
82

83

84
def event_detail(request, event_id):
1✔
85
    loggedIn = request.user.is_authenticated
1✔
86
    event = get_object_or_404(Event, pk=event_id)
×
87

×
88
    pattern = r"[^a-zA-Z0-9\s]"
×
89
    cleaned_title = re.sub(pattern, "", event.title)
×
90
    title_split = cleaned_title.split()
91
    room_slug = ""
92
    if len(title_split) >= 3:
×
93
        room_slug = "_".join(title_split[:3])
×
94
    else:
×
95
        room_slug = "_".join(title_split[:])
96

97
    room_slug = room_slug.lower()
1✔
98

1✔
99
    interested = False
1✔
100
    if loggedIn:
1✔
101
        interested = UserEvent.objects.filter(
1✔
102
            event=event,
103
            user=request.user,
1✔
104
        ).exists()
1✔
105

106
    try:
1✔
107
        category_list = ast.literal_eval(event.category)
108
        if isinstance(category_list, list):
109
            event.category = ", ".join(category_list)
110
        else:
111
            event.category = event.category
1✔
112
    except (ValueError, SyntaxError):
113
        event.category = event.category
1✔
114

1✔
115
    avg_rating_result = Review.objects.filter(event=event).aggregate(Avg("rating"))
1✔
116
    avg_rating = avg_rating_result["rating__avg"]
1✔
117

1✔
118
    if avg_rating is not None:
1✔
119
        avg_rating = round(avg_rating, 2)
1✔
120
        event.avg_rating = avg_rating
121
        event.save()
122
    else:
123
        event.avg_rating = avg_rating
1✔
124
        event.save()
×
125

×
126
    return render(
×
127
        request,
128
        "event_detail.html",
129
        {
130
            "event_id": event_id,
1✔
131
            "event": event,
1✔
132
            "loggedIn": loggedIn,
133
            "interested": interested,
134
            "avg_rating": avg_rating,
135
            "room_slug": room_slug,
136
        },
1✔
137
    )
1✔
138

139

140
def user_detail(request, username):
141
    User = get_user_model()
1✔
142
    user = get_object_or_404(User, username=username)
143
    return render(request, "user_detail.html", {"detail_user": user})
144

145

146
@login_required
147
def interest_list(request):
1✔
148
    User = get_user_model()
149
    interestList = []
150
    if request.user.id:
1✔
151
        interestList = UserEvent.objects.filter(
1✔
152
            user=User.objects.get(pk=request.user.id),
1✔
153
        )
1✔
154
    interestEventIds = [userEvent.event_id for userEvent in interestList]
155
    interestEvents = Event.objects.filter(id__in=interestEventIds)
156
    return render(request, "interest_list.html", {"interestEvents": interestEvents})
1✔
157

1✔
158

1✔
159
def search_results(request):
1✔
160
    search_query = request.GET.get("search_events", "").strip()
1✔
161
    search_type = request.GET.get("search_type", "Shows")
162
    sort_by = request.GET.get("sort_by", "")
163
    User = get_user_model()
1✔
164

1✔
165
    availability_filter = request.GET.get("availability", "All")
1✔
166
    now = timezone.now()
167

168
    if search_query:
1✔
169
        events = Event.objects.filter(title__icontains=search_query)
170
    else:
171
        events = Event.objects.all()
172

173
    users = User.objects.none()
174

175
    if search_query:
176
        if request.user.is_authenticated:
177
            SearchHistory.objects.create(
178
                user=request.user, search=search_query, search_type=search_type
179
            )
1✔
180
        if search_type == "Shows":
1✔
181
            if availability_filter != "All":
1✔
182
                if availability_filter == "Past":
1✔
183
                    events = events.filter(close_date__isnull=False, close_date__lt=now)
184
                elif availability_filter == "Current":
185
                    events = events.filter(
1✔
186
                        Q(open_date__lte=now, close_date__gte=now)
1✔
187
                        | Q(open_date__lte=now, close_date__isnull=True)
1✔
188
                    )
1✔
189
            elif availability_filter == "Upcoming":
190
                events = events.filter(open_date__gt=now)
1✔
191
        elif search_type == "Users":
192
            users = User.objects.filter(
1✔
193
                Q(username__icontains=search_query) | Q(email__icontains=search_query)
1✔
194
            )
1✔
195

1✔
196
    if sort_by == "Average Rating":
1✔
197
        events = events.annotate(
198
            adjusted_avg_rating=Coalesce(
199
                Avg("reviews__rating"), Value(0), output_field=FloatField()
200
            )
1✔
201
        ).order_by("-adjusted_avg_rating")
1✔
202
    elif sort_by == "Popularity":
203
        events = events.annotate(review_count=Count("reviews")).order_by(
1✔
204
            "-review_count"
1✔
205
        )
206

207
    context = {
208
        "events": events if search_type == "Shows" else None,
209
        "users": users if search_type == "Users" else None,
1✔
210
        "search_query": search_query,
1✔
211
        "search_type": search_type,
212
    }
213
    return render(request, "search_results.html", context)
214

1✔
215

216
def search_history(request):
217
    user = request.user
218
    search_history = SearchHistory.objects.filter(user=user).order_by("-timestamp")
219
    return render(request, "search_history.html", {"search_history": search_history})
220

221

222
def delete_search_view(request, search_id):
1✔
223
    search = SearchHistory.objects.get(id=search_id)
1✔
224
    if search.user == request.user:
1✔
225
        search.delete()
1✔
226
    return redirect("search_history")
1✔
227

×
228

×
229
def clear_history_view(request):
230
    SearchHistory.objects.filter(user=request.user).delete()
1✔
231
    return redirect("search_history")
×
232

×
233

234
def recent_searches(request):
×
235
    if request.user.is_authenticated:
236
        recent_searches = SearchHistory.objects.filter(user=request.user).order_by(
237
            "-timestamp"
238
        )[
×
239
            :5
240
        ]  # Get the last 5 searches
1✔
241
        searches = [search.search for search in recent_searches]
242
        return JsonResponse({"recent_searches": searches})
1✔
243
    return JsonResponse({"recent_searches": []})
244

245

246
def events_by_category(request, category):
1✔
247
    categories = EVENT_CATEGORIES
1✔
248
    availability_filter = request.GET.get("availability", "All")
1✔
249
    now = timezone.now()
250
    sort_by = request.GET.get("sort_by", "")
251

252
    events = Event.objects.filter(category__icontains=category)
253

254
    if availability_filter != "All":
255
        if availability_filter == "Past":
256
            events = events.filter(close_date__isnull=False, close_date__lt=now)
257
        elif availability_filter == "Current":
258
            events = events.filter(
1✔
259
                Q(open_date__lte=now, close_date__gte=now)
1✔
260
                | Q(open_date__lte=now, close_date__isnull=True)
1✔
261
            )
262
        elif availability_filter == "Upcoming":
263
            events = events.filter(open_date__gt=now)
264

265
    if sort_by == "Average Rating":
266
        events = events.annotate(
×
267
            adjusted_avg_rating=Coalesce(
268
                Avg("reviews__rating"), Value(0), output_field=FloatField()
269
            )
270
        ).order_by("-adjusted_avg_rating")
271
    elif sort_by == "Popularity":
272
        events = events.annotate(review_count=Count("reviews")).order_by(
273
            "-review_count"
1✔
274
        )
1✔
275

1✔
276
    return render(
1✔
277
        request,
1✔
278
        "events_by_category.html",
1✔
279
        {"events": events, "categories": categories, "current_category": category},
1✔
280
    )
1✔
281

1✔
282

283
# This code snippet is called once the verification link is accessed by the user, to confirm the validity of the link.
284
def activate(request, uidb64, token):
×
285
    User = get_user_model()
×
286
    try:
287
        uid = force_str(urlsafe_base64_decode(uidb64))
288
        user = User.objects.get(pk=uid)
×
289
    except Exception:
290
        user = None
291

×
292
    if user is not None and account_activation_token.check_token(user, token):
293
        user.is_active = True
294
        user.save()
295

296
        messages.success(
297
            request,
1✔
298
            "Thank you for your email confirmation. Now you can login your account.",
1✔
299
        )
1✔
300
        return redirect("login")
1✔
301
    else:
1✔
302
        messages.error(request, "Activation link is invalid!")
1✔
303

1✔
304
    return redirect("login")
1✔
305

1✔
306

×
307
# This code snippet is responsible for generating and sending the verification email.
308
def activateEmail(request, user, to_email):
1✔
309
    mail_subject = "Activate your user account"
310
    message = render_to_string(
1✔
311
        "template_activate_account.html",
312
        {
1✔
313
            "user": user.username,
1✔
314
            "domain": get_current_site(request).domain,
315
            "uid": urlsafe_base64_encode(force_bytes(user.pk)),
1✔
316
            "token": account_activation_token.make_token(user),
317
            "protocol": "https" if request.is_secure() else "http",
318
        },
1✔
319
    )
×
320
    email = EmailMessage(mail_subject, message, to=[to_email])
×
321
    if email.send():
×
322
        messages.success(
323
            request,
324
            f"Dear {user}, please go to you email {to_email} inbox and click on \
1✔
NEW
325
                received activation link to confirm and complete the registration. Note: Check your spam folder.",
×
326
        )
327
    else:
328
        messages.error(
329
            request,
330
            f"Problem sending email to {to_email}, check if you typed it correctly.",
331
        )
332

333

334
# Register new user
335
def register_user(request):
336
    if request.method == "POST":
337
        form = UserRegistrationForm(request.POST)
338
        if form.is_valid():
339
            user = form.save(commit=False)
340
            user.is_active = False
341
            user.save()
342
            activateEmail(request, user, form.cleaned_data.get("email"))
343
            return redirect("login")
344

345
        else:
346
            for error in list(form.errors.values()):
347
                messages.error(request, error)
348

349
    else:
350
        form = UserRegistrationForm()
351
        #    form = {}
352

353
    return render(
354
        request=request, template_name="register.html", context={"form": form}
355
    )
356

357

358
# Delete current user
359
@login_required
360
@require_POST
361
def delete_user(request):
362
    User = get_user_model()
363
    user = User.objects.filter(id=request.user.id).first()
364
    if user:
365
        user.delete()
366
    return JsonResponse({"message": "account has been deleted"})
367

368

369
# Login existing user
370
def login_user(request):
371
    if request.method == "POST":
372
        username = request.POST["username"]
373
        password = request.POST["password"]
374
        remember_me = request.POST.get("remember_me")
375

376
        try:
377
            user = User.objects.get(username=username)
378
        except User.DoesNotExist:
379
            user = None
380

381
        if user:
382
            if user.check_password(password):
383
                # Check if the user is banned
384
                try:
385
                    BannedUser.objects.get(user=user)
386
                    messages.error(request, "Your account has been banned.")
387
                    return redirect("login")
388
                except BannedUser.DoesNotExist:
389
                    pass
390

391
                if user.is_active:
392
                    login(request, user)
393
                    if remember_me:
394
                        request.session.set_expiry(604800)
395
                    else:
396
                        request.session.set_expiry(0)
397
                    return redirect("index")
398
                else:
399
                    messages.error(
400
                        request,
401
                        "Account is not authenticated. Check your email and authenticate before logging in.",
402
                    )
403
                    return redirect("login")
404
            else:
405
                messages.error(request, "Invalid username or password.")
406
                return redirect("login")
407
        else:
408
            messages.error(request, "Invalid username or password.")
409
            return redirect("login")
410
    else:
411
        return render(request, "authenticate/login.html", {})
412

413

414
def logout_user(request):
415
    logout(request)
416
    messages.success(request, "You have been successfully logged out.")
417
    return redirect("login")
418

419

420
def import_rooms(request):
421
    event_titles = Event.objects.values_list("title", flat=True)
422

423
    pattern = r"[^a-zA-Z0-9\s]"
424

425
    for title in event_titles:
426
        cleaned_title = re.sub(pattern, "", title)
427

428
        title_split = cleaned_title.split()
429

430
        room_name = ""
431

432
        if len(title_split) >= 3:
433
            room_name = "_".join(title_split[:3])
434
        else:
435
            room_name = "_".join(title_split[:])
436

437
        Room3.objects.create(name=title, slug=room_name.lower())
438

439

440
def not_found_page(request):
441
    return render(request, "404.html")
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

© 2025 Coveralls, Inc