From 2b219e54275ceebc5aa89e62b65074b47b739835 Mon Sep 17 00:00:00 2001 From: Wilfrido Araujo Date: Wed, 20 Dec 2023 14:31:14 -0500 Subject: [PATCH 1/3] Added about and contact page --- server/db.sqlite3 | Bin 0 -> 131072 bytes .../djangoapp/templates/djangoapp/about.html | 46 +++++++++ .../templates/djangoapp/contact.html | 88 ++++++++++++++++++ .../templates/djangoapp/custom_template.html | 63 +++++++++++++ .../djangoapp/templates/djangoapp/index.html | 22 ++++- server/djangoapp/urls.py | 3 + server/djangoapp/views.py | 13 ++- server/requirements.txt | 2 +- 8 files changed, 233 insertions(+), 4 deletions(-) create mode 100644 server/db.sqlite3 create mode 100644 server/djangoapp/templates/djangoapp/about.html create mode 100644 server/djangoapp/templates/djangoapp/contact.html create mode 100644 server/djangoapp/templates/djangoapp/custom_template.html diff --git a/server/db.sqlite3 b/server/db.sqlite3 new file mode 100644 index 0000000000000000000000000000000000000000..9f3d34fc200498194b7df0804cbd79d0e955d6ac GIT binary patch literal 131072 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 + + + + Dealership Review + + + + + + + + + + + + + + + +

+ Welcome to Best Cars dealership, home to the best cars in North America. We sell domestic and imported cars at reasonable prices. +

+ + + + diff --git a/server/djangoapp/templates/djangoapp/contact.html b/server/djangoapp/templates/djangoapp/contact.html new file mode 100644 index 0000000000..1fd7147881 --- /dev/null +++ b/server/djangoapp/templates/djangoapp/contact.html @@ -0,0 +1,88 @@ + + + + + Dealership Review + + + + + + + + + + + + + + + +
+
+
+
+ image +

Contact Us

+

We would love to hear from you !

+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+ + + + + diff --git a/server/djangoapp/templates/djangoapp/custom_template.html b/server/djangoapp/templates/djangoapp/custom_template.html new file mode 100644 index 0000000000..926edfad10 --- /dev/null +++ b/server/djangoapp/templates/djangoapp/custom_template.html @@ -0,0 +1,63 @@ + + + + + Dealership Review + + + + + + + + + + + + + + + +
+
+
+
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ Go somewhere +
+
+
+
+
+
+
Special title treatment
+

With supporting text below as a natural lead-in to additional content.

