how to add slug argument to url in django?

Viewed 127

I want to add slug in url using django like this <a href="{% url 'tutorials:tutorial' topic.tutorial_category.slug topic.tutorial_topic_category.slug topic.slug %} </a> i dont really know how to pass in triple slug in the url for example: i want to access the programming > html > introduction-to-html like this http://127.0.0.1:8000/tutorial/programming/html/introduction-to-html

Error

Reverse for 'tutorial' with arguments '('', 'html', 'introduction-to-html')' not found. 1 pattern(s) tried: ['tutorial/(?P<main_category_slug>[^/]+)/(?P<topic_category_slug>[^/]+)/(?P<tutorial_slug>[^/]+)$']

topic.html:

{% for topic in topics %}
     <a href="{% url 'tutorials:tutorial' topic.tutorial_category.slug topic.tutorial_topic_category.slug topic.slug %}">{{topic.title}} - Start Now</a>    

{% endfor %}

views.py:

def topic(request, main_category_slug, topic_category_slug):
    tutorial_category = TutorialCategory.objects.get(slug=main_category_slug)
    tutorial_topic_category = TutorialTopicCategory.objects.get(slug=topic_category_slug)
    topics = Topic.objects.filter(tutorial_topic_category=tutorial_topic_category)

    context = {
        'topics':topics,
    }
    return render(request, 'tutorials/topic.html', context)

def tutorial(request, main_category_slug, topic_category_slug, tutorial_slug):
    tutorial_category = TutorialCategory.objects.get(slug=main_category_slug)
    tutorial_topic_category = TutorialTopicCategory.objects.get(slug=topic_category_slug)
    topics = Topic.objects.filter(tutorial_topic_category=tutorial_topic_category)
    tutorial = Topic.objects.get(slug=tutorial_slug)


    context = {
        'topics':topics,
        'tutorial':tutorial,
    }
    return render(request, 'tutorials/tutorial.html', context)

urls.py

  path("<slug>", views.tutorial_topic_category, name='tutorial-topic-category'),
        path("<slug:main_category_slug>/<slug:topic_category_slug>", views.topic, name='topic'),
        path("<slug:main_category_slug>/<slug:topic_category_slug>/<slug:tutorial_slug>/", views.tutorial, name='tutorial'),

models.py

class TutorialCategory(models.Model):
    title = models.CharField(max_length=1000)
    slug = models.SlugField(unique=True)
    active = models.BooleanField(default=True)
    

class TutorialTopicCategory(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    tutorial_category = models.ForeignKey(TutorialCategory, on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=1000)
    slug = models.SlugField(unique=True)


class Topic(models.Model):
    tutorial_topic_category = models.ForeignKey(TutorialTopicCategory, on_delete=models.CASCADE, null=True)
    title = models.CharField(max_length=10000)
    slug = models.SlugField(unique=True)
1 Answers

By default, if you don't give anything in route while defining in path() as you give "<main_category_slug>/<topic_category_slug>/<tutorial_slug>" so these are considered strings.

For example: <str:name>/ and <name>/ is same.

If you want to make slugs all of three, so you should define them as slug first, write your route as "<slug:main_category_slug>/<slug:topic_category_slug>/<slug:tutorial_slug>/", then these is considered as slugs.

Minor Mistake: You should not define same variables, it must be for topic in topics not for topic in topic.

Note: Always give / at the end of every route.

Edit:

You should do following things in your code:

Firstly, change this link:

<a href="{% url 'tutorials:tutorial' topic.tutorial_category.slug topic.tutorial_topic_category.slug topic.slug %}">{{topic.title}} - Start Now</a>

To this link:

<a href="{% url 'tutorials:tutorial' topic.tutorial_topic_category.tutorial_category.slug topic.tutorial_topic_category.slug topic.slug %}">{{topic.title}} - Start Now</a>

Why?

Look at your url correctly:

 path("<slug:main_category_slug>/<slug:topic_category_slug>/<slug:tutorial_slug>/", views.tutorial, name='tutorial')

It's first slug is main_category_slug that means slug of TutorialCategory model which is at the first in models.py. So, for accessing you need to write topic.tutorial_topic_category.tutorial_category.slug in the template tutorial.html.

It's second slug is topic_category_slug that means slug of TutorialTopicCategory model which is at the second in models.py. So, for accessing it, you need to write topic.tutorial_topic_category.slug in the template tutorial.html.

It's third slugs is tutorial_slug that means your slug of Topic model which is at the last in models.py. So, for accessing it, you need to write topic.slug simply, in the template tutorial.html.

Simply change this and don't change anything:

topic.html or template file:

{% for topic in topics %}

    <a href="{% url 'tutorials:tutorial' topic.tutorial_topic_category.tutorial_category.slug topic.tutorial_topic_category.slug topic.slug %}">{{topic.title}} - Start Now</a>
{% endfor %}
Related