Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Solution #826

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions taxi/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# forms.py
from django import forms
from .models import Driver, Car
import re


class DriverLicenseUpdateForm(forms.ModelForm):
class Meta:
model = Driver
fields = ["license_number"]

def clean_license_number(self):
license_number = self.cleaned_data["license_number"]
if not re.match(r"^[A-Z]{3}\d{5}$", license_number):
raise forms.ValidationError(
"License number must consist of exactly 8 characters: "
"the first 3 uppercase letters, followed by 5 digits."
)
return license_number


class CarForm(forms.ModelForm):
class Meta:
model = Car
fields = ["model", "manufacturer", "drivers"]
widgets = {
"drivers": forms.CheckboxSelectMultiple(),
}
18 changes: 18 additions & 0 deletions taxi/migrations/0002_alter_driver_license_number.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.1 on 2024-12-19 19:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('taxi', '0001_initial'),
]

operations = [
migrations.AlterField(
model_name='driver',
name='license_number',
field=models.CharField(max_length=8, unique=True),
),
]
13 changes: 11 additions & 2 deletions taxi/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import re

from django.core.exceptions import ValidationError
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.contrib.auth.models import AbstractUser, User
from django.urls import reverse


Expand All @@ -15,7 +18,13 @@ def __str__(self):


class Driver(AbstractUser):
license_number = models.CharField(max_length=255, unique=True)
license_number = models.CharField(max_length=8, unique=True)

def clean_number(self):
if not re.match(r"^[A-Z]{3}\d{5}$", self.license_number):
raise ValidationError(
"License number must consist of 3 "
"uppercase letters followed by 5 digits.")
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
Comment on lines +23 to +27

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method clean_number should be renamed to clean_license_number to ensure it is automatically called during the model's full_clean process. This is crucial for proper validation of the license_number field.


class Meta:
verbose_name = "driver"
Expand Down
10 changes: 10 additions & 0 deletions taxi/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
ManufacturerCreateView,
ManufacturerUpdateView,
ManufacturerDeleteView,
DriverCreateView,
DriverDeleteView,
DriverLicenseUpdateView,
toggle_driver,
)

urlpatterns = [
Expand Down Expand Up @@ -46,6 +50,12 @@
path(
"drivers/<int:pk>/", DriverDetailView.as_view(), name="driver-detail"
),
path("drivers/create/", DriverCreateView.as_view(), name="driver-create"),
path("drivers/<int:pk>/delete/",
DriverDeleteView.as_view(), name="driver-delete"),
path("drivers/<int:pk>/update-license/",
DriverLicenseUpdateView.as_view(), name="driver-update-license"),
path("cars/<int:pk>/toggle-driver/", toggle_driver, name="toggle-driver"),
]

app_name = "taxi"
38 changes: 36 additions & 2 deletions taxi/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse_lazy
from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import UpdateView

from .forms import DriverLicenseUpdateForm, CarForm
from .models import Driver, Car, Manufacturer


Expand Down Expand Up @@ -62,9 +64,20 @@ class CarDetailView(LoginRequiredMixin, generic.DetailView):
model = Car


@login_required
def toggle_driver(request, pk):
car = get_object_or_404(Car, pk=pk)
if request.user in car.drivers.all():
car.drivers.remove(request.user)
else:
car.drivers.add(request.user)
return redirect("taxi:car-detail", pk=pk)


class CarCreateView(LoginRequiredMixin, generic.CreateView):
model = Car
fields = "__all__"
form_class = CarForm
template_name = "car_form.html"
success_url = reverse_lazy("taxi:car-list")


Expand All @@ -87,3 +100,24 @@ 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
fields = "__all__"
success_url = reverse_lazy("taxi:driver-list")
template_name = "driver_form.html"


class DriverDeleteView(LoginRequiredMixin, generic.DeleteView):
model = Driver
fields = "__all__"
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fields attribute is not applicable for a DeleteView. It should be removed to avoid confusion and potential errors.

template_name = "driver_confirm_delete.html"
success_url = reverse_lazy("driver-list")


class DriverLicenseUpdateView(UpdateView):
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
model = Driver
form_class = DriverLicenseUpdateForm
template_name = "driver_license_update.html"
success_url = reverse_lazy("taxi:driver-list")
1 change: 1 addition & 0 deletions taxi_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"debug_toolbar",
"crispy_forms",
"taxi",
"crispy_bootstrap4",
]

