mark
mark

Reputation: 673

Slug in url with CBV in django 1.8

I use Django 1.8 and I want to buid blog with slugs in urls. But my code doesn't work.

Here is my template with link to post details:

{% extends "base.html" %}
{% block head_title %}<title>Blog</title>{% endblock %}

{% block content %}
    <div class="container">
        <h2>Blog</h2>
        {% for i in blog %}
            <p><b>{{ i.date|date:"D, d M Y" }}</b></p>

            <h4><a href="{% url 'projde:blogdetail' slug=i.slug %}">{{ i.title }}</a></h4>
            <p>{{ i.text|truncatewords:100 }}</p>
            {% if not forloop.last %}
                <hr>
            {% endif %}
        {% endfor %}
    </div>
{% endblock %}

Here is my model:

class BlogPost(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=200, unique=True)
    text = models.TextField()
    date = models.DateTimeField()
    is_online = models.BooleanField(default=False)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("blogdetail", kwargs={"slug": self.slug})

Here are all my views in my application, but in this case the most important is the last one.

class Home(TemplateView):
    template_name = "projde/index.html"


class Projects(ListView):
    template_name = "projde/projects.html"
    context_object_name = "all_projects"
    model = ProjectItem

    def get_queryset(self):
        return ProjectItem.objects.filter(is_online=True)


class Resume(ListView):
    template_name = 'projde/resume.html'
    context_object_name = 'resume'
    model = ResumeItem

    def get_queryset(self):
        return ResumeItem.objects.filter(is_online=True)


class Blog(ListView):
    template_name = "projde/blog.html"
    context_object_name = "blog"
    model = BlogPost

    def get_queryset(self):
        s = BlogPost.objects.all().order_by("-date")
        return s

class BlogDetail(DetailView):
    model = BlogPost
    template_name = "projde/blogdetail.html"

and my url:

    urlpatterns = [
    url(r'^$', Home.as_view(), name="home"),
    url(r'^projects/$', Projects.as_view(), name="projects"),
    url(r'^resume/$', Resume.as_view(), name="resume"),
    url(r'^blog/$', Blog.as_view(), name="blog"),
    url(r'^blog/(?P<slug>\S+)$', BlogDetail.as_view(), name="blogdetail"),
]

Upvotes: 0

Views: 358

Answers (1)

Alasdair
Alasdair

Reputation: 308769

In the ListView template the list of blog posts will be available as blogpost_list if you don't set context_object_name.

{% for blogpost in blogpost_list %}
<p><b>{{ blogpost.date|date:"D, d M Y" }}</b></p>
<h4><a href="{% url 'projde:blogdetail' slug=blogpost.slug %}">{{ blogpost.title }}</a></h4>
{% endfor %}

Since you have set context_object_name = 'blog' for your list view, you should change the above for loop to {% for blogpost in blogs %}.

If you still get the error '{'slug': ''}', that suggests that there is a blogpost in your database with slug=''. Fix this through the shell or Django admin, then refresh the page.

In the DetailView template, you don't need the for loop, and you can access the blog post with {{ blogpost }}.

Upvotes: 1

Related Questions