From 93eccbf08d958f568fe86fa3aecf4a5fea2fb80c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=27=D1=8F=D0=BD=D0=B0=20=D0=A2=D0=B8?= =?UTF-8?q?=D1=85=D0=B0?= Date: Sat, 28 Dec 2024 19:18:14 +0200 Subject: [PATCH 1/2] Taxi Service User Form and Validation --- taxi/forms.py | 20 +++++++++++++ taxi/models.py | 1 + taxi/urls.py | 18 ++++++++++++ taxi/views.py | 40 ++++++++++++++++++++++++-- taxi_service/forms.py | 14 +++++++++ taxi_service/settings.py | 1 + templates/taxi/car_confirm_delete.html | 2 +- templates/taxi/car_detail.html | 16 +++++++++-- templates/taxi/car_form.html | 4 +-- templates/taxi/driver_detail.html | 12 +++++++- templates/taxi/driver_list.html | 6 ++-- 11 files changed, 124 insertions(+), 10 deletions(-) create mode 100644 taxi/forms.py create mode 100644 taxi_service/forms.py diff --git a/taxi/forms.py b/taxi/forms.py new file mode 100644 index 000000000..bde2da1e4 --- /dev/null +++ b/taxi/forms.py @@ -0,0 +1,20 @@ +from django import forms +from .models import Driver, Car + + +class DriverCreationForm(forms.ModelForm): + class Meta: + model = Driver + fields = ["username", "first_name", "last_name", "license_number"] + + +class DriverLicenseUpdateForm(forms.ModelForm): + class Meta: + model = Driver + fields = ["license_number"] + + +class CarCreationForm(forms.ModelForm): + class Meta: + model = Car + fields = ["model", "manufacturer", "drivers"] diff --git a/taxi/models.py b/taxi/models.py index 769fd7002..eef3be887 100644 --- a/taxi/models.py +++ b/taxi/models.py @@ -29,6 +29,7 @@ def get_absolute_url(self): class Car(models.Model): + objects = None model = models.CharField(max_length=255) manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) drivers = models.ManyToManyField(Driver, related_name="cars") diff --git a/taxi/urls.py b/taxi/urls.py index 4f017a999..2f29b1f50 100644 --- a/taxi/urls.py +++ b/taxi/urls.py @@ -8,11 +8,16 @@ CarUpdateView, CarDeleteView, DriverListView, + DriverCreateView, + DriverLicenseUpdateView, + DriverDeleteView, DriverDetailView, ManufacturerListView, ManufacturerCreateView, ManufacturerUpdateView, ManufacturerDeleteView, + assign_me_car, + delete_me_car, ) urlpatterns = [ @@ -46,6 +51,19 @@ path( "drivers//", DriverDetailView.as_view(), name="driver-detail" ), + path("drivers/create/", DriverCreateView.as_view(), name="driver-create"), + path( + "drivers//delete/", + DriverDeleteView.as_view(), + name="driver-delete" + ), + path( + "drivers//driver-update/", + DriverLicenseUpdateView.as_view(), + name="driver-update" + ), + path("assign-me-car//", assign_me_car, name="assign-me-car"), + path("delete-me-car//", delete_me_car, name="delete-me-car"), ] app_name = "taxi" diff --git a/taxi/views.py b/taxi/views.py index 0789d616e..94aca136d 100644 --- a/taxi/views.py +++ b/taxi/views.py @@ -1,9 +1,10 @@ from django.contrib.auth.decorators import login_required -from django.shortcuts import render +from django.shortcuts import render, redirect, get_object_or_404 from django.urls import reverse_lazy from django.views import generic from django.contrib.auth.mixins import LoginRequiredMixin +from .forms import DriverCreationForm, DriverLicenseUpdateForm, CarCreationForm from .models import Driver, Car, Manufacturer @@ -64,7 +65,7 @@ class CarDetailView(LoginRequiredMixin, generic.DetailView): class CarCreateView(LoginRequiredMixin, generic.CreateView): model = Car - fields = "__all__" + form_class = CarCreationForm success_url = reverse_lazy("taxi:car-list") @@ -87,3 +88,38 @@ class DriverListView(LoginRequiredMixin, generic.ListView): class DriverDetailView(LoginRequiredMixin, generic.DetailView): model = Driver queryset = Driver.objects.all().prefetch_related("cars__manufacturer") + + +class DriverCreateView(LoginRequiredMixin, generic.CreateView): + model = Driver + form_class = DriverCreationForm + + +class DriverDeleteView(LoginRequiredMixin, generic.DeleteView): + model = Driver + success_url = reverse_lazy("taxi:driver-list") + + +class DriverLicenseUpdateView(LoginRequiredMixin, generic.UpdateView): + model = Driver + form_class = DriverLicenseUpdateForm + + +@login_required +def assign_me_car(request, pk): + if request.method == "POST": + driver = get_object_or_404(Driver, pk=request.user.id) + car = get_object_or_404(Car, pk=pk) + car.drivers.add(driver) + + return redirect("taxi:car-detail", pk=pk) + + +@login_required +def delete_me_car(request, pk): + if request.method == "POST": + driver = get_object_or_404(Driver, pk=request.user.id) + car = get_object_or_404(Car, pk=pk) + car.drivers.remove(driver) + + return redirect("taxi:car-detail", pk=pk) diff --git a/taxi_service/forms.py b/taxi_service/forms.py new file mode 100644 index 000000000..b4d8cbb37 --- /dev/null +++ b/taxi_service/forms.py @@ -0,0 +1,14 @@ +from django import forms +from django.contrib.auth import get_user_model +from django.contrib.auth.forms import UserCreationForm +from django.core.exceptions import ValidationError +from django.core.validators import MinLengthValidator, MaxLengthValidator + +from taxi.models import Driver, Car + + +class LicenseNumberValidatorMixin: + license_number = forms.CharField( + required=True, + validators=[MinLengthValidator(8), MaxLengthValidator(8)] + ) diff --git a/taxi_service/settings.py b/taxi_service/settings.py index 8f98f33e6..d6784f9a6 100644 --- a/taxi_service/settings.py +++ b/taxi_service/settings.py @@ -44,6 +44,7 @@ "django.contrib.staticfiles", "debug_toolbar", "crispy_forms", + "crispy_bootstrap4", "taxi", ] diff --git a/templates/taxi/car_confirm_delete.html b/templates/taxi/car_confirm_delete.html index 7b28981b1..ed996b50d 100644 --- a/templates/taxi/car_confirm_delete.html +++ b/templates/taxi/car_confirm_delete.html @@ -7,4 +7,4 @@

