Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot resolve keyword u'slug' into field error in Django?

I am getting the following error:

FieldError at /blog/1/first-post/

Cannot resolve keyword u'slug' into field. Choices are: article, date, id, likes

Request Method:     GET
Request URL:    http://127.0.0.1:8000/blog/1/first-post/
Django Version:     1.6.2
Exception Type:     FieldError
Exception Value:    

Cannot resolve keyword u'slug' into field. Choices are: article, date, id, likes

My model:

class Article(models.Model):
    title = models.CharField(max_length=20)
    body = models.TextField()
    image = models.ImageField(upload_to="/", blank=True, null=True)
    slug = models.SlugField()

    def save(self, *args, **kwargs):
        if not self.id:
            self.slug = slugify(self.title)
        super(Article, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('article_detail', kwargs={'slug':self.slug, 'id':self.id})

    def __unicode__(self):
        return self.title

class Detail(models.Model):
    article = models.ForeignKey(Article)
    date = models.DateField()
    likes = models.IntegerField()

    def __unicode__(self):
        return "%s %s" % (self.article.title, self.likes)

    def get_absolute_url(self):
        return reverse('detail_article', kwargs={'id':self.id})

View:

class ArticleDetail(DetailView):
     model = Detail
     template_name = "article_detail.html"
     context_object_name = "details"

     def get_queryset(self):
        print self.kwargs['slug']
        a = Article.objects.get(slug=self.kwargs['slug'])
        # print Details.object.get()
        # print Detail.objects.filter(article__slug=self.kwargs['slug']) fails with same error
        return Detail.objects.filter(article=a)

urls.py (this is inside by blog app):

urlpatterns = patterns('',

url(r'all$', ArticleList.as_view(), name='blog_all'),
url(r'^(?P<id>\d+)/(?P<slug>[-\w\d]+)/$', ArticleDetail.as_view(), name='article_detail'),
url(r'^detail/?(P<id?\d+)/$', DetailArticle.as_view(), name='detail_article'),
url(r'^create$', ArticleCreateView.as_view(), name='blog_create'),
)

Basically the detailView of an article instance will display the contents of detail model that has foreignkey relationship to article model. It is not the traditional way where the detail view of article instance displays that instance.

Template here:

{% extends "base.html" %}
{% block content %}
{% for detail in details %}
<p>{{ detail.article.title }}</p>
<p>{{ detail.date }}</p>
<p>{{ detail.likes }}</p>
{% endfor %}
{% endblock %}
like image 783
brain storm Avatar asked May 15 '14 23:05

brain storm


2 Answers

overriding the get_object(self, queryset=None) method instead of DetailView get_queryset(self) is an easier solution

class ArticleDetail(DetailView):
    model = Detail
    template_name = "article_detail.html"
    context_object_name = "details"

    def get_object(self, queryset=None):
        slug = self.kwargs['slug']
        a_obj = Article.objects.get(slug=slug)
        try:
           d_obj = Detail.objects.get(article=a_obj)
        except Detail.DoesNotExist:
            d_obj = None
        except Detail.MultipleObjectsReturned:
            #select the apt object
        return d_obj
like image 93
javed Avatar answered Sep 19 '22 17:09

javed


Solution: you need to rename slug parameter in url to other name, or in your view set slug_url_kwarg some other value - not 'slug'

Explanation: When you add to url, django tries to get object by slug and your model Detail has no slug field.

Link to django code: https://github.com/django/django/blob/master/django/views/generic/detail.py#L33

UPDATE

in SingleObjectMixin:

slug = self.kwargs.get(self.slug_url_kwarg, None)
...
elif slug is not None:
    slug_field = self.get_slug_field()
    queryset = queryset.filter(**{slug_field: slug})

so django gets slug from your url, tries to get slug field from Detail model and fails

Your view need to rewrite slug_url_kwarg attribute:

class ArticleDetail(DetailView):
    model = Detail
    template_name = "article_detail.html"
    context_object_name = "details"
    slug_url_kwarg = "not_slug" # this attribute

 def get_queryset(self):
    print self.kwargs['slug']
    a = Article.objects.get(slug=self.kwargs['slug'])
    # print Details.object.get()
    # print Detail.objects.filter(article__slug=self.kwargs['slug']) fails with same error
    return Detail.objects.filter(article=a)

but I think better way is to change to attribute in your url:

url(r'^(?P<id>\d+)/(?P<article_slug>[-\w\d]+)/$', ArticleDetail.as_view(), name='article_detail'),

and get article_slug from view kwargs

like image 34
zymud Avatar answered Sep 19 '22 17:09

zymud