Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Django 5 By Example

You're reading from   Django 5 By Example Build powerful and reliable Python web applications from scratch

Arrow left icon
Product type Paperback
Published in Apr 2024
Publisher Packt
ISBN-13 9781805125457
Length 820 pages
Edition 5th Edition
Languages
Tools
Arrow right icon
Author (1):
Arrow left icon
Antonio Melé Antonio Melé
Author Profile Icon Antonio Melé
Antonio Melé
Arrow right icon
View More author details
Toc

Table of Contents (20) Chapters Close

Preface 1. Building a Blog Application 2. Enhancing Your Blog and Adding Social Features FREE CHAPTER 3. Extending Your Blog Application 4. Building a Social Website 5. Implementing Social Authentication 6. Sharing Content on Your Website 7. Tracking User Actions 8. Building an Online Shop 9. Managing Payments and Orders 10. Extending Your Shop 11. Adding Internationalization to Your Shop 12. Building an E-Learning Platform 13. Creating a Content Management System 14. Rendering and Caching Content 15. Building an API 16. Building a Chat Server 17. Going Live 18. Other Books You May Enjoy
19. Index

Building list and detail views

Now that you understand how to use the ORM, you are ready to build the views of the blog application. A Django view is just a Python function that receives a web request and returns a web response. All the logic to return the desired response goes inside the view.

First, you will create your application views, then you will define a URL pattern for each view, and finally, you will create HTML templates to render the data generated by the views. Each view will render a template, passing variables to it, and will return an HTTP response with the rendered output.

Creating list and detail views

Let’s start by creating a view to display the list of posts.

Edit the views.py file of the blog application and make it look like this; the new lines are highlighted in bold:

from django.shortcuts import render
from .models import Post
def post_list(request):
    posts = Post.published.all()
    return render(
        request,
        'blog/post/list.html',
        {'posts': posts}
    )

This is our very first Django view. The post_list view takes the request object as the only parameter. This parameter is required by all views.

In this view, we retrieve all the posts with the PUBLISHED status using the published manager that we created previously.

Finally, we use the render() shortcut provided by Django to render the list of posts with the given template. This function takes the request object, the template path, and the context variables to render the given template. It returns an HttpResponse object with the rendered text (normally HTML code).

The render() shortcut takes the request context into account, so any variable set by the template context processors is accessible by the given template. Template context processors are just callables that set variables into the context. You will learn how to use context processors in Chapter 4, Building a Social Website.

Let’s create a second view to display a single post. Add the following function to the views.py file:

from django.http import Http404
def post_detail(request, id):
    try:
        post = Post.published.get(id=id)
    except Post.DoesNotExist:
        raise Http404("No Post found.")
    return render(
        request,
        'blog/post/detail.html',
        {'post': post}
    )

This is the post_detail view. This view takes the id argument of a post. In the view, we try to retrieve the Post object with the given id by calling the get() method on the published manager. We raise an Http404 exception to return an HTTP 404 error if the model DoesNotExist exception is raised because no result is found.

Finally, we use the render() shortcut to render the retrieved post using a template.

Using the get_object_or_404 shortcut

Django provides a shortcut to call get() on a given model manager and raises an Http404 exception instead of a DoesNotExist exception when no object is found.

Edit the views.py file to import the get_object_or_404 shortcut and change the post_detail view, as follows. The new code is highlighted in bold:

from django.shortcuts import get_object_or_404, render
# ...
def post_detail(request, id):
    post = get_object_or_404(
        Post,
        id=id,
        status=Post.Status.PUBLISHED
    )
    return render(
        request,
        'blog/post/detail.html',
        {'post': post}
    )

In the detail view, we now use the get_object_or_404() shortcut to retrieve the desired post. This function retrieves the object that matches the given parameters or an HTTP 404 (not found) exception if no object is found.

Adding URL patterns for your views

URL patterns allow you to map URLs to views. A URL pattern is composed of a string pattern, a view, and, optionally, a name that allows you to name the URL project-wide. Django runs through each URL pattern and stops at the first one that matches the requested URL. Then, Django imports the view of the matching URL pattern and executes it, passing an instance of the HttpRequest class and the keyword or positional arguments.

Create a urls.py file in the directory of the blog application and add the following lines to it:

from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
    # post views
    path('', views.post_list, name='post_list'),
    path('<int:id>/', views.post_detail, name='post_detail'),
]

In the preceding code, you define an application namespace with the app_name variable. This allows you to organize URLs by application and use the name when referring to them. You define two different patterns using the path() function. The first URL pattern doesn’t take any arguments and is mapped to the post_list view. The second pattern is mapped to the post_detail view and takes only one argument id, which matches an integer, set by the path converter int.

You use angle brackets to capture the values from the URL. Any value specified in the URL pattern as <parameter> is captured as a string. You use path converters, such as <int:year>, to specifically match and return an integer. For example <slug:post> would specifically match a slug (a string that can only contain letters, numbers, underscores, or hyphens). You can see all the path converters provided by Django at https://docs.djangoproject.com/en/5.0/topics/http/urls/#path-converters.

If using path() and converters isn’t sufficient for you, you can use re_path() instead to define complex URL patterns with Python regular expressions. You can learn more about defining URL patterns with regular expressions at https://docs.djangoproject.com/en/5.0/ref/urls/#django.urls.re_path. If you haven’t worked with regular expressions before, you might want to take a look at Regular Expression HOWTO, located at https://docs.python.org/3/howto/regex.html, first.

Creating a urls.py file for each application is the best way to make your applications reusable by other projects.

Next, you have to include the URL patterns of the blog application in the main URL patterns of the project.

Edit the urls.py file located in the mysite directory of your project and make it look like the following. The new code is highlighted in bold:

from django.contrib import admin
from django.urls import include, path
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls', namespace='blog')),
]

The new URL pattern defined with include refers to the URL patterns defined in the blog application so that they are included under the blog/ path. You include these patterns under the namespace blog. Namespaces have to be unique across your entire project. Later, you will refer to your blog URLs easily by using the namespace followed by a colon and the URL name, for example, blog:post_list and blog:post_detail. You can learn more about URL namespaces at https://docs.djangoproject.com/en/5.0/topics/http/urls/#url-namespaces.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime