Homework: add more to your website!

    Currently when we’re creating new posts using our New post form the post is published directly. To instead save the post as a draft, remove this line in in the post_new and post_edit methods:

    This way, new posts will be saved as drafts that we can review later on rather than being instantly published. All we need now is a way to list and publish drafts, let’s get to it!

    Remember the chapter about querysets? We created a view post_list that displays only published blog posts (those with non-empty published_date).

    Time to do something similar, but for draft posts.

    Let’s add a link in blog/templates/blog/base.html in the header. We don’t want to show our list of drafts to everybody, so we’ll put it inside the {% if user.is_authenticated %} check, right after the button for adding new posts.

    1. <a href="{% url 'post_draft_list' %}" class="top-menu"><span class="glyphicon glyphicon-edit"></span></a>

    Next: urls! In blog/urls.py we add:

    1. url(r'^drafts/$', views.post_draft_list, name='post_draft_list'),

    Time to create a view in blog/views.py:

    1. def post_draft_list(request):
    2. posts = Post.objects.filter(published_date__isnull=True).order_by('created_date')

    The line posts = Post.objects.filter(published_date__isnull=True).order_by('created_date') makes sure that we take only unpublished posts (published_date__isnull=True) and order them by created_date (order_by('created_date')).

    Ok, the last bit is of course a template! Create a file and add the following:

    It looks very similar to our post_list.html, right?

    Yay! Your first task is done!

    It would be nice to have a button on the blog post detail page that will immediately publish the post, right?

    Let’s open blog/templates/blog/post_detail.html and change these lines:

    1. {% if post.published_date %}
    2. <div class="date">
    3. {{ post.published_date }}
    4. </div>
    5. {% endif %}

    into these:

    1. {% if post.published_date %}
    2. <div class="date">
    3. {{ post.published_date }}
    4. {% else %}
    5. <a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
    6. {% endif %}

    As you noticed, we added {% else %} line here. That means, that if the condition from {% if post.published_date %} is not fulfilled (so if there is no ), then we want to do the line <a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>. Note that we are passing a pk variable in the {% url %}.

    Time to create a URL (in blog/urls.py):

    1. url(r'^post/(?P<pk>\d+)/publish/$', views.post_publish, name='post_publish'),

    and finally, a view (as always, in blog/views.py):

    Remember, when we created a Post model we wrote a method publish. It looked like this:

    1. def publish(self):
    2. self.published_date = timezone.now()
    3. self.save()

    Now we can finally use this!

    And once again after publishing the post we are immediately redirected to the post_detail page!

    Congratulations! You are almost there. The last step is adding a delete button!

    Let’s open blog/templates/blog/post_detail.html once again and add this line:

    1. <a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>

    just under a line with the edit button.

    Now we need a URL (blog/urls.py):

      Now, time for a view! Open blog/views.py and add this code:

      The only new thing is to actually delete a blog post. Every Django model can be deleted by . It is as simple as that!

      And this time, after deleting a post we want to go to the webpage with a list of posts, so we are using redirect.

      Let’s test it! Go to the page with a post and try to delete it!

      Yes, this is the last thing! You completed this tutorial! You are awesome!