+ Go somewhere +
+
+
+
+ + + + diff --git a/server/djangoapp/templates/djangoapp/index.html b/server/djangoapp/templates/djangoapp/index.html index 1a9ee6e39a..8a6c512737 100644 --- a/server/djangoapp/templates/djangoapp/index.html +++ b/server/djangoapp/templates/djangoapp/index.html @@ -14,9 +14,27 @@ - - This is the index page of your Django app! + diff --git a/server/djangoapp/urls.py b/server/djangoapp/urls.py index 37b1c89d01..536f9c3ee0 100644 --- a/server/djangoapp/urls.py +++ b/server/djangoapp/urls.py @@ -10,8 +10,10 @@ # name the URL # path for about view + path(route='about', view=views.about, name='about'), # path for contact us view + path(route='contact', view=views.contact, name='contact'), # path for registration @@ -24,5 +26,6 @@ # path for dealer reviews view # path for add a review view + path(route='profile', view=views.custom_profile, name='profile'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) \ No newline at end of file diff --git a/server/djangoapp/views.py b/server/djangoapp/views.py index 61cc664da0..c0eb7585a8 100644 --- a/server/djangoapp/views.py +++ b/server/djangoapp/views.py @@ -15,15 +15,26 @@ # Create your views here. - +def custom_profile(request): + context = {} + if request.method == "GET": + return render(request, 'djangoapp/custom_template.html', context) # Create an `about` view to render a static about page # def about(request): # ... +def about(request): + context = {} + if request.method == "GET": + return render(request, 'djangoapp/about.html', context) # Create a `contact` view to return a static contact page #def contact(request): +def contact(request): + context = {} + if request.method == "GET": + return render(request, 'djangoapp/contact.html', context) # Create a `login_request` view to handle sign in request # def login_request(request): diff --git a/server/requirements.txt b/server/requirements.txt index 2851cca128..a3e766f47a 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -1,6 +1,6 @@ requests Django==3.1.3 -Pillow==8.0.1 +Pillow==10.1.0 gunicorn==20.1.0 ibm-cloud-sdk-core==3.10.0 ibm-watson==5.2.2 From c21cf56bd8f571037808dbe3d3f933a17904c50c Mon Sep 17 00:00:00 2001 From: Wilfrido Araujo Date: Wed, 20 Dec 2023 16:07:27 -0500 Subject: [PATCH 2/3] Added login, logout and sigup methods --- server/db.sqlite3 | Bin 131072 -> 131072 bytes .../djangoapp/templates/djangoapp/about.html | 43 +++++- .../templates/djangoapp/contact.html | 133 ++++++++++++------ .../templates/djangoapp/custom_template.html | 43 +++++- .../templates/djangoapp/dealer_details.html | 61 ++++++++ .../djangoapp/templates/djangoapp/index.html | 43 +++++- .../templates/djangoapp/registration.html | 101 +++++++++++++ .../templates/djangoapp/user_login.html | 119 ++++++++++++++++ server/djangoapp/urls.py | 3 + server/djangoapp/views.py | 58 +++++++- 10 files changed, 557 insertions(+), 47 deletions(-) create mode 100644 server/djangoapp/templates/djangoapp/user_login.html diff --git a/server/db.sqlite3 b/server/db.sqlite3 index 9f3d34fc200498194b7df0804cbd79d0e955d6ac..68dd8fae138b42477febb8760751f7b482b85600 100644 GIT binary patch delta 1103 zcmaiyJ8aul6oyGEDI^2Z?K2+S)J~%YC<@B=UWzXPE7 zy+Puu57Q)Goc*}@{tv`kU_yYu!EfL(n1HXq&tSTkpMh^D+wlhkLA<-XD<>KYZIb%f zbL!)fJ*3uehZyp^dk*>D^{?9qhN;+70yJY!7xTxl+59dQCFY+>;q~=sI3j(}H_ojF zu8$lYvs@e_4ni0|&lRirlhYGio|fb3kysMSsswwsuDG9_>V}?9%Gs)VEI3#(Z7t`O zjv-2qeRT&z%+Lta7;a&df;h!;37+Rff%oi@hbs1LSzp)0A(j)dwv<1=L%tLk*@#9X z5h?mwfw16BPh7oNP}@TM!fCfEay7eep>c6|VW|Fo*5cc2#dfnn$vIKCHIeO0$^Nde zlfSV%nPP=Ra%q}ne0`{o-QG$A5>rW>LSlj!F@oIMGI9z$C%|*?&-FWJe}X%a&^r0j z7_}DKi2OewdQJ92Z?91?i-`Rmv!b6b<~T}`4;J%}$(cvpk^{*$5igF<%`PiUO)tQ> zgPM$M3@mXXu!iW_3{0V6p2_u69f8J~wlVGItLXwf7pBlQI8MrE`(0eto3%r6P;GTM zEVRv~@+1ur4Vf(rQw)>BFd;w@v*_V{^0xeiCgB;|;GmQ227xFJY}PgGks(eo=EVLG zvB*!@#p$stj}*TpsfP_Z=N)A;K}jAn4buoDU)Ed=mTaa(D|NjuO)RE+pfqZo0!Bj@ zbvs3ETC4WVO5Y0hJHNQgJUD-!~Us1 z&Wzf_I=%s;hhEQN^ZTuIBfO@sLcui5hi3BuDTY5`OVJ{@r}|?3ZWct*tc*JR!he;0gF?x$ApC aZeB?nJ0FE4az)||mek#l6j^z`;ov_Wy)-@m delta 126 zcmZo@;Am*zm>|t4JyFJ)QF>#-B6*P&3~c;m4E!(ouki2YFXQj#pT%FXu`z*va+$u0 z8V?_{JV#<_Nk)8WacU6*1A{OSBLi_(W@E + + + diff --git a/server/djangoapp/templates/djangoapp/contact.html b/server/djangoapp/templates/djangoapp/contact.html index 1fd7147881..268af6e3f6 100644 --- a/server/djangoapp/templates/djangoapp/contact.html +++ b/server/djangoapp/templates/djangoapp/contact.html @@ -31,57 +31,108 @@ + + + -
+
-
-
- image -

Contact Us

-

We would love to hear from you !

-
-
-
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
- -
- -
-
-
-
- -
+
+
+ +
+
+
+
+ image +

Contact Us

+

We would love to hear from you !

