diff --git a/taxi/admin.py b/taxi/admin.py index 08448baa..2893830c 100644 --- a/taxi/admin.py +++ b/taxi/admin.py @@ -27,6 +27,7 @@ class DriverAdmin(UserAdmin): @admin.register(Car) class CarAdmin(admin.ModelAdmin): + list_display = ["model", "manufacturer", ] search_fields = ("model",) list_filter = ("manufacturer",) diff --git a/taxi/migrations/0001_initial.py b/taxi/migrations/0001_squashed_0001_initial.py similarity index 90% rename from taxi/migrations/0001_initial.py rename to taxi/migrations/0001_squashed_0001_initial.py index ff29293e..4be0ab05 100644 --- a/taxi/migrations/0001_initial.py +++ b/taxi/migrations/0001_squashed_0001_initial.py @@ -1,63 +1,65 @@ -# Generated by Django 4.0.2 on 2022-03-24 06:38 - -from django.conf import settings -import django.contrib.auth.models -import django.contrib.auth.validators -from django.db import migrations, models -import django.db.models.deletion -import django.utils.timezone - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), - ] - - operations = [ - migrations.CreateModel( - name='Driver', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('password', models.CharField(max_length=128, verbose_name='password')), - ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), - ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), - ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), - ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), - ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), - ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), - ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), - ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), - ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), - ('license_number', models.CharField(max_length=255)), - ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), - ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), - ], - options={ - 'verbose_name': 'driver', - 'verbose_name_plural': 'drivers', - }, - managers=[ - ('objects', django.contrib.auth.models.UserManager()), - ], - ), - migrations.CreateModel( - name='Manufacturer', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=255)), - ('country', models.CharField(max_length=255)), - ], - ), - migrations.CreateModel( - name='Car', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('model', models.CharField(max_length=255)), - ('drivers', models.ManyToManyField(related_name='cars', to=settings.AUTH_USER_MODEL)), - ('manufacturer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='taxi.manufacturer')), - ], - ), - ] +# Generated by Django 4.1 on 2024-08-14 12:27 + +from django.conf import settings +import django.contrib.auth.models +import django.contrib.auth.validators +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + replaces = [('taxi', '0001_initial')] + + initial = True + + dependencies = [ + ('auth', '0012_alter_user_first_name_max_length'), + ] + + operations = [ + migrations.CreateModel( + name='Driver', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('password', models.CharField(max_length=128, verbose_name='password')), + ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), + ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), + ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), + ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), + ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), + ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), + ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), + ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting registration.', verbose_name='active')), + ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), + ('license_number', models.CharField(max_length=255)), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')), + ], + options={ + 'verbose_name': 'driver', + 'verbose_name_plural': 'drivers', + }, + managers=[ + ('objects', django.contrib.auth.models.UserManager()), + ], + ), + migrations.CreateModel( + name='Manufacturer', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=255)), + ('country', models.CharField(max_length=255)), + ], + ), + migrations.CreateModel( + name='Car', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('model', models.CharField(max_length=255)), + ('drivers', models.ManyToManyField(related_name='cars', to=settings.AUTH_USER_MODEL)), + ('manufacturer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='taxi.manufacturer')), + ], + ), + ] diff --git a/taxi/migrations/0002_alter_car_options_alter_driver_options_and_more.py b/taxi/migrations/0002_alter_car_options_alter_driver_options_and_more.py new file mode 100644 index 00000000..6935a8de --- /dev/null +++ b/taxi/migrations/0002_alter_car_options_alter_driver_options_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 4.1 on 2024-08-14 14:44 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('taxi', '0001_squashed_0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='car', + options={'ordering': ('model',)}, + ), + migrations.AlterModelOptions( + name='driver', + options={'ordering': ('username',), 'verbose_name': 'driver', 'verbose_name_plural': 'drivers'}, + ), + migrations.AlterModelOptions( + name='manufacturer', + options={'ordering': ['name']}, + ), + migrations.AlterField( + model_name='car', + name='manufacturer', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='cars', to='taxi.manufacturer'), + ), + migrations.AlterField( + model_name='driver', + name='is_active', + field=models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active'), + ), + migrations.AlterField( + model_name='driver', + name='license_number', + field=models.CharField(max_length=255, unique=True), + ), + migrations.AlterField( + model_name='manufacturer', + name='name', + field=models.CharField(max_length=255, unique=True), + ), + ] diff --git a/taxi/migrations/0002_alter_manufacturer_options_and_more.py b/taxi/migrations/0002_alter_manufacturer_options_and_more.py deleted file mode 100644 index a056822c..00000000 --- a/taxi/migrations/0002_alter_manufacturer_options_and_more.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 4.0.2 on 2022-04-12 06:44 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('taxi', '0001_initial'), - ] - - operations = [ - migrations.AlterModelOptions( - name='manufacturer', - options={'ordering': ['name']}, - ), - migrations.AlterField( - model_name='driver', - name='license_number', - field=models.CharField(max_length=255, unique=True), - ), - ] diff --git a/taxi/migrations/0003_alter_manufacturer_name.py b/taxi/migrations/0003_alter_manufacturer_name.py deleted file mode 100644 index 806cc0e6..00000000 --- a/taxi/migrations/0003_alter_manufacturer_name.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.0.2 on 2022-06-16 07:46 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('taxi', '0002_alter_manufacturer_options_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='manufacturer', - name='name', - field=models.CharField(max_length=255, unique=True), - ), - ] diff --git a/taxi/models.py b/taxi/models.py index 9061de82..f6635111 100644 --- a/taxi/models.py +++ b/taxi/models.py @@ -1,3 +1,4 @@ +from django.conf import settings from django.db import models from django.contrib.auth.models import AbstractUser @@ -10,24 +11,32 @@ class Meta: ordering = ["name"] def __str__(self): - return f"{self.name} {self.country}" + return f"{self.name}, {self.country}" class Driver(AbstractUser): license_number = models.CharField(max_length=255, unique=True) class Meta: + ordering = ("username",) verbose_name = "driver" verbose_name_plural = "drivers" def __str__(self): - return f"{self.username} ({self.first_name} {self.last_name})" + return f"{self.username}: ({self.first_name} {self.last_name})" class Car(models.Model): model = models.CharField(max_length=255) - manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) - drivers = models.ManyToManyField(Driver, related_name="cars") + manufacturer = models.ForeignKey( + Manufacturer, on_delete=models.CASCADE, related_name="cars" + ) + drivers = models.ManyToManyField( + settings.AUTH_USER_MODEL, related_name="cars" + ) - def __str__(self): - return self.model + class Meta: + ordering = ("model",) + + def __str__(self) -> str: + return f"{self.model}, {self.manufacturer.country}" diff --git a/taxi/views.py b/taxi/views.py index 82ad312f..4e5ec24a 100644 --- a/taxi/views.py +++ b/taxi/views.py @@ -1,47 +1,53 @@ +from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import LoginRequiredMixin +from django.http import HttpRequest, HttpResponse from django.shortcuts import render from django.views import generic from .models import Driver, Car, Manufacturer -def index(request): +@login_required +def index(request: HttpRequest) -> HttpResponse: """View function for the home page of the site.""" num_drivers = Driver.objects.count() num_cars = Car.objects.count() num_manufacturers = Manufacturer.objects.count() - + num_visits = request.session.get("num_visits", 0) + request.session["num_visits"] = num_visits + 1 context = { "num_drivers": num_drivers, "num_cars": num_cars, "num_manufacturers": num_manufacturers, + "num_visits": num_visits + 1 } return render(request, "taxi/index.html", context=context) -class ManufacturerListView(generic.ListView): +class ManufacturerListView(LoginRequiredMixin, generic.ListView): model = Manufacturer context_object_name = "manufacturer_list" template_name = "taxi/manufacturer_list.html" paginate_by = 5 -class CarListView(generic.ListView): +class CarListView(LoginRequiredMixin, generic.ListView): model = Car paginate_by = 5 queryset = Car.objects.select_related("manufacturer") -class CarDetailView(generic.DetailView): +class CarDetailView(LoginRequiredMixin, generic.DetailView): model = Car -class DriverListView(generic.ListView): +class DriverListView(LoginRequiredMixin, generic.ListView): model = Driver paginate_by = 5 -class DriverDetailView(generic.DetailView): +class DriverDetailView(LoginRequiredMixin, generic.DetailView): model = Driver queryset = Driver.objects.prefetch_related("cars__manufacturer") diff --git a/taxi_service/settings.py b/taxi_service/settings.py index b6c0cf19..2a982c39 100644 --- a/taxi_service/settings.py +++ b/taxi_service/settings.py @@ -133,3 +133,5 @@ # https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" + +LOGIN_REDIRECT_URL = "/taxi/" diff --git a/taxi_service/urls.py b/taxi_service/urls.py index 8b94449f..baf83d1a 100644 --- a/taxi_service/urls.py +++ b/taxi_service/urls.py @@ -22,4 +22,5 @@ urlpatterns = [ path("admin/", admin.site.urls), path("", include("taxi.urls", namespace="taxi")), + path("accounts/", include("django.contrib.auth.urls")), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/templates/base.html b/templates/base.html index f4a0b6cf..3e0343c9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -6,9 +6,9 @@ + href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css" + integrity="sha384-TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" + crossorigin="anonymous"> {% load static %} diff --git a/templates/includes/sidebar.html b/templates/includes/sidebar.html index b7cd72dc..14da6597 100644 --- a/templates/includes/sidebar.html +++ b/templates/includes/sidebar.html @@ -1,4 +1,11 @@ +

You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.

{% endblock %}