1 - Brief reminder of the previous tutorial: student management with django

To achieve this paging system we will adopt the previous tutorial of student management:

1.1 - Creating a new new app django studentsApp

We start by creating a new django project and a django app called studentsApp

We then create a media directory in our mysite project which will be used to store the downloaded media. This folder needs to be configured in the settings.py file: settings.py

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

Next, let's configure the url.py files of the studentsApp application: urls.py So that the media files or images... are accessible, we must add to the

mysite/urls.py

file the following code:

+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 

Thus our

mysite/urls.py

file becomes:

#mysite/urls.py
from django.contrib import admin
from django.urls import path
from uploadFile import views
from django.conf.urls.static import static
from . import settings

urlpatterns = [
path('admin/', admin.site.urls),
path('student/', views.student),
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Now we need to register our application at the

settings.py

file

INSTALLED_APPS = [
'studentsApp.apps.StudentsappConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

1.2 - Creating a model for studentsApp

Consider the Students model example that we have already covered in the previous tutorial django models, to which we add a file field that allows students to attach their photos during registration:

# studentsApp/models.py
from django.db import models
class Students(models.Model):
name = models.CharField(max_length=25)
email = models.EmailField(max_length=40)
phone = models.IntegerField(max_length=40)
section = models.CharField(max_length=25)
photo = models.FileField(upload_to = 'photos')

The

upload_to = 'photos'

argument that we added tells django that the uploaded files should be saved in a folder named

'media/photos'

. Do you have to manually create this directory? Well don't worry! Django will create it automatically when running the script. 

The necessary migrations are then carried out:

python manage.py makemigrations studentsApp

and then :

python manage.py migrate

1.3 - Creating an insert data form

Now we create a forms.py file which will be used to generate the insert data form: forms.py

# studentsApp/forms.py
from django.forms import ModelForm
from studentsApp.models import Students

class StudentsForm(ModelForm):
class Meta:
model = Students
fields = ['name' , 'email' ,'phone' ,'section' , 'photo']

Regarding views and models, they will be created in the same way as the previous tutorial except to add a

request.FILES

parameter:

1.4 - Creating views for studentsApp

views.py

# studentsApp/views.py
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import StudentsForm

def student(request):
if request.method == 'POST':
form = StudentsForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return HttpResponseRedirect('/student/')
else:
form = StudentsForm()
return render(request, 'student.html', {'form': form})

2 - Pagination system

2.1 - The Paginator class

Django

provides a class called

Paginator

which performs

pagination

. It is located in the

django.core.paginator

module. The Paginator class is instantiated with two parameters: the list of objects to spread and the maximum number of objects to display per page. So first we have to import it: We start by importing the Paginator class and related classes:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

  1. The Paginator class is located at:
    django/core/paginator.py

    . This is a class allowing to paging a list of data with links to first page last page, Previous/Next... 

  2. The EmptyPage class: class used to throw an exception if the page is not found, especially when the indexing limit is exceeded.  
  3. The PageNotInteger class: class used to throw an exception if the index of the requested page is not an integer.

We then create an object:

objectlist

which contains the student data as a list:

object_list = Students.objects.all()

We then create a

Paginator object

whose parameter will be the object:

object_list

and the number of elements per page to display:

paginator = Paginator(object_list, 3)

We then retrieve the number of the current page we are on:

page_number = request.GET.get('page')

We then create exceptions if the requested page is not found, or if the requested page number is not an integer:

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

Here is finally the code of the views.py file:

# studentsApp/views.py
from django.shortcuts import render, redirect
from .forms import StudentsForm
from .models import Students
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

def students(request):
if request.method=='POST':
form = StudentsForm(request.POST,request.FILES)
if form.is_valid():
form.save()
return redirect('students')
else:
form = StudentsForm()

# Pagination
object_list = Students.objects.all()
paginator = Paginator(object_list, 2)
page_number = request.GET.get('page') # get current page number

try:
page_object = paginator.page(page_number)
except PageNotAnInteger:
page_object = paginator.page(1) # go to page number 1
except EmptyPage: # except last page
# stay on current page
page_object = paginator.page(paginator.num_pages)

return render(request, 'students.html', {'form': form, 'page_obj': page_object})

Load Pagination system in the template

<!-- Load pagination system -->
<div style="font-size:20px;">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}

Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.

{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</div>

Code final of pagination in the template:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>Manage students </h2>

<!-- load form -->
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn−default">Save</button>
</form>
<br />

<table border='1' style = 'border-collapse:collapse;' width="600">
<thead>

<th>Name</th> <th>Email</th> <th>Phone</th> <th>Section</th> <th>Photo</th>

</thead>
<tbody>
<!-- load students data -->
{% for stud in page_obj %}
<tr>
<td>{{ stud.name }}</td>
<td>{{ stud.email }}</td>
<td>{{ stud.phone }}</td>
<td>{{ stud.section }}</td>
<td width="96"><img src = "/media/{{stud.photo }}" width = "96" height = "86"></td>
</tr>
{% endfor %}

</tbody>
</table>

<!-- Load pagination system -->
<div style="font-size:20px;">
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}

Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.

{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
</div><br />

</body>
</html>

.

Younes Derfoufi
my-courses.net

Leave a Reply