+
+
+
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+ +
-
- +
diff --git a/server/djangoapp/templates/djangoapp/custom_template.html b/server/djangoapp/templates/djangoapp/custom_template.html index 926edfad10..9e64f279ae 100644 --- a/server/djangoapp/templates/djangoapp/custom_template.html +++ b/server/djangoapp/templates/djangoapp/custom_template.html @@ -31,7 +31,48 @@ + + +
diff --git a/server/djangoapp/templates/djangoapp/dealer_details.html b/server/djangoapp/templates/djangoapp/dealer_details.html index 25bd9a223d..6be3523825 100644 --- a/server/djangoapp/templates/djangoapp/dealer_details.html +++ b/server/djangoapp/templates/djangoapp/dealer_details.html @@ -10,6 +10,67 @@ + diff --git a/server/djangoapp/templates/djangoapp/index.html b/server/djangoapp/templates/djangoapp/index.html index 8a6c512737..7ada791ed7 100644 --- a/server/djangoapp/templates/djangoapp/index.html +++ b/server/djangoapp/templates/djangoapp/index.html @@ -31,7 +31,48 @@ + + +
diff --git a/server/djangoapp/templates/djangoapp/registration.html b/server/djangoapp/templates/djangoapp/registration.html index ae11ea4b71..e9e9306cfe 100644 --- a/server/djangoapp/templates/djangoapp/registration.html +++ b/server/djangoapp/templates/djangoapp/registration.html @@ -4,8 +4,109 @@ {% load static %} + + + + + + + + +
+
+
+
+ +
+ {% csrf_token %} +

Sign Up

+

Please fill in this form to create an account!

+
+
+
+
+
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+ +
+
+
+ \ No newline at end of file diff --git a/server/djangoapp/templates/djangoapp/user_login.html b/server/djangoapp/templates/djangoapp/user_login.html new file mode 100644 index 0000000000..f877965710 --- /dev/null +++ b/server/djangoapp/templates/djangoapp/user_login.html @@ -0,0 +1,119 @@ + + + + + Dealership Review + + + + + + + + + + + + + + +
+
+
+

Login Form

