From 707d389a971ad2660f7c2e3ee9cd823dcaab09b5 Mon Sep 17 00:00:00 2001 From: ryaningham2001 <ryaningham2001@gmail.com> Date: Thu, 5 Jan 2023 03:46:09 +0000 Subject: [PATCH] TODO sort elevate user --- UWEFlix/__pycache__/admin.cpython-310.pyc | Bin 281 -> 350 bytes UWEFlix/__pycache__/forms.cpython-310.pyc | Bin 3876 -> 3784 bytes UWEFlix/__pycache__/models.cpython-310.pyc | Bin 3883 -> 3909 bytes UWEFlix/__pycache__/urls.cpython-310.pyc | Bin 1249 -> 1296 bytes UWEFlix/__pycache__/views.cpython-310.pyc | Bin 4510 -> 5606 bytes UWEFlix/admin.py | 5 +- UWEFlix/forms.py | 3 +- UWEFlix/migrations/0006_film_genre.py | 19 +++ .../0006_film_genre.cpython-310.pyc | Bin 0 -> 672 bytes UWEFlix/models.py | 1 + UWEFlix/templates/base.html | 2 +- UWEFlix/templates/create_account.html | 1 + UWEFlix/templates/create_club.html | 1 + UWEFlix/templates/create_film.html | 29 ++++ UWEFlix/templates/create_screen.html | 1 + UWEFlix/templates/create_showing.html | 14 +- UWEFlix/templates/elevate_user.html | 2 +- UWEFlix/templates/login.html | 15 +- UWEFlix/templates/manage_screens.html | 2 +- UWEFlix/urls.py | 3 +- UWEFlix/views.py | 154 +++++++++++------- db.sqlite3 | Bin 270336 -> 270336 bytes 22 files changed, 169 insertions(+), 83 deletions(-) create mode 100644 UWEFlix/migrations/0006_film_genre.py create mode 100644 UWEFlix/migrations/__pycache__/0006_film_genre.cpython-310.pyc create mode 100644 UWEFlix/templates/create_film.html diff --git a/UWEFlix/__pycache__/admin.cpython-310.pyc b/UWEFlix/__pycache__/admin.cpython-310.pyc index fde77289443a35787c1ec96aa13a138cea227276..a4b3473f0bd376f1dd049c6e831f50c99cd2a0c2 100644 GIT binary patch delta 148 zcmbQqbdQNQpO=@50SNeAwk0o{$ScceGErMnESDvUC6_gdHJ2@ljgcXhF^hcxM=Hxi zKRH{LTfEMhd8xUHzKMB>>8VAxSVD_|B%fn)a(-!E2~1STIj1x!D7By{wKz4eB(Ws3 mEY(kwb7H*`PZ2B7wjwqV!9H=G7#lZ;#XWIXG>ZhI022TN-6@a& delta 97 zcmcb|G?R%ppO=@50SKHbHYc}F<dtRAn5Zqu#mJD#n8mVyHI;c{l$<c*Ener$ywu!8 z-^9Gc^wc6hO}2?!l_YPm6la#C-r^`qP0uVYNiAB*P{aW=sfc6Z|7aE-Mge931os=L diff --git a/UWEFlix/__pycache__/forms.cpython-310.pyc b/UWEFlix/__pycache__/forms.cpython-310.pyc index 275baa96faeb71ab99df915e7e209e5d3e4c682e..dc1fb7161809d003f928da322212e998b12f95ff 100644 GIT binary patch delta 545 zcmYjOJx>Bb5M_ir_Bapa<UkGRK@>Cr3qPZx;X|dfq11%JLM?=3i17~?8#|}5voW!; zp)qzu6B9dQ>re0xSlBqTA;C-L-Q3=rx9{!VPrav|w&O$s{8-heqnoaC8KknUs2B98 zVaI4QY|(G<HW_6`$7E1}5GcSjxBECvpP@`7q?g?x%+QOK(&Jg<5#sb=%#Gyv=NK3I z0(oY{Y0`XvIeInoFhSqu7fjMy_|z*fVVtYKO$uDVf>vy*9^|NNryxrutK=<-)Uv>a zfb5T(6jSNsDz{Ty9mSvmE^Dx_RaQBKHNAJq7^Q0D9OmgcGV7IORN~`6b6b?WEnduV z_1$QlE$yak7h#=Rc9Jt(*>zaZIV;R9ijXf*5oQ8cxSuz^?8Zs^;<R<V*Typ(*f<zI zh7}Gp<D>Rr$>hMtj(iRa?CNYaZWp=!X9KMDJt=BB*RY|z)S0y|gT6qWveCO~xd)UZ fMmZytcqpDxWSR3BO43i%cfzjWnyzyBoe2K{iP2~~ delta 623 zcmYjOJ#5oZ5cad5o#(_R!o;+Jh6J@GI71LZltK%wR3%Xdq>924u~@YUMol8lsgT$Z zU7<oZB9(<13SwhmgKjKLkq}Hw3=HgWXAtE{_vwD#eeb(_`<3S>+@b5{H99}{-)y{n z<!&2m=_v|htt%p}tH;J28Hq@LB)Voti;PHaYmt1Ycdf`=*8*!?x{=0kE$$`h2*Ob^ z9JGhfzaEIOg81%M0&#>djMt)wp)Bb^4u2@$&A0ktve{1J%?PIPtX;t!X)BAKRhlDk zSAG&c?zpFq1e7X~L5+c<jVFi8_`%#24ZLO5#W8$rjm2?Ha*5xha+xgsLo_8k0Zshk zOrfFPi8}5%lV*kL)A&^_`sc}mIfg|B$#9vqOw5y8B})~7(mdkvbePYW9@xwBBBk-8 zJc-}zEs}9FKkHwi6!041fOeV5{3S}($^MGUsFsLo2EXTL%L`Nq<o)7GGKl*jZ?1VY z9)-}rMxi6l@DAJ+y2GPoJHXFQb@Bptnd8Fx?cu#-(Bn4vC+b(BC+29vnHprOY;HYJ z)#lJ)=w!pT$UR5)|F8mDr0}I!;P;EGRK3IvHHKAu?>?*YPe3M$mjyf|uufn)y0hm@ T;L}4jS9zvqdCJRq=F!}5F*1ZU diff --git a/UWEFlix/__pycache__/models.cpython-310.pyc b/UWEFlix/__pycache__/models.cpython-310.pyc index a41f30d68ea2a1f14da1ee576341ac60c928efea..defe40172299e2850e833e0d99ec35f01db44b82 100644 GIT binary patch delta 153 zcmZ22cT|oypO=@50SF4rwk7Ls<Xy|f=rDOVm$5-Aa~4|)YYIy*V-!ycTQGwr`z;o? z%$(eiB1NF;B6|>_0wR=wgr6qwWP2{<$p+jW>`|=gsd+`IlMk|pPVVLA6ygEOb1?8Q v@-T7$p#Wo%<KzMsk;%KbpEAa6Uce*3$e1#DBkyX)+{v+gCt2Br*u*#in&u-U delta 114 zcmX>qw_1)jpO=@50SLaH*pke!k#{W@qsioZ+|rYIxws}j;NoLTVGU-`WShh-#_Xrb zGufU?d9ow7$K-=7qGFCfUEx4n4ARfRz{AMH$ic`nc`x@L#@Nlfcmx<3lP90%UCo#? Oxt#ALE1M9T7$*Qw<{JqB diff --git a/UWEFlix/__pycache__/urls.cpython-310.pyc b/UWEFlix/__pycache__/urls.cpython-310.pyc index 831c5e6fe67abe40bd2bf1cdd9b0b1ed1b36f08c..9be615b1473ef52ab0e6e3911aed19c7263ffd7d 100644 GIT binary patch delta 161 zcmaFJIe|+jpO=@50SHt~w<UYCGB7*_agc!skmCTv#XO7?b$&>sGNve{GG_^=D5tRZ zGN%hfiKM6mGia)A)?@t3$f!P9hgn@OiZ8h+HL)Z$zBnVlJTou7iU-P1%go8ukK#t+ g`Duzy&S$>I7R3#co9xC?$fz-S2a7rjA0x*H0MQ>P&Hw-a delta 120 zcmbQh^^j91pO=@50SLaH*pe*7%E0g##6bqaK#l_t7yo0JsPls>oj*!AMJbp;Q+cxu z<6lNbgUMFR>M}N&c_mf_*>?I-e91+ri6yD=#TohKnR)4cnj(|?neR=mV##7uoBWhT Ior&Wk05BXL-~a#s diff --git a/UWEFlix/__pycache__/views.cpython-310.pyc b/UWEFlix/__pycache__/views.cpython-310.pyc index 22f97ee8ed23183ed1148c30672854e1470f049d..1820bc410e1e1dbd187c9f86cc8f2bdb00d88969 100644 GIT binary patch literal 5606 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 literal 4510 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 diff --git a/UWEFlix/admin.py b/UWEFlix/admin.py index d1649fe0..2377a132 100644 --- a/UWEFlix/admin.py +++ b/UWEFlix/admin.py @@ -1,5 +1,4 @@ from django.contrib import admin -from .models import CinemaManager +from .models import CinemaManager, User, AccountManager, ClubRepresentative # Register your models here. - -admin.site.register(CinemaManager) \ No newline at end of file +admin.site.register(User) \ No newline at end of file diff --git a/UWEFlix/forms.py b/UWEFlix/forms.py index 9098fc90..8166a8b1 100644 --- a/UWEFlix/forms.py +++ b/UWEFlix/forms.py @@ -10,8 +10,7 @@ class AccountForm(forms.ModelForm): class UserRegistrationForm(UserCreationForm): - email = forms.EmailField(required=True) - + class Meta: model = User fields = ("email", "username", "password1", "password2") diff --git a/UWEFlix/migrations/0006_film_genre.py b/UWEFlix/migrations/0006_film_genre.py new file mode 100644 index 00000000..116f2b6d --- /dev/null +++ b/UWEFlix/migrations/0006_film_genre.py @@ -0,0 +1,19 @@ +# Generated by Django 4.1.4 on 2023-01-05 01:22 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('UWEFlix', '0005_alter_cinema_id_alter_film_id_alter_screen_id_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='film', + name='genre', + field=models.CharField(default='', max_length=50), + preserve_default=False, + ), + ] diff --git a/UWEFlix/migrations/__pycache__/0006_film_genre.cpython-310.pyc b/UWEFlix/migrations/__pycache__/0006_film_genre.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6dee78a0d15c091fa4d44690c60ecf7762af4dd5 GIT binary patch literal 672 zcmYjP&2H2%5VoCUH;G!Q2ShpcRB12O0)hh|RMhPv4)j0;6;UM1WM;Ej5@&I;r9H#7 z55f!ZFuua2uYi!s*j==>G$VhSpKs=~+wJX?(fPdpv-r&!`{lsh6B0Ni>-Nb3175R+ zXS@-a;OsR60l{|$0rExgEyw~0PuVECrd&1>Hf^fXsJ?1-X9rCSSa*dB-91ABhh*KD z9I}i9%LMR}X90$b$PwURF@z8z7+eV$LVOicG=_wzQk%T}&q0L4_h-k`y1K}okH_OD zQq?^gSyUPuB`a9tSyeY1)D;F%d#ph=tw9^Q3>%fG39#!&G??oRI8&>-r>)e5tWlT! zd^!pVy2Yec4OMy{%_^+H?ko*<XwFftD^Es=jit|&(x#HwU{xdCx1{{CQnjmg2ylrS zP!|<;Mi9M?Uja;AR}(mx9L<&S*rx3g*Bbv|W|yMg{rNC?mcP4Hdhd-c=c>skZLw-l z_g(%GmDzioPmWI~`O(?KeDxJ)q*=b!F5f&_PAWc?UN0}k!Sd3$4>2I??vaa`2*R5% z5?t^tvhZ(w<1<c3m;@F|m+b+3@;ms+eQ-17?d<_|vhj;sHD1y$WSwK#5%+_CsOh@H literal 0 HcmV?d00001 diff --git a/UWEFlix/models.py b/UWEFlix/models.py index 02682500..2394c805 100644 --- a/UWEFlix/models.py +++ b/UWEFlix/models.py @@ -89,6 +89,7 @@ class Film(models.Model): title = models.CharField(max_length=255) length = models.PositiveIntegerField() rating = models.PositiveSmallIntegerField() + genre = models.CharField(max_length=50) class Screen(models.Model): id = models.AutoField(primary_key=True) diff --git a/UWEFlix/templates/base.html b/UWEFlix/templates/base.html index bf31cc42..a177bee7 100644 --- a/UWEFlix/templates/base.html +++ b/UWEFlix/templates/base.html @@ -30,7 +30,7 @@ <li class="nav-item"> <a class="nav-link" href="#">View Tickets</a> </li> - {% if request.user.is_authenticated %} + {% if user.is_authenticated %} <li class="nav-item"> <a class = "nav-link" href="{% url 'view_details' %}">View My Details</a> </li> diff --git a/UWEFlix/templates/create_account.html b/UWEFlix/templates/create_account.html index 1eb83c0f..3645ec90 100644 --- a/UWEFlix/templates/create_account.html +++ b/UWEFlix/templates/create_account.html @@ -27,6 +27,7 @@ <input type="number" class="form-control" id="discountRate" name="discountRate" placeholder="Discount Rate"> </div> <button type="submit" class="btn btn-primary">Create Account</button> + </form> </div> {% endblock %} diff --git a/UWEFlix/templates/create_club.html b/UWEFlix/templates/create_club.html index c7db43e9..155363bb 100644 --- a/UWEFlix/templates/create_club.html +++ b/UWEFlix/templates/create_club.html @@ -27,6 +27,7 @@ <textarea class="form-control" id="contact_details" name="contact_details" rows="3"></textarea> </div> <button type="submit" class="btn btn-primary">Create Club</button> + </form> </div> diff --git a/UWEFlix/templates/create_film.html b/UWEFlix/templates/create_film.html new file mode 100644 index 00000000..8a35efdb --- /dev/null +++ b/UWEFlix/templates/create_film.html @@ -0,0 +1,29 @@ +{% extends 'base.html' %} + +{% block content %} + +<div class="container mt-4"> + <h1>Create Film</h1> + <form method="post" action="{% url 'create_film' %}" class="form"> + {% csrf_token %} + <div class="form-group"> + <label for="title">Title</label> + <input type="text" class="form-control" id="title" name="title" required> + </div> + <div class="form-group"> + <label for="length">Length (in minutes)</label> + <input type="number" class="form-control" id="length" name="length" required> + </div> + <div class="form-group"> + <label for="rating">Rating (out of 10)</label> + <input type="number" class="form-control" id="rating" name="rating" required> + </div> + <div class="form-group"> + <label for="genre">Genre</label> + <input type="text" class="form-control" id="genre" name="genre" required> + </div> + <button type="submit" class="btn btn-primary">Create Film</button> + <a href="{% url 'create_showing' %}" class="btn btn-secondary" onClick="javascript:history.go(-1);">Return</a> + </form> +</div> +{% endblock %} \ No newline at end of file diff --git a/UWEFlix/templates/create_screen.html b/UWEFlix/templates/create_screen.html index 5b1097ce..b4ac2f6c 100644 --- a/UWEFlix/templates/create_screen.html +++ b/UWEFlix/templates/create_screen.html @@ -23,6 +23,7 @@ </select> </div> <button type="submit" class="btn btn-primary">Create Screen</button> + </form> </div> diff --git a/UWEFlix/templates/create_showing.html b/UWEFlix/templates/create_showing.html index afea2eab..95807e6b 100644 --- a/UWEFlix/templates/create_showing.html +++ b/UWEFlix/templates/create_showing.html @@ -4,7 +4,7 @@ <div class="container mt-4"> <h1>Create Showing</h1> - <form method="post" action="{% url 'create_showing' screen.pk %}"> + <form method="post" action="{% url 'create_showing' %}"> {% csrf_token %} <div class="form-group"> <label for="film">Film</label> @@ -16,15 +16,21 @@ </div> <div class="form-group"> <label for="screen">Screen</label> - <select class="form-control" id="screen" name="screen"> - <option value="{{ screen.id }}">{{ screen.cinema.name }} - Screen {{ screen.screen_number }}</option> + <select class="form-control" id="screen" name="screen" disabled> + {% for screen in screens %} + <option value="{{ screen.id }}">{{ screen.cinema.name }} - Screen {{ screen.screen_number }}</option> + {% endfor %} </select> </div> <div class="form-group"> <label for="start_time">Start Time</label> <input type="datetime-local" class="form-control" id="start_time" name="start_time" required> </div> - <button type="submit" class="btn btn-primary">Create Showing</button> + <div class="form-group"> + <button type="submit" class="btn btn-primary mr-2">Create Showing</button> + <a href="{% url 'create_film' %}" class="btn btn-secondary">Create Film</a> + </div> + </form> </div> {% endblock %} \ No newline at end of file diff --git a/UWEFlix/templates/elevate_user.html b/UWEFlix/templates/elevate_user.html index 2ccd0c30..876340d1 100644 --- a/UWEFlix/templates/elevate_user.html +++ b/UWEFlix/templates/elevate_user.html @@ -10,7 +10,7 @@ <label for="user">User</label> <select class="form-control" id="user" name="user" required> {% for user in users %} - <option value="{{ user.id }}">{{ user.first_name }} {{ user.last_name }}</option> + <option value="{{ user.id }}">{{ user.username }}</option> {% endfor %} </select> </div> diff --git a/UWEFlix/templates/login.html b/UWEFlix/templates/login.html index ec43fbb3..fb7893a3 100644 --- a/UWEFlix/templates/login.html +++ b/UWEFlix/templates/login.html @@ -8,14 +8,13 @@ <div class="col-md-6 offset-md-3"> <form class="form-signin" method="post" action="{% url 'login' %}"> {% csrf_token %} - <h1 class="h3 mb-3 font-weight-normal">Please sign in</h1> - <div class="form-group"> - <label for="inputEmail" class="sr-only">Email address</label> - <input type="email" id="inputEmail" class="form-control" placeholder="Email address" required autofocus> - </div> - <div class="form-group"> - <label for="inputPassword" class="sr-only">Password</label> - <input type="password" id="inputPassword" class="form-control" placeholder="Password" required> + <div class="form-group"> + <label for="inputUsername">Username</label> + <input type="text" class="form-control" id="inputUsername" name="inputUsername" required> + </div> + <div class="form-group"> + <label for="inputPassword">Password</label> + <input type="password" class="form-control" id="inputPassword" name="inputPassword" required> </div> <div class="form-group form-check"> <input type="checkbox" class="form-check-input" id="rememberMe" value="remember-me"> diff --git a/UWEFlix/templates/manage_screens.html b/UWEFlix/templates/manage_screens.html index b7e3032e..9c8199b5 100644 --- a/UWEFlix/templates/manage_screens.html +++ b/UWEFlix/templates/manage_screens.html @@ -13,7 +13,7 @@ <p class="card-text">Seating Capacity: {{ screen.seating_capacity }}</p> <a href="{% url 'update_screen' pk=screen.pk %}" class="btn btn-primary">Update</a> <a href="{% url 'delete_screen' pk=screen.pk %}" class="btn btn-danger">Delete</a> - <a href="{% url 'create_showing' pk=screen.pk %}" class="btn btn-success mt-2">Create Showing</a> + <a href="{% url 'create_showing' pk=screen.pk origin=0 %}" class="btn btn-success mt-2">Create Showing</a> {% if screen.showings %} <h6 class="mt-3">Showings:</h6> <ul> diff --git a/UWEFlix/urls.py b/UWEFlix/urls.py index e3389e0c..818e444c 100644 --- a/UWEFlix/urls.py +++ b/UWEFlix/urls.py @@ -18,5 +18,6 @@ urlpatterns = [ path('manage_screens/update_screen/<int:pk>/', views.screen_update, name='update_screen'), path('manage_screens/delete_screen/<int:pk>/', views.screen_delete, name='delete_screen'), path('manage_screens/screen_list/', views.screen_list, name='screen_list'), - path('manage_screens/showings/create_showing/<int:pk>/', views.showing_create, name='create_showing') + path('manage_screens/showings/create_showing/', views.showing_create, name='create_showing'), + path('create_film/', views.film_create, name='create_film') ] diff --git a/UWEFlix/views.py b/UWEFlix/views.py index bbda8a29..ee3acbe9 100644 --- a/UWEFlix/views.py +++ b/UWEFlix/views.py @@ -1,10 +1,11 @@ from django.shortcuts import render, redirect, HttpResponseRedirect, get_object_or_404 +from django.contrib import messages from django.contrib.auth import authenticate, login, logout from django.contrib.auth.decorators import login_required -from .forms import AccountForm, UserRegistrationForm, ClubForm, RepresentativeRegistrationForm, ElevateUserForm, ScreenForm, ShowingForm +from .forms import AccountForm, UserRegistrationForm, ClubForm, RepresentativeRegistrationForm, ElevateUserForm, ScreenForm, ShowingForm, FilmForm from .models import Account, User, ClubRepresentative, Club, Screen, Cinema, Film, Showing from django.http import JsonResponse - +from django.contrib.auth.models import AbstractUser, Group, Permission # Create your views here. @@ -13,6 +14,8 @@ def index_view(request): def login_view(request): + + ### IF USER HAS SUBMITTED FORM ### if request.method == "POST": # Validate the form data username = request.POST.get('inputUsername') @@ -24,15 +27,35 @@ def login_view(request): else: error_message = "Invalid username or password" context = {'error_message': error_message} + print(error_message) return render(request, 'login.html', context) else: # Display the login form - context = {} + context = {'user': request.user} return render(request, 'login.html', context) + + ### IF THE USER HAS REQUESTED THE FORM return render(request, 'login.html', {}) +def register_view(request): + if request.method == "POST": + form = UserRegistrationForm(request.POST) + if form.is_valid(): + user = form.save(commit=True) + email = form.cleaned_data['email'] + password = form.cleaned_data['password1'] + login(request, user) + messages.success(request, "Registration Successful") + return redirect('/index/') + else: + print(form.errors) + form = UserRegistrationForm() + return render(request, 'register.html', {'form': form}) + + def create_account(request): + ### USER SUBMITS FORM ### if request.method == 'POST': # code to handle form submission and create a new account form = AccountForm(request.POST) @@ -41,25 +64,14 @@ def create_account(request): return redirect('/index/') else: # render the form with errors - return render(request, 'create_account.html', {'form': form}) + context = {'form': form, 'user': request.user} + return render(request, 'create_account.html', context) else: + ### USER REQUESTS FORM ### # render the empty form form = AccountForm() - return render(request, 'create_account.html', {'form': form}) - -def register_view(request): - if request.method == "POST": - form = UserRegistrationForm(request.POST) - if form.is_valid(): - form.save(commit=True) - email = form.cleaned_data['email'] - password = form.cleaned_data['password1'] - user = authenticate(request, email=email, password=password) - login(request, user) - return redirect('/index/') - else: - form = UserRegistrationForm() - return render(request, 'register.html', {'form': form}) + context = {'form': form, 'user': request.user} + return render(request, 'create_account.html', context) def create_club(request): @@ -69,9 +81,9 @@ def create_club(request): club = form.save(commit=True) #return redirect('club_detail', pk=club.pk) return redirect('/index/') - else: - form = ClubForm() - return render(request, 'create_club.html', {'form': form}) + form = ClubForm() + context = {'form': form, 'user': request.user} + return render(request, 'create_club.html', context) def representative_registration(request): @@ -81,9 +93,10 @@ def representative_registration(request): if form.is_valid(): form.save(commit=True) return redirect('login') - else: - form = RepresentativeRegistrationForm() - return render(request, 'representative_registration.html', {'form': form, 'clubs': clubs}) + + form = RepresentativeRegistrationForm() + context = {'form': form, 'user': request.user, 'clubs': clubs} + return render(request, 'representative_registration.html', context) def elevate_user_view(request): @@ -91,11 +104,28 @@ def elevate_user_view(request): form = ElevateUserForm(request.POST) if form.is_valid(): # Form is valid, process the data and return a response - # ... + user_id = form.cleaned_data['user'] + user = User.objects.get(id=user_id) + role = form.cleaned_data['role'] + + if role == 'account_manager': + group, created = Group.objects.get_or_create(name='Account Manager') + user.groups.add(group) + elif role == 'cinema_manager': + group, created = Group.objects.get_or_create(name='Cinema Manager') + user.groups.add(group) + else: + # Handle invalid role selection + pass + + # Save changes to the user instance + user.save() + return redirect('index') - else: - form = ElevateUserForm() - return render(request, 'elevate_user.html', {'form': form}) + + form = ElevateUserForm() + context = {'form': form, 'user': request.user, 'users': User.objects.all()} + return render(request, 'elevate_user.html', context) def view_my_details(request): @@ -110,28 +140,11 @@ def view_my_details(request): def screen_list(request): screens = Screen.objects.all() showings = Showing.objects.all() - return render(request, 'manage_screens.html', {'screens': screens, 'showings': showings}) + context = {'user': request.user, 'screens': screens, 'showings': showings} + return render(request, 'manage_screens.html', context) def screen_create(request): - # if request.method == 'POST': - # form = ScreenForm(request.POST) - # if form.is_valid(): - # # Check if the user is a cinema manager - # if request.user.groups.filter(name='Cinema Manager').exists(): - # # Check if the cinema the user manages matches the cinema associated with the screen - # if request.user.cinema == form.cleaned_data['cinema']: - # form.save() - # return redirect('manage_screens') - # else: - # # Return an error message or redirect the user to a different page - # pass - # else: - # # Return an error message or redirect the user to a different page - # pass - # else: - # form = ScreenForm() - # return render(request, 'create_screen.html', {'form': form}) - + cinemas = Cinema.objects.all() if request.method == 'POST': form = ScreenForm(request.POST) if form.is_valid(): @@ -140,10 +153,11 @@ def screen_create(request): # Check if the cinema the user manages matches the cinema associated with the screen #if request.user.cinema == form.cleaned_data['cinema']: form.save() - return redirect('manage_screens') - else: - form = ScreenForm() - return render(request, 'create_screen.html', {'form': form, 'cinemas': Cinema.objects.all()}) + form = ScreenForm() + + form = ScreenForm() + context = {'form': form, 'user': request.user, 'cinemas': Cinema.objects.all()} + return render(request, 'create_screen.html', {'form': form, 'cinemas': cinemas}) def screen_update(request, pk): screen = get_object_or_404(Screen, pk=pk) @@ -152,22 +166,38 @@ def screen_update(request, pk): if form.is_valid(): form.save() return redirect('screen_list') - else: - form = ScreenForm(instance=screen) - return render(request, 'update_screen.html', {'form': form, 'screen': screen}) + + form = ScreenForm(instance=screen) + context = {'form': form, 'user': request.user, 'screen': screen} + return render(request, 'update_screen.html', context) def screen_delete(request, pk): screen = get_object_or_404(Screen, pk=pk) screen.delete() return redirect('screen_list') -def showing_create(request, pk): - screen = get_object_or_404(Screen, pk=pk) +def showing_create(request): + films = Film.objects.all() + screens = Screen.objects.all() if request.method == 'POST': form = ShowingForm(request.POST) if form.is_valid(): form.save() - return redirect('manage_screens') - else: - form = ShowingForm() - return render(request, 'create_showing.html', {'form': form, 'films': Film.objects.all(), 'screen': screen}) \ No newline at end of file + form = ShowingForm() + + form = ShowingForm() + context = {'form': form, 'user': request.user, 'films': films, 'screens': screens} + return render(request, 'create_showing.html', context) + +def film_create(request, pk=None): + success = False + if request.method == 'POST': + form = FilmForm(request.POST) + if form.is_valid(): + form.save() + form = FilmForm() + + form = FilmForm() + context = {'form': form, 'user': request.user, 'pk': pk} + return render(request, 'create_film.html', context) + \ No newline at end of file diff --git a/db.sqlite3 b/db.sqlite3 index c98ac66b7484603760582aaa93f735be51a04626..8ec1ce490ae91f42862f2fd18ff2c333fec58a2c 100644 GIT binary patch delta 2591 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 delta 868 zcmZWnT}V@582;Y#opZJ`bMM(Q*EV%i7_^MdFuMpeZ51I!CWIk`E*dt_DQebTVs#}! za)?0}As7W+<njcEexS{}E&?yKVkn`R6(uVp>_=GdS>8l&-sgeme9!wm-}`;TX>~ZQ zUiUg8jIje$4OBoiG`6c2A`d!mBX=no&7y|&-TqNU&$t`qN*ray_74(%#69=~hp-uM z;wx;&dsu1TK>DRSIy3ePTIRMoOL?{RWZR*`-SLYZ1Lt}##1mau!UI+f!bgB>&EY12 zG3{EoTtt-zwEN)`;F_utTT~fm8UDmI{DjLmkF&a?FO7R;S!4h_Bugd>6_O}21<E9D zl2;N;@<?EkyVyL8J<IG_3N&Nav$uAF6>y%>XQOsAsLxOCsIhU(F#L?Om?2Teu!D0J zjKmYMo~Zv=G!gBJ^_L2q)keC{pYgZG`ubx7vBY3>Fg_G>0%zKnTnVL}WB3cdQJ;6X zfOFI-gZnKa6v7sm!pfooP$m}0%M0WYBoY<3jl#;f$Z!MK>CmhA9v7*}3#^qm^^i@Z zrCb5g1a5-BxuX0vE-?I!-!Vs*@)j4!_#CTD3k`~}LNc*TG||gV^avsc#mM_W8m0l{ zHtl3w#AI#~wvo8D8HU7VG}fMhQzbRT=+gT!L^JhcGV}&sk~qyM@pR$X4>9cILHKum z+{NiV{Xaj!$*UFZYi_FyxWsUYwt9`mQXZ;QQlbo_q_kl&>JuhNSZBDdJ5sBttzUBJ z*3=K*R9aLg#FSqbQyacJ<3f6idFxDN3|CksnX_oD^zxcUd(jO(Zf&sDTP7_YTS#wG zd$=*C^9FiI3=+oCaiJBqlT~pAgK%}^>}iW@q=TTY4z5Iv`p5hf*hb`biz^U-%g2-c kN4(s4`h*`W8EYw$>dCl|lI76Ihe1&9f*<?_sA3-f09Hxh;s5{u -- GitLab