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 #886

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
Empty file added accounts/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.

Choose a reason for hiding this comment

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

You need to register your models with the admin site. If you have models defined in models.py, import them here and use admin.site.register(ModelName) to register each model.

6 changes: 6 additions & 0 deletions accounts/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class AccountsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "accounts"
Empty file added accounts/migrations/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.db import models

# Create your models here.

Choose a reason for hiding this comment

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

Consider defining your models here if your application requires them. Each model should subclass models.Model and include fields that represent the data structure you need.

3 changes: 3 additions & 0 deletions accounts/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.

Choose a reason for hiding this comment

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

Consider adding test cases to this file. Use TestCase to create tests that verify the behavior of your application's features and ensure they work as expected.

10 changes: 10 additions & 0 deletions accounts/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from accounts.views import login_view, logout_view
from django.urls import path


urlpatterns = [
path("login/", login_view, name="login"),
path("logout/", logout_view, name="logout"),
]

app_name = "accounts"
27 changes: 27 additions & 0 deletions accounts/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from django.contrib.auth import authenticate, login, logout
from django.http import HttpRequest, HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse


# Create your views here.
def login_view(request: HttpRequest) -> HttpResponse:
if request.method == "POST":
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse("taxi:index"))

Choose a reason for hiding this comment

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

Ensure that the URL name 'taxi:index' used in reverse() is correctly defined in your URL configurations. If 'taxi:index' does not exist, it will cause a NoReverseMatch error.

else:
context = {
"message": "Invalid username or password.",
}
return render(request, "registration/login.html", context=context)

Choose a reason for hiding this comment

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

Make sure the template registration/login.html exists in your templates directory to avoid TemplateDoesNotExist errors.

if request.method == "GET":
return render(request, "registration/login.html")


def logout_view(request: HttpRequest) -> HttpResponse:
logout(request)
return render(request, "registration/logout.html")

Choose a reason for hiding this comment

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

Ensure the template registration/logout.html exists in your templates directory to avoid TemplateDoesNotExist errors.

4 changes: 4 additions & 0 deletions static/css/styles.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
body {
margin-top: 20px;
}

ul {
text-decoration: none;
}
177 changes: 149 additions & 28 deletions taxi/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,172 @@ 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

Choose a reason for hiding this comment

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

Ensure that settings.AUTH_USER_MODEL is correctly set to the custom user model if Driver is intended to be a custom user model. This is important for maintaining the integrity of the many-to-many relationship.

Choose a reason for hiding this comment

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

Ensure that settings.AUTH_USER_MODEL is correctly set to the custom user model you are using, which should be Driver in this case.

),
),
(
"manufacturer",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="taxi.manufacturer",

Choose a reason for hiding this comment

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

Verify that the Manufacturer model is correctly defined in your models.py file under the taxi app. This is crucial for the foreign key relationship to work properly.

Choose a reason for hiding this comment

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

Verify that the manufacturer ForeignKey is correctly pointing to the Manufacturer model. The string 'taxi.manufacturer' should match the app and model name.

),
),
],
),
]
10 changes: 5 additions & 5 deletions taxi/migrations/0002_alter_manufacturer_options_and_more.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
class Migration(migrations.Migration):

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

operations = [
migrations.AlterModelOptions(
name='manufacturer',
options={'ordering': ['name']},
name="manufacturer",
options={"ordering": ["name"]},

Choose a reason for hiding this comment

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

The ordering option for the Manufacturer model is set to order by name. Ensure that this aligns with your application's requirements for displaying manufacturers.

Choose a reason for hiding this comment

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

The Manufacturer model now has an ordering option set to name. Ensure this is reflected in your models.py if you want this ordering to be applied at the model level.

),
migrations.AlterField(
model_name='driver',
name='license_number',
model_name="driver",
name="license_number",
field=models.CharField(max_length=255, unique=True),

Choose a reason for hiding this comment

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

The license_number field in the Driver model is now unique. This change ensures that no two drivers can have the same license number, which is important for data integrity.

Choose a reason for hiding this comment

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

The license_number field in the Driver model is now unique. Ensure that this change is reflected in your models.py to maintain consistency between your models and migrations.

),
]
6 changes: 3 additions & 3 deletions taxi/migrations/0003_alter_manufacturer_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
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),

Choose a reason for hiding this comment

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

The name field in the Manufacturer model is now unique. This change prevents duplicate manufacturer names, which is crucial for ensuring that each manufacturer is uniquely identifiable.

Choose a reason for hiding this comment

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

The name field in the Manufacturer model is now unique. Ensure this change is reflected in your models.py to maintain consistency between your models and migrations.

),
]
1 change: 0 additions & 1 deletion taxi/urls.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from django.urls import path

from .views import (
index,
CarListView,
Expand Down
14 changes: 9 additions & 5 deletions taxi/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from django.views import generic

Expand All @@ -10,38 +11,41 @@ def index(request):
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,

Choose a reason for hiding this comment

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

Consider using the pluralize filter in your template to handle singular and plural forms for num_visits. This will ensure the visit counter displays correctly as 'time' or 'times' based on the count. Check the template taxi/index.html to ensure it uses {{ num_visits|pluralize }}.

}

return render(request, "taxi/index.html", context=context)

Choose a reason for hiding this comment

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

Ensure that the template 'taxi/index.html' exists in your templates directory. Otherwise, this will result in a TemplateDoesNotExist error.



class ManufacturerListView(generic.ListView):
class ManufacturerListView(LoginRequiredMixin, generic.ListView):
model = Manufacturer
context_object_name = "manufacturer_list"
template_name = "taxi/manufacturer_list.html"

Choose a reason for hiding this comment

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

Ensure that the template 'taxi/manufacturer_list.html' exists in your templates directory. Otherwise, this will result in a TemplateDoesNotExist error.

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")
1 change: 1 addition & 0 deletions taxi_service/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"django.contrib.messages",
"django.contrib.staticfiles",
"taxi",
"accounts",
]

MIDDLEWARE = [
Expand Down
3 changes: 2 additions & 1 deletion taxi_service/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path("blog/", include("blog.urls"))
"""

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static


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)
6 changes: 6 additions & 0 deletions templates/includes/sidebar.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<ul class="sidebar-nav">
{% if user.is_authenticated %}
<li><a href="{% url 'taxi:driver-detail' pk=user.id %}">{{ user.username }}</a></li><br>

Choose a reason for hiding this comment

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

Ensure that the driver-detail URL pattern expects a pk parameter corresponding to the user's ID. If the Driver model uses a different field for identification, adjust the URL accordingly.

Choose a reason for hiding this comment

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

Ensure that the URL pattern taxi:driver-detail is correctly defined in your URL configurations. This is necessary for the link to the driver's detail page to work properly.

<li><a href="{% url 'logout' %}">Logout</a></li>

Choose a reason for hiding this comment

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

The logout URL should be correctly configured in your URL patterns. Ensure that the name attribute for the logout path is set to 'logout'.

{% else %}
<li><a href="{% url 'login' %}">Login</a></li>

Choose a reason for hiding this comment

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

The login URL should be correctly configured in your URL patterns. Ensure that the name attribute for the login path is set to 'login'.

{% endif %}
<li><a href="{% url "taxi:index" %}">Home page</a></li>
<li><a href="{% url "taxi:manufacturer-list" %}">Manufacturers</a></li>
<li><a href="{% url "taxi:car-list" %}">Cars</a></li>
Expand Down
Loading
Loading