+
Made with bootstrap
+
+ +
+ + {% csrf_token %} +
+ profile +
+ +
+ +
+
+ +
+
+ +
+ {% if message %} +
+ {{ message }} +
+ {% endif %} +
+
+ +
+
+
+ + + + diff --git a/server/djangoapp/urls.py b/server/djangoapp/urls.py index 536f9c3ee0..05c4a3cf0f 100644 --- a/server/djangoapp/urls.py +++ b/server/djangoapp/urls.py @@ -16,10 +16,13 @@ path(route='contact', view=views.contact, name='contact'), # path for registration + path('registration/', views.registration_request, name='registration'), # path for login + path('login/', views.login_request, name='login'), # path for logout + path('logout/', views.logout_request, name='logout'), path(route='', view=views.get_dealerships, name='index'), diff --git a/server/djangoapp/views.py b/server/djangoapp/views.py index c0eb7585a8..a704fb1e93 100644 --- a/server/djangoapp/views.py +++ b/server/djangoapp/views.py @@ -38,15 +38,67 @@ def contact(request): # Create a `login_request` view to handle sign in request # def login_request(request): -# ... +def login_request(request): + context = {} + # Handles POST request + if request.method == "POST": + # Get username and password from request.POST dictionary + username = request.POST['username'] + password = request.POST['psw'] + # Try to check if provide credential can be authenticated + user = authenticate(username=username, password=password) + if user is not None: + # If user is valid, call login method to login current user + login(request, user) + return redirect('djangoapp:index') + else: + # If not, return to login page again + return render(request, 'djangoapp/user_login.html', context) + else: + return render(request, 'djangoapp/user_login.html', context) # Create a `logout_request` view to handle sign out request # def logout_request(request): -# ... +def logout_request(request): + # Get the user object based on session id in request + print("Log out the user `{}`".format(request.user.username)) + # Logout user in the request + logout(request) + # Redirect user back to course list view + return redirect('djangoapp:index') # Create a `registration_request` view to handle sign up request # def registration_request(request): -# ... +def registration_request(request): + context = {} + # If it is a GET request, just render the registration page + if request.method == 'GET': + return render(request, 'djangoapp/registration.html', context) + # If it is a POST request + elif request.method == 'POST': + # Get user information from request.POST + username = request.POST['username'] + password = request.POST['psw'] + first_name = request.POST['firstname'] + last_name = request.POST['lastname'] + user_exist = False + try: + # Check if user already exists + User.objects.get(username=username) + user_exist = True + except: + # If not, simply log this is a new user + logger.debug("{} is new user".format(username)) + # If it is a new user + if not user_exist: + # Create user in auth_user table + user = User.objects.create_user(username=username, first_name=first_name, last_name=last_name, + password=password) + # Login the user and redirect to course list page + login(request, user) + return redirect("djangoapp:index") + else: + return render(request, 'djangoapp/registration.html', context) # Update the `get_dealerships` view to render the index page with a list of dealerships def get_dealerships(request): From fc0c652a954cb3ec2ec4c81cb5e0e7dd1e5f24d0 Mon Sep 17 00:00:00 2001 From: Wilfrido Araujo Date: Thu, 21 Dec 2023 16:54:24 -0500 Subject: [PATCH 3/3] new models --- server/db.sqlite3 | Bin 131072 -> 131072 bytes server/djangoapp/models.py | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/server/db.sqlite3 b/server/db.sqlite3 index 68dd8fae138b42477febb8760751f7b482b85600..3d1c9c07a6955ed5774729658ae8c4983d3884d2 100644 GIT binary patch delta 1315 zcmaizPfXK%7{~jgC2g4H8Lwc%#NIhuOTtfqj}$W^kU+#U4|Q&czF(=-zQJLZNAUS z3bV4p-1nn_^_D?2U|&7ng*a=i>oj7lf4cZa2Brx3AO409@D`rH4VZ#8+dKu4BUC7W zl(f7stI4{al5<&2Q8P>v74lbOd0wThwE+XKnk3*q_!s_yH}Du%ArF(bIRud=h9W|N z1G^e&jQv#@@3L0UFOeL3%c3s`-g=h(#(rjZ*thHpcAdRtn{jseFooI?Q*$FN!OL!%>1I%BgL{gtLE{m^JB$SUpg}_CeKOg#id*_ zJJh2H{B&|w?3HIEqmUXmR8hK8NG8t8`Qb#AkBSjqi11=LN^fT@CQ30eUqg)=3G4L+ zXRSUOKSsI{L@lrA@u;GuyS2>1Otu(H=`p>qC`mc3Tb>b}2oqz)D}6ner3-Q6%*8@( z!dMudja}E%nep5;RZu51J)b>wT|8YhM$Q!zgR=)Ch@DbzRO}V%V3!~vOTYuj!j^4L z!*ClpihlPWC`bBTQqtPm2vY<>w5^-mvu*FoZOTh>Fl5m?f)_NHgA`1{1dPE54B6)Q zdcKxKh~eBBa%a$;0cX-J?)1CU=g#KM8z1j|B{@&qLwW}Z-a{u3HF~~y-g};U3Z4;9 zn{DpaEr+>U0<{a(T^*DcIHzeGE-&XERYwSGC*u3->xiZPRj9#|TG2q~EFHCkeyXj3 zW$cE#s+#VIxTqCYiz`)izd9lAbGsi)9kG4aus@$8`buIcOTT+y81IjV(a~mXwni$i zrYaj&wyy4?r-xbigj;f#fOqg5?%L)}NCwFSI#{c6v#DP{ms>|V&(`)MUu_MpM{qsi F`vGGpfZzZC delta 445 zcmZo@;Am*zm>|t)G*QNx(P(3WmOi7zR5~$=&vqK#48}{d}G|kK)!z8b=($cap)if(9wK&PL!pO+XvY^P&)UbSV+T5+- zMj@tFrn*7?QOTi^##uhaIWA>Rg=xVl$(cpv0Y!zS{w1Lq231C;zL90=?jDgw21X{j z28Ox@#tMd(RwhPPrj~l9M&@Sb7F-Mr3{3pn8Tjw;Z|9%1S+Jm;pHX#UqvGW4>s3{h znSD74IcL)b76oPr{?f_p7l6TF%fGqwe*Xt%37&-M>=zh;A{so~6YelB6y^n6beMtv l5&vQSB|wX2@-xa$bd+Y1V|HYmd|;lGJd-T5BPVW`0sx Create a Car Model model `class CarModel(models.Model):`: @@ -19,6 +26,31 @@ # - Year (DateField) # - Any other fields you would like to include in car model # - __str__ method to print a car make object +class CarModel(models.Model): + SEDAN = 'Sedan' + SUV = 'SUV' + WAGON = 'WAGON' + TYPE_CHOICES = [ + (SEDAN, 'Sedan'), + (SUV, 'SUV'), + (WAGON, 'WAGON') + ] + dealer_id = models.IntegerField() + name = models.CharField(null=False, max_length=100, default='name') + description = models.CharField(max_length=500) + type = models.CharField( + null=False, + max_length=20, + choices=TYPE_CHOICES, + default=SEDAN + ) + year = models.IntegerField() + carMade = models.ManyToManyField(CarMake) + + # Create a toString method for object string representation + def __str__(self): + return "Name: " + self.name + "," + \ + "Description: " + self.type # Create a plain Python class `CarDealer` to hold dealer data