Delete car?

-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/taxi/car_detail.html b/templates/taxi/car_detail.html index 78197443a..dc2825fe1 100644 --- a/templates/taxi/car_detail.html +++ b/templates/taxi/car_detail.html @@ -12,11 +12,23 @@

Manufacturer: ({{ car.manufacturer.name }}, {{ car.manufacturer.country }})

-

Drivers

+

Drivers + {% if user in car.drivers.all %} + + {% else %} + + {% endif %} +


    {% for driver in car.drivers.all %} -
  • {{ driver.username }} ({{ driver.first_name }} {{ driver.last_name }})
  • +
  • {{ driver.username }} ({{ driver.first_name }} {{ driver.last_name }})
  • {% endfor %}
{% endblock %} diff --git a/templates/taxi/car_form.html b/templates/taxi/car_form.html index 08287665c..8d833f4a7 100644 --- a/templates/taxi/car_form.html +++ b/templates/taxi/car_form.html @@ -2,11 +2,11 @@ {% load crispy_forms_filters %} {% block content %} -

{{ object|yesno:"Update,Create" }} car

+

Create driver

{% csrf_token %} {{ form|crispy }}
-{% endblock %} \ No newline at end of file +{% endblock %} diff --git a/templates/taxi/driver_detail.html b/templates/taxi/driver_detail.html index 788084648..3f7681a2b 100644 --- a/templates/taxi/driver_detail.html +++ b/templates/taxi/driver_detail.html @@ -7,7 +7,9 @@

First name: {{ driver.first_name }}

Last name: {{ driver.last_name }}

-

License number: {{ driver.license_number }}

+

+ License number: {{ driver.license_number }} +

Is staff: {{ driver.is_staff }}

@@ -23,4 +25,12 @@

Cars

No cars!

{% endfor %}
+ {% endblock %} diff --git a/templates/taxi/driver_list.html b/templates/taxi/driver_list.html index b740f95ea..09687d0d6 100644 --- a/templates/taxi/driver_list.html +++ b/templates/taxi/driver_list.html @@ -2,6 +2,9 @@ {% block content %}

Driver List + + Create +

{% if driver_list %} @@ -22,8 +25,7 @@

Driver List {{ driver.license_number }} {% endfor %} - - + {% else %}

There are no drivers in the service.

{% endif %} From 4c6992797c22fbbd1e48615da0f1cb90d9f3e54f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9C=D0=B0=D1=80=27=D1=8F=D0=BD=D0=B0=20=D0=A2=D0=B8?= =?UTF-8?q?=D1=85=D0=B0?= Date: Sun, 29 Dec 2024 12:07:35 +0200 Subject: [PATCH 2/2] Fixed Car template title --- taxi/models.py | 1 - taxi_service/settings.py | 2 -- templates/taxi/car_form.html | 5 +---- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/taxi/models.py b/taxi/models.py index eef3be887..769fd7002 100644 --- a/taxi/models.py +++ b/taxi/models.py @@ -29,7 +29,6 @@ def get_absolute_url(self): class Car(models.Model): - objects = None model = models.CharField(max_length=255) manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) drivers = models.ManyToManyField(Driver, related_name="cars") diff --git a/taxi_service/settings.py b/taxi_service/settings.py index d6784f9a6..f9fde6055 100644 --- a/taxi_service/settings.py +++ b/taxi_service/settings.py @@ -42,7 +42,6 @@ "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", - "debug_toolbar", "crispy_forms", "crispy_bootstrap4", "taxi", @@ -50,7 +49,6 @@ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", - "debug_toolbar.middleware.DebugToolbarMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", diff --git a/templates/taxi/car_form.html b/templates/taxi/car_form.html index 8d833f4a7..4bb6f32a1 100644 --- a/templates/taxi/car_form.html +++ b/templates/taxi/car_form.html @@ -1,8 +1,5 @@ -{% extends "base.html" %} -{% load crispy_forms_filters %} - {% block content %} -

Create driver

+

{{ object|default_if_none:"Create Car" }}

{% csrf_token %} {{ form|crispy }}