MIDDLEWARE = [
Expand Down
11 changes: 11 additions & 0 deletions templates/car_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "base.html" %}

{% block content %}
<h1>Create Car</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Create Car</button>
</form>
<a href="{% url "taxi:car-list" %}" class="btn btn-secondary">Back to Car List</a>
{% endblock %}
11 changes: 11 additions & 0 deletions templates/driver_confirm_delete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "base.html" %}

{% block content %}
<h1>Delete Driver</h1>
<p>Are you sure you want to delete "{{ object }}"?</p>
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Yes, Delete</button>
<a href="{% url "taxi:driver-list" %}" class="btn btn-secondary">Cancel</a>
</form>
{% endblock %}
26 changes: 26 additions & 0 deletions templates/driver_form.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{% extends "base.html" %}
{% load crispy_forms_tags %}

{% block content %}
<h1>Driver List</h1>
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
<a href="{% url "taxi:driver-create" %}" class="btn btn-primary">Create Driver</a>
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
<table>
<tr>
<th>Username</th>
<th>First name</th>
<th>Last name</th>
<th>License number</th>
</tr>
{% for driver in drivers %}
<tr>
<td>{{ driver.username }}</td>
<td>{{ driver.first_name }}</td>
<td>{{ driver.last_name }}</td>
<td>{{ driver.license_number }}</td>
<td>
<a href="{% url "taxi:driver-delete" driver.pk %}" class="btn btn-danger">Delete</a>
</td>
</tr>
{% endfor %}
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
</table>
{% endblock %}
11 changes: 11 additions & 0 deletions templates/driver_license_update.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "base.html" %}

{% block content %}
<h1>Update Driver's License</h1>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-success">Update License</button>
<a href="{% url "taxi:driver-list" %}" class="btn btn-secondary">Back to Driver List</a>
</form>
{% endblock %}
39 changes: 25 additions & 14 deletions templates/taxi/car_detail.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
{% extends "base.html" %}

{% block content %}
<h1>
{{ car.model }}
<a href="{% url 'taxi:car-delete' pk=car.id %}" class="btn btn-danger link-to-page">
Delete
</a>

<a href="{% url 'taxi:car-update' pk=car.id %}" class="btn btn-secondary link-to-page">
Update
</a>
</h1>
<p>Manufacturer: ({{ car.manufacturer.name }}, {{ car.manufacturer.country }})</p>
<h1>Model: {{ car.model }}</h1>
<p><b>Manufacturer: </b>({{ car.manufacturer.name }}, {{ car.manufacturer.country }})</p>
<div>
{% if user in car.drivers.all %}
yablonskyiv marked this conversation as resolved.
Show resolved Hide resolved
<form action="{% url "taxi:toggle-driver" car.id %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-danger">Delete me from this car</button>
</form>
{% else %}
<form action="{% url "taxi:toggle-driver" car.id %}" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-primary">Assign me to this car</button>
</form>
{% endif %}
</div>
<h1>Drivers</h1>
<hr>
<ul>

{% for driver in car.drivers.all %}
<li>{{ driver.username }} ({{ driver.first_name }} {{ driver.last_name }})</li>
<p><b>Username: </b>{{ driver.username }}</p>
<p><b>Full name: </b>({{ driver.first_name }} {{ driver.last_name }})</p>
<p><b>License number: </b>{{ driver.license_number }}</p>
<hr>
{% endfor %}
</ul>

<div class="d-flex justify-content-start">
<a href="{% url "taxi:car-delete" pk=car.id %}" class="btn btn-danger link-to-page">Delete</a>
<a href="{% url "taxi:car-update" pk=car.id %}" class="btn btn-secondary link-to-page">Update</a>
</div>
{% endblock %}
2 changes: 2 additions & 0 deletions templates/taxi/driver_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@ <h4>Cars</h4>
{% empty %}
<p>No cars!</p>
{% endfor %}
<a href="{% url "taxi:driver-update-license" driver.pk %}" class="btn btn-primary">Update License</a>
<a href="{% url "taxi:driver-delete" driver.pk %}" class="btn btn-danger">Delete Driver</a>
</div>
{% endblock %}
Loading