26. Creation of slugs for dynamic URLs

We will utilize slugs to prevent issues related to URL formatting and encoding. Slugs enable the admin to enforce URL rules, such as prohibiting spaces and special characters. To implement this, we will update the Category and Type classes by adding a slug attribute.

models.py
class Categoric(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    slug = models.CharField(max_length=200, null=True, blank=True)

    def __str__(self) :
        return str(self.name)

class Type(models.Model):
    name = models.CharField(max_length=200, null=True, blank=True)
    slug = models.CharField(max_length=200, null=True, blank=True)
    
    def __str__(self) :
        return str(self.name)

Note: As previously done in Chapter 5.3, when making direct changes to our database models, we need to perform migrations to apply these changes.

cmd prompt
python manage.py makemigrations
cmd prompt
python manage.py mmigrate

Navigate to each category and type within the administrative interface. Format their names in uppercase, remove spaces, and exclude special characters when entering them into the slug field.

Now, we need to update the code segments that were directly accessing information from unformatted names to use slugs instead. We'll start by changing the href URLs in navbar.html from category.name and type.name to category.slug and type.slug, respectively.

<div style="display: flex;">
        {% for category in categories %}
        <div>
            <a href="{% url 'store' %}{{ category.slug }}">{{ category.name }}</a>
            <br>
            {% for type in types %}
                <a href="{% url 'store' %}{{ category.slug }}-{{ type.slug }}">{{ type.name }}</a>
            {% endfor %}
        </div>
        {% endfor %}
    </div>

Lastly, we need to update the store view function. Previously, it filtered products by their category name. The updated code segment should now filter products using products.filter(category__slug=category_name).

For organizational purposes, we will also change all iteration names of category_name to filter.

views.py
def store(request, filter = None):
    products = Product.objects.filter(active=True) #? grabbing all products from the database (queryset, result of the search of the database)
    if filter:
        products = products.filter(category__slug = filter) #? gets the slug atribute from the category class and filters it according to the name of the category obtained from the banner
    context = {"products" : products} 
    return render(request, 'store.html', context) 

We also need to update the parameter name in urls.py from str:category_name to str:filter

    path('store/<str:filter>/', store, name="store"), #? comes after the fixed urls, allows to create multiple urls with varied names

Last updated