DEV Community

loading...
Cover image for Django Tutorial #9: Wrap Things Up

Django Tutorial #9: Wrap Things Up

ericnanhu profile image Eric Hu Originally published at techjblog.com ・4 min read

You can download the source code of this tutorial here.
https://www.techjblog.com/index.php/django-tutorial-for-beginners/

In this post, we’ll create some optional features for our website. If you are not interested, just skip to the end of this post and start preparing for deployment.

Pagination

img

When we add more and more posts to our blog, creating a paginator might be a good idea, since we don’t want to have too many posts on one page.

To do that, we need to add some extra code to our views. Let’s take the home view has an example.

Import necessary packages:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
Enter fullscreen mode Exit fullscreen mode

Update home view:

def home(request):
    page = request.GET.get('page', '')
    posts_list = Post.objects.all()
    paginator = Paginator(posts_list, 1)

    try:
        posts = paginator.page(page)
    except PageNotAnInteger:
        posts = paginator.page(1)
    except EmptyPage:
        posts = paginator.page(paginator.num_pages)

    return render(request, 'blog/home.html', {
        'posts': posts,
    })
Enter fullscreen mode Exit fullscreen mode

Here I striped unnecessary part to avoid confusion, but you need to remember to add them.

Line 2, we get the page number here which we’ll need to use later.

Line 3, get all the posts like we did before.

Line 6 to 11, here we try three different conditions. If the page number is an integer, if the page number is not an integer, and if the page number is empty.

Next, we need to display the paginator like this:

<!-- Pagination -->

{% if posts.has_other_pages %}
<!-- Pagination -->
{% if posts.has_other_pages %}
    <ul class="pagination">
        {% if posts.has_previous %}
            <li class="page-item"><a class="page-link" href="?page={{ posts.previous_page_number }}">&laquo;</a></li>
        {% else %}
            <li class="page-item disabled"><span class="page-link">&laquo;</span></li>
        {% endif %}
        {% for i in posts.paginator.page_range %}
            {% if posts.number == i %}
                <li class="page-item active"><span class="page-link">{{ i }} <span
                        class="sr-only">(current)</span></span></li>
            {% else %}
                <li class="page-item"><a class="page-link" href="?page={{ i }}">{{ i }}</a></li>
            {% endif %}
        {% endfor %}
        {% if posts.has_next %}
            <li class="page-item"><a class="page-link" href="?page={{ posts.next_page_number }}">&raquo;</a></li>
        {% else %}
            <li class="page-item disabled"><span class="page-link">&raquo;</span></li>
        {% endif %}
    </ul>
{% endif %}
Enter fullscreen mode Exit fullscreen mode

Refresh the page and you should see the paginator at the bottom.

img

Related Posts

img

The idea is to get the posts with the same tags.

Update post view:

def post(request, slug):
    requested_post = Post.objects.get(slug=slug)
    post_tags = requested_post.tag.values_list('id', flat=True)
    related_posts = Post.objects.filter(tag__in=post_tags).exclude(id=requested_post.id)

    return render(request, 'blog/post.html', {
        'post': requested_post,
        'related_posts': related_posts,
    })
Enter fullscreen mode Exit fullscreen mode

Line 3, get all the tags that this post has.

Line 4, get all the posts that have at least one of the tags from post_tags, but exclude the same post.

Display the related posts:

<!-- Related Posts -->
<h3>Related Posts</h3>
<div class="row">
    {% for post in related_posts %}
        <div class="col-md-4">
            <div class="card mb-4 box-shadow">
                <img class="card-img-top" src="{{ post.featured_image.url }}" alt="{{ post.title }}">
                <div class="card-body">
                    <h3 class="card-title">{{ post.title }}</h3>
                    <p class="card-text">{{ post.content|striptags|truncatewords_html:25 }}</p>
                    <div class="d-flex justify-content-between align-items-center">
                        <div class="btn-group">
                            <a href="{% url 'post' post.slug %}"
                               class="btn btn-sm btn-outline-secondary">Read
                                More →</a>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    {% endfor %}
</div>
Enter fullscreen mode Exit fullscreen mode

If you are tired of coding, there is always an easy way by using AddThis. They have related posts, share buttons, subscription forms and lots of other tools you may find useful.

Comments

First, register a Disqus account.

img

Create a new site.

img

Follow the instructions and put the code into the right place, and Disqus will take care of the rest.

img

Prepare For Deployment

There are a few things we need to do before deploying our website.

Prepare static and media files. Run the following command:

python manage.py collectstatic
Enter fullscreen mode Exit fullscreen mode

This command will collect all static files from all the apps you created into the staticfiles folder. And now we can delete the static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) from the URL config.

The media files, on the other hand, Django discourages serving media files directly from the server in the production environment. You need to configure your server settings. Take Apache as an example:

Alias /media/ /path/to/mediafiles/

<Directory /path/to/mediafiles/>
Order deny,allow
Allow from all
</Directory>
Enter fullscreen mode Exit fullscreen mode

Notice that /media/ matches the setting for MEDIA_URL, and /path/to/mediafiles/ is the absolute path to the mediafiles/ folder.

Run Deployment Check

Before we deploy our project, we need to check a few things. Go to terminal and run manage.py check --deploy. This command will check the SECRET_KEY, DEBUG, ALLOWED_HOSTS and a few other sensitive settings for you.

Please check your own settings against this documentation: https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/

Discussion (0)

pic
Editor guide