Thursday, 8 July 2021

*Episode 14* PYTHON (Create a Detail Page of Django)



Creating a detail page


This episode covers :-


 1) How to add a detail page.

 2) How to create slugs.

 3) How to return canonical URLs with get_absolute_url().

 4) How to reverse URLS.

 5) How to use the {% url %} template tag.


  •  Setup :-

Terminal

cp -fr 15-Base-Project 16-Detail-Page

cd 16-Detail-Page

source ../venv/bin/activate


  •  Adding a detail page path :-

     Edit mysite app urls.py file and add a path to the detail page:

mysite/urls.py

urlpatterns = [

path('admin/', admin.site.urls),

path('flower/<int:id>/', myapp_views.detail, name='deta\

il'), # < here

path('', myapp_views.index, name='index'),

]


  •  Creating the detail view :-

     Edit myapp views.py file and add the detail function:

myapp/views.py

from django.shortcuts import render, get_object_or_404 # < \

here

from .models import Flower

def index(request):

flowers = Flower.objects.all()

return render(request, 'myapp/index.html', {'flowers': \

flowers})

def detail(request, id=None): # < here

flower = get_object_or_404(Flower, id=id)

return render(request, 'myapp/detail.html', {'flower': \

flower})


        Make sure to import get_object_or_404.


  •  Creating the detail page template :-


     Create detail.html file in the myapp templates folder:

Detail page template

├── 16-Detail-Page

│ ├── myapp

│ │ ├── templates

│ │ │ └── myapp

│ │ │ ├── detail.html # < here


     Fill it with these lines:

myapp/templates/myapp/detail.py

{% extends 'base/base.html' %}

{% block content %}

<div class="jumbotron">

<div class="container">

<h1 class="display-3">{{ flower.title }}</h1>

<div class="lead">{{ flower.description }}</div>

</div>

</div>

<a href="">Back<a>

{% endblock %}


    Visit http://127.0.0.1:8000flower1/ and you should see the detail page jumbotron:




  •  Creating slugs :-

     Accessing individual flowers with an id is not the most friendly approach. Let’s add a SlugField to hold a human-readable path.

     Edit myapp models.py file and add a SlugField:

myapp/models.py

from django.utils.text import slugify # < here

from django.db import models

class Flower(models.Model):

title = models.CharField(max_length=255, default='')

description = models.TextField(default='')

slug = models.SlugField(blank=True, default='') # < here

def __str__(self):

return self.title

def save(self, *args, **kwargs): # < here

self.slug = slugify(self.title)

super(Flower, self).save()


      We create the slug using the slugify() function in the save method.

      Edit the detail function in the myapp views.py file and change all id occurrences to slug:

myapp/views.py

def detail(request, slug=None): # < here

flower = get_object_or_404(Flower, slug=slug) # < here

return render(request, 'myapp/detail.html', {'flower': \

flower})


  •  Updating the path :-

     Edit mysite app urls.py file and change the detail path:

mysite/urls.py

#path('flower/<int:id>/', myapp_views.detail, name='detail'\

),

path('flower/<slug:slug>/', myapp_views.detail, name='detai\

l'),


Run migrations:


Terminal

python manage.py makemigrations

python manage.py migrate


     Edit all flowers you have created and save them once to generate slugs.


  •  Defining get_absolute_url() method :-

     We can add a “View on site” link to the admin by defining a get_absolute_url method. Edit myapp models.py file and add the method to the Flower class:

myapp/models.py

from django.utils.text import slugify

from django.db import models

from django.urls import reverse # < here

class Flower(models.Model):

...

def __str__(self):

...

def save(self, *args, **kwargs):

...

def get_absolute_url(self): # < here

return reverse('detail', args=[str(self.slug)])


      Edit a Flower object and you will see a link on the top right corner. Click it to visit the flower detail page:



  •  Using url tag :-

     Edit myapp index.html file and use the url tag to link the card to the detail page:

myapp/templates/myapp/index.html

<h5 class="card-title"><a href="{% url 'detail' flower.slug\

%}">{{ flower.title }}</a></h5>


     Note: make sure that each flower has a slug by editing and saving them once.


     Visit the frontpage and click a title to see the detail page.


  •  In Details :-

Capturing URL values :-


     You can use angle brackets to capture values from the URL. In here we first captured the id number and then the slug:

mysite/urls.py

#path('flower/<int:id>/', myapp_views.detail, name='detail'\

),

path('flower/<slug:slug>/', myapp_views.detail, name='detai\

l'),


     You can optionally specify a converter type. int converter type in <int:id>means that the path matches only integers.


Using view parameters :-


     In the myapp views.py file we specify a slug parameter. The slug from the URL will be stored in this variable. slug=None means that the default value is None if a parameter is not passed to this view.

myapp/views.py

def detail(request, slug=None):


    get_object_or_404 returns “404 Page not Found” error if the object doesn’t exist. Otherwise the object with the slug from the URL parameter will be stored in the flower object:

myapp/views.py

flower = get_object_or_404(Flower, slug=slug)


Explaining slugs :-


      Slug is a short label that contains only letters, numbers, underscores or hyphens. It’s often used to offer user-friendly URLS. “productmacbook/” is better than “product-113zxc/”. In our app we use the title field to create the slug.


      In the myapp models.py we add the SlugField and specify blank=True so that the field can be empty for the save() method to run:

myapp/models.py

slug = models.SlugField(blank=True, default='')


       Slugify function converts strings to URL slugs. You can find it indjango.utils.text:

myapp/models.py

from django.utils.text import slugify


     You can override predefined model methods like save():

myapp/models.py

def save(self, *args, **kwargs):

self.slug = slugify(self.title)

super(Flower, self).save()


     In the save() method we can make something happen when the object is saved. In this case we use it to generate a slug.


    We have to call the superclass method super() so that the save method default behaviour will be executed and the object stored in the database.


    *args and **kwargs allow you to collect arguments or keyword arguments and pass them to the function. This is a Python concept we don’t explore in this book.



  •  Reversing URLS :-

     You can define get_absolute_url method to calculate a canonical URL for an object. In here we use the reverse() function to get the URL to a flower object:

myapp/models.py

def get_absolute_url(self):

return reverse('detail', args=[str(self.slug)])


     The reverse function is similar to the url tag that we used with the card markup. In here we pass the detail path name “detail” and the slug as a parameter to it.


     If you have a path like this…

mysite/urls.py

path('flower', myapp_views.detail, name=detail),


     … then reverse('detail') will generate flower.


     If you have a path like this…

mysit/urls.py

path('flower/<slug:slug>/', myapp_views.detail, name='detai\

l'),


    … then reverse('detail', args=[str(self.slug)]) will generate a path like

this floweramelanchier-asiatica/.


Summary


  •  Use angle brackets with paths to capture URL values: 'flower/<slug:slug>/'.
  •  get_object_or_404() tries to fetch an object but returns a “Page not Found” error if the object is not found.
  •  SlugField can be used to store a user-friendly path.
  •  It’s useful to define the get_absolute_url() method for a model to have an easy access to canonical URLS.
  •  Use {% url %} tag or {{ object.get_absolute_url }} in templates instead of hardcoding URLS.

👈Episode 13(P).                                                                           Episode 15(P)👉
Share This Post

PRINT THIS POST

No comments:

Post a Comment

If you have any doubts. Please let me know.

Featured post

*Episode 1* MCQ for Govt. Job/ Private Job/ MNCs

  Topic:- One Word Substitution 1) Especially skilled in storytelling  Answer:- Raconteur 2) Fear of loneliness Answer:- Eremophobia  3) Usa...