I am a beginner in Django. I am building a Django app, named PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models.
I have already created models, views and the template files. Now, I am facing a problem. I can't use slug in URLs. Right now, it looks like this:
Here are my codes of models.py located inside PhoneReview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.brand_name)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.model_name
def save(self, *args, **kwargs):
self.slug = slugify(self.model_name)
super().save(*args, **kwargs)
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
# slug = models.SlugField(max_length=150, null=True, blank=True)
link = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are my codes of urls.py located inside PhoneReview folder:
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
path('details/<int:pk>/', views.ReviewView.as_view(), name='details'),
]
Here are my codes of views.py located inside PhoneReview folder:
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/index.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are my codes of apps.py located inside PhoneReview folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are my codes of index.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<h2>Here is the list of the brands</h2>
<ul>
{% for brand in all_brands %}
<!-- <li>{{ brand.brand_name }}</li>-->
<li><a href = "{% url 'modellist' brand.id %}">{{ brand.brand_name }}</a></li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of phonemodel.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
<li><a href = "{% url 'details' phonemodel.id %}">{{ phonemodel.model_name }}</a></li>
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
In index.html, I tried to replace <li><a href = "{% url 'details' phonemodel.id %}">{{ phonemodel.model_name }}</a></li>
with <li><a href = "{% url 'details' phonemodel.slug %}">{{ phonemodel.model_name }}</a></li>
. But I get error.
How can I fix the issue?
Update: I added the codes provided by @arjun. However, I am getting an error. It says the following
OperationalError at /index
no such table: PhoneReview_brand
You need to pass slug
instead of pk
through your url if you want to use slug
path('phonemodel/<slug:slug>/', views.ModelView.as_view(), name='modellist'),
path('details/<slug:slug>/', views.ReviewView.as_view(), name='details'),
Now in template instead of id
<li><a href = "{% url 'details' phonemodel.slug %}">{{ phonemodel.model_name }}</a></li>
And it's better to have unique slug field
slug = models.SlugField(max_length=150, unique=True)
Also I will suggest you to use the django-autoslug. It is a reusable Django library that provides an improved slug field which can automatically populate itself from another field.
EDIT:You haven't passed context_object_name
in your detail view so provide the context here
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
context_object_name= 'phonemodel'