diff --git a/taxi/migrations/0001_initial.py b/taxi/migrations/0001_initial.py index ff29293e..040306d7 100644 --- a/taxi/migrations/0001_initial.py +++ b/taxi/migrations/0001_initial.py @@ -9,55 +9,169 @@ class Migration(migrations.Migration): - initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), + ("auth", "0012_alter_user_first_name_max_length"), ] operations = [ migrations.CreateModel( - name='Driver', + 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')), + ( + "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', + "verbose_name": "driver", + "verbose_name_plural": "drivers", }, managers=[ - ('objects', django.contrib.auth.models.UserManager()), + ("objects", django.contrib.auth.models.UserManager()), ], ), migrations.CreateModel( - name='Manufacturer', + 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)), + ( + "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', + 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')), + ( + "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_manufacturer_options_and_more.py b/taxi/migrations/0002_alter_manufacturer_options_and_more.py index a056822c..178da235 100644 --- a/taxi/migrations/0002_alter_manufacturer_options_and_more.py +++ b/taxi/migrations/0002_alter_manufacturer_options_and_more.py @@ -4,19 +4,18 @@ class Migration(migrations.Migration): - dependencies = [ - ('taxi', '0001_initial'), + ("taxi", "0001_initial"), ] operations = [ migrations.AlterModelOptions( - name='manufacturer', - options={'ordering': ['name']}, + name="manufacturer", + options={"ordering": ["name"]}, ), migrations.AlterField( - model_name='driver', - name='license_number', + 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 index 806cc0e6..7bf3309d 100644 --- a/taxi/migrations/0003_alter_manufacturer_name.py +++ b/taxi/migrations/0003_alter_manufacturer_name.py @@ -4,15 +4,14 @@ class Migration(migrations.Migration): - dependencies = [ - ('taxi', '0002_alter_manufacturer_options_and_more'), + ("taxi", "0002_alter_manufacturer_options_and_more"), ] operations = [ migrations.AlterField( - model_name='manufacturer', - name='name', + model_name="manufacturer", + name="name", field=models.CharField(max_length=255, unique=True), ), ] diff --git a/taxi/urls.py b/taxi/urls.py index c663d6e2..68d6ac65 100644 --- a/taxi/urls.py +++ b/taxi/urls.py @@ -1,4 +1,4 @@ -from django.urls import path +from django.urls import path, include from .views import ( index, @@ -20,7 +20,9 @@ path("cars//", CarDetailView.as_view(), name="car-detail"), path("drivers/", DriverListView.as_view(), name="driver-list"), path( - "drivers//", DriverDetailView.as_view(), name="driver-detail" + "drivers//", + DriverDetailView.as_view(), + name="driver-detail" ), ] diff --git a/taxi/views.py b/taxi/views.py index 82ad312f..15da8358 100644 --- a/taxi/views.py +++ b/taxi/views.py @@ -1,9 +1,12 @@ +from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import render from django.views import generic from .models import Driver, Car, Manufacturer +@login_required def index(request): """View function for the home page of the site.""" @@ -11,37 +14,41 @@ def index(request): num_cars = Car.objects.count() num_manufacturers = Manufacturer.objects.count() + num_visits = request.session.get("num_visits", 1) + request.session["num_visits"] = num_visits + 1 + context = { "num_drivers": num_drivers, "num_cars": num_cars, "num_manufacturers": num_manufacturers, + "num_visits": num_visits, } 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..ea4f77c7 100644 --- a/taxi_service/settings.py +++ b/taxi_service/settings.py @@ -1,37 +1,14 @@ -""" -Django settings for taxi_service project. - -Generated by "django-admin startproject" using Django 4.0.2. - -For more information on this file, see -https://docs.djangoproject.com/en/4.0/topics/settings/ - -For the full list of settings and their values, see -https://docs.djangoproject.com/en/4.0/ref/settings/ -""" - from pathlib import Path -# Build paths inside the project like this: BASE_DIR / "subdir". BASE_DIR = Path(__file__).resolve().parent.parent +SECRET_KEY = ("django-insecure-8ovil3xu6=eao" + "qd#-#&ricv159p0pypoh5_lgm*)-dfcjqe=yc") -# Quick-start development settings - unsuitable for production -# See https://docs.djangoproject.com/en/4.0/howto/deployment/checklist/ - -# SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = ( - "django-insecure-8ovil3xu6=eaoqd#-#&ricv159p0pypoh5_lgm*)-dfcjqe=yc" -) - -# SECURITY WARNING: don"t run with debug turned on in production! DEBUG = True ALLOWED_HOSTS = [] - -# Application definition - INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", @@ -72,10 +49,6 @@ WSGI_APPLICATION = "taxi_service.wsgi.application" - -# Database -# https://docs.djangoproject.com/en/4.0/ref/settings/#databases - DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", @@ -83,10 +56,6 @@ } } - -# Password validation -# https://docs.djangoproject.com/en/4.0/ref/settings/#auth-password-validators - AUTH_PASSWORD_VALIDATORS = [ { "NAME": "django.contrib.auth.password_validation." @@ -94,23 +63,20 @@ }, { "NAME": "django.contrib.auth.password_validation." - "MinimumLengthValidator", + "MinimumLengthValidator", }, { "NAME": "django.contrib.auth.password_validation." - "CommonPasswordValidator", + "CommonPasswordValidator", }, { "NAME": "django.contrib.auth.password_validation." - "NumericPasswordValidator", + "NumericPasswordValidator", }, ] AUTH_USER_MODEL = "taxi.Driver" -# Internationalization -# https://docs.djangoproject.com/en/4.0/topics/i18n/ - LANGUAGE_CODE = "en-us" TIME_ZONE = "Europe/Kiev" @@ -119,9 +85,7 @@ USE_TZ = True - -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/4.0/howto/static-files/ +LOGIN_REDIRECT_URL = "/" STATIC_URL = "static/" @@ -129,7 +93,4 @@ STATIC_ROOT = BASE_DIR / "staticfiles" -# Default primary key field type -# https://docs.djangoproject.com/en/4.0/ref/settings/#default-auto-field - DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField" 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/includes/sidebar.html b/templates/includes/sidebar.html index b7cd72dc..565a7988 100644 --- a/templates/includes/sidebar.html +++ b/templates/includes/sidebar.html @@ -1,4 +1,12 @@ diff --git a/templates/taxi/index.html b/templates/taxi/index.html index 13c59aa8..40493bd8 100644 --- a/templates/taxi/index.html +++ b/templates/taxi/index.html @@ -10,4 +10,6 @@

Dynamic content

  • Drivers: {{ num_drivers }}
  • Manufacturers: {{ num_manufacturers }}
  • +
    +

    Times you visited this page: {{ num_visits }}

    {% endblock %} diff --git a/tests/test_taxi_service.py b/tests/test_taxi_service.py index a3e07ae3..f273c68d 100644 --- a/tests/test_taxi_service.py +++ b/tests/test_taxi_service.py @@ -64,11 +64,7 @@ def test_manufacturer_list(self): self.assertEqual(response.status_code, 200) self.assertEqual( list(response.context["manufacturer_list"]), - list( - manufacturers[ - 0 : len(list(response.context["manufacturer_list"])) - ] - ), + list(manufacturers[0 : len(list(response.context["manufacturer_list"]))]), ) self.assertTemplateUsed(response, "taxi/manufacturer_list.html") @@ -122,8 +118,6 @@ def setUp(self): self.credentials = {"username": "admin.user", "password": "1qazcde3"} def test_login(self): - response = self.client.post( - reverse("login"), self.credentials, follow=True - ) + response = self.client.post(reverse("login"), self.credentials, follow=True) self.assertTrue(response.context["user"].is_active) print(response.context["user"])