rant_category() got an unexpected keyword argument 'slug'

Question:

Running into an rant_category() got an unexpected keyword argument 'slug' on my django project. Basically, I just need to get the slug of the #category in my app to show it in the url.

Here’s my code:

views.py

class RantListView(ListView):
    model = Rant
    context_object_name = "rants"
    template_name = "rants/rant_list.html"


class RantDetailView(DetailView):
    model = Rant
    template_name = "rants/rant_detail.html"

def rant_category(request, category):
    rants = Rant.objects.filter(categories__slug__contains=category)
    context = {"category": category, "rants": rants}
    return render(request, "rants/rant_category.html", context)

models.py

class Category(models.Model):
    title = models.CharField(max_length=50)
    slug = AutoSlugField(populate_from="title", slugify_function=to_slugify)

    class Meta:
        get_latest_by = "-date_added"
        verbose_name = _("Category")
        verbose_name_plural = _("Categories")

    def get_absolute_url(self):
        return reverse("rants:rant-category", kwargs={"slug": self.slug})

    def __str__(self):
        return self.slug


class Rant(BaseModel, models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    post = models.TextField(blank=False)
    slug = AutoSlugField(populate_from="post", slugify_function=to_slugify)
    categories = models.ManyToManyField(Category, related_name="rants")

    class Meta:
        get_latest_by = "-date_added"
        verbose_name = _("rant")
        verbose_name_plural = _("rants")

    def get_absolute_url(self):
        return reverse("rants:rant-detail", kwargs={"slug": self.slug})

    def __str__(self):
        return self.slug

html code

    {% for rant in rants %}
        {{ rant.post }}
        {% for category in rant.categories.all %}
            <a href="{% url 'rants:rant-category' category.slug %}">#{{ category.title }}</a>
        {% endfor %}
    {% endfor %}

I’m getting an:

TypeError at /rants/category/category 1/
rant_category() got an unexpected keyword argument 'slug'

haven’t coded in awhile so I based everything on my old tutorial https://github.com/reyesvicente/cookiecutter-blog-tutorial-learnetto but it seems to not be working.

EDIT

Here’s my urls.py on the app:

    path("", RantListView.as_view(), name="rant"),
    path("<str:slug>/", RantDetailView.as_view(), name="rant-detail"),
    path("category/<str:slug>/", rant_category, name="rant-category"),

Answers:

It should be slug in rant_category view not category, like so:

def rant_category(request, slug):
    rants = Rant.objects.filter(categories__slug__contains=slug)
    context = {"category": slug, "rants": rants}
    return render(request, "rants/rant_category.html", context)
Answered By: Sunderam Dubey

Figured it out with the help of @sunderam dubey

def rant_category(request, slug):
    rants = Rant.objects.filter(categories__slug__contains=slug)
    context = {"slug": slug, "rants": rants}
    return render(request, "rants/rant_category.html", context)
    {% for rant in rants %} 
        {{rant.title}} 
        {% for category in rant.categories.all %}
            {{category.title}}
        {% endfor %}
    {% endfor %}

Now I have this data:

enter image description here

To explain the issue …

def rant_category(request, category):

category here is actually the category slug from the url.

path("category/<str:slug>/", rant_category, name="rant-category"),

So the view function is getting slug but only has a parameter called category. As the previous answer notes you need to change the function parameters for the view to reference slug instead. Then if you specifically need to reference the category object itself in the template you need to get that object first and pass that in the context, rather than the slug. So ..

def rant_category(request, slug):
    rants = Rant.objects.filter(categories__slug__contains=slug)
    category = Category.objects.get(slug=slug)
    context = {"category": category, "rants": rants}
    return render(request, "rants/rant_category.html", context)

Hope this gives a little explanation as to why it was wrong and the different options you have to fix it.

Answered By: michjnich