Django: Multiple Pagination in a single Template

Assuming you would like to display two models in the same template each with their own pagination, here’s how to do it.

views.py

def myview():
        Model_one = Model.objects.all()
        paginator = Paginator(Model_one, 6)
        page = request.GET.get('page1')
        try:
            Model_one = paginator.page(page)
        except PageNotAnInteger:
            Model_one = paginator.page(1)
        except EmptyPage:
            Model_one = paginator.page(paginator.num_pages)

        Model_two = Model_other.objects.all()
        paginator = Paginator(Model_two, 6)
        page = request.GET.get('page2')
        try:
            Model_two = paginator.page(page)
        except PageNotAnInteger:
            Model_two = paginator.page(1)
        except EmptyPage:
            Model_two = paginator.page(paginator.num_pages)

        context = {'Model_one': Model_one, 'Model_two': Model_two}
        return render(request, 'template.html', context)

The important thing above is the ‘page1’ and ‘page2’.

In the template,

{% if model_one %}
          <div class="col-md-12 well">
            {% for item in model_one %}
            ..... iterates through model_one.....
            {% endfor %}
            <span class="step-links pagination">
                {% if model_one.has_previous %}
                    <a href="?page1={{ model_one.previous_page_number }}"> previous </a>
                {% endif %}
                <span class="current">
                    Page {{ model_one.number }} of {{ model_one.paginator.num_pages }}
                </span>
                {% if model_one.has_next %}
                    <a href="?page1={{ model_one.next_page_number }}"> next </a>
                {% endif %}
            </span>
          </div>
          {% endif %}
          {% if model_two %}
          <div class="col-md-12 well">
            {% for item in model_two %}
            ..... iterates through model_two.....
            {% endfor %}
            <span class="step-links pagination">
                {% if model_two.has_previous %}
                    <a href="?page2={{ model_two.previous_page_number }}"> previous 
                {% endif %}
                <span class="current">
                    Page {{ model_two.number }} of {{ model_two.paginator.num_pages }}
                </span>
                {% if model_two.has_next %}
                    <a href="?page2={{ model_two.next_page_number }}"> next </a>
                {% endif %}
            </span>
          </div>
          {% endif %}

Again using ‘page1’ and ‘page2’ to distinguish the pagination for each model.

Django-allauth Installation

There is a useful django-allauth video tutorial at Create third party Facebook login in Django. The document below simply follows that but only adds facebook social authentication. Documentation can be found at django-alluth documentation. django-allauth can also be installed by cloning from https://github.com/pennersr/django-allauth
I am running Django 1.9.5 and will install django-allauth 0.25.2 Setup a virtual environment if you haven’t already.

$ pip install django-allauth

Check the packages in your virtual environment with,

$ pip list

You can install the packages in requirements.txt to your virtual environment or whatever environment you are in with,

$ pip install -r requirements.txt

Put the packages in your virtual environment into your requirements.txt file with,

$ pip freeze -> requirements.txt

For this example the django project name is `crudProject’ and the app name is `crudapp’. In settings.py add appropriately to TEMPLATES so that it looks like this,

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.template.context_processors.request',
            ],
        },
    },
]

Bear in mind,

'django.template.context_processors.request',

may already be in the `context_processors’
Then add to settings.py,

AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth`
    'django.contrib.auth.backends.ModelBackend',

    # `allauth` specific authentication methods, such as login by e-mail
    'allauth.account.auth_backends.AuthenticationBackend',
)

Then add to INSTALLED_APPS

INSTALLED_APPS = (
    ...
    # The Django sites framework is required
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    'allauth.socialaccount.providers.facebook',
)

and also add to settings.py,

SITE_ID = 1

To urlpatterns = […] in urls.py add,

url(r'^accounts/', include('allauth.urls')),

To see the accounts urls available to you go to localhost:8000/accounts/ be sure not to omit the trailing ‘/’.
Next run a migrate,

$ python manage.py migrate
python manag.py runserver

And go to localhost:8000/accounts/admin You should see in admin, ACCOUNTS, SITES and SOCIALACCOUNTS.
Selection_015

 

We need to go to the Facebook Developer Site. Signup to get account or login with your Facebook credentials if you already have a Facebook account.
In the `My Apps’ pull down menu select `Add a New App’
Selection_016

 

and then click on `Website`
Selection_017

Put in the name of your app which in my case is `crudapp`

 

Selection_018

then continue to `Create New Facebook App ID`. You’ll be asked for an email after that, choose a category for your app. Choose `Education’. Next click `Create App ID`

 

Selection_019

Skipped down to the bottom of the page

 

Selection_021
and for `Site URL:’ Put in localhost:8000, then click `Next’.
Then choose `Login’

 

Selection_022

 

Then go to the `Apps’ pulldown menu at the top right of the page and choose `crudapp`. This should take you to the app’s dashboard and you should see the app ID and secret key which you can reveal my clicking on the `Show’ button.

 

Selection_023

Now go back to your browser and navigate to localhost:8000/admin and go into `SITES` and click on `example.com`

 

Selection_024

 

Change the `Domain name` and `Display name` to the following,

Selection_025
Now localhost:800 has site ID: 1. Back in the admin home click on `Social applications’ under `SOCIALACCOUNTS’.

 

Selection_026
Next click `ADD SOCIAL APPLICATION` which is over on the top right of the screen. Fill in the `Provider`, `Name` and the `Client id` and `Secret key` which we looked at on the facebook developer site. Click the `localhost:8000` under `Available sites`.

 

Selection_027
Move `localhost:8000` across from `Available sites` to `Chosen sites` by clicking the little right arrow between them, while it is highlighted.

 

Selection_029
Then click `SAVE` at the bottom right of the page. Now logout of `admin and navigate to http://localhost:8000/accounts/login`
This should bring up a simple unstyled form,

 

Selection_030
You need to return to the Facebook developer site and under `App Review` set to `Yes` under `Make crudapp public?`

 

Selection_031
Logout of the Facebook developer site and all Facebook accounts and go back to http://localhost:8000/accounts/login/
This will bring you to http://localhost:8000/accounts/loggedin/#_=_ where you will see `Page not found (404)`. To correct this,
In settings.py add,

LOGIN_REDIRECT_URL = '/'

to redirect to the homepage after login.
Next add to your app the a `templates` directory and inside that a directory called `account`. In your directory where you setup your virtual environment you will find a lib directory from there go to,

lib/python2.7/site-packages/allauth/templates

where you should find a base.html templates file copy this to your app/templates directory.

$ cp base.html ~/djangoForum/djangoForum/crudapp/templates/

Then change directory into `account` and you will see html template files for login.html, logout.html, signup.html etc. These files need to be copied to your app’s templates/account directory.

$ cp -r * ~/djangoForum/djangoForum/crudapp/templates/account/

You can now style these templates.

Access the Python shell

Access the Python shell with,

$ python manage.py shell

This will take you to a Python shell which should look like this,
Selection_032
However,

$ python manage.py dbshell

will take you to a ‘sqlite’ shell if it is installed, which looks like this,
Selection_033
This can also be accessed outside of Django with,

$ sqlite3

Selection_034
So continuing now in the Python shell (not dbshell) connect with the models in your app using,

>>> from <appname>.models import <model1>, <model2>

Have a look at everything in the models1

models.objects.all()

Part 6: Django CRUD, Update

Continued from Part 5: Django CRUD, Delete

Full code on https://github.com/shanegibney/djangoCRUD

We may wish to update the model ‘Members’. Let us start by adding an edit icon to the table in ‘index.html’.

<td><a href="{% url 'edit_new' item.id %}"><span class="glyphicon glyphicon-pencil"></span></a></td>

If you are not using Bootstrap replace the span tags with ‘edit’.

<td><a href="{% url 'edit_new' item.id %}">edit</a></td>

This will bring us to a url named ‘edit_new’ and also will pass the ‘id’. Create this url in urls.py,

url(r'^edit/(?P\d+)/$', home.edit_new, name='edit_new'),

Django then brings us to the view ‘edit_new’ which we will now create in ‘views.py’,

def edit_new(request, id):
    post = get_object_or_404(Members, pk=id)
    if request.method == "POST":
        form = MemberForm(request.POST, instance=post)
        if form.is_valid():
            post = form.save(commit=False) 
            post.save()
            return redirect('init')
    else:
        form = MemberForm(instance=post)
    return render(request, 'member_edit.html', {'form': form})

This is almost identical to the view ‘member_new’ which we used to create a new instance of the model ‘Members’. But this time we use ‘id’ and ‘pk=id’. Again we the ‘.save()’ method to update the model. It is important to use ‘instance=post’ so that the ‘else’ part of the if statement return the current instance of the model ‘Members’ to ‘edit.html’, otherwise we will have a blank form and nothing to edit.
Django then passes the dictionary {‘form’:form} to ‘member_edit.html’ and everything after that works the same as it did when we used the from to create an instance of the model ‘Members’.
This completes the ‘U’ for ‘update’ in CRUD.

Part 5: Django CRUD, Delete

Continued from Part 4: Django CRUD, Create

Full code on https://github.com/shanegibney/djangoCRUD

Next we will delete an instance, or row from the model ‘Members’. First we will place an icon at the end of the row in the table, which we want to delete. Add the following data cell to the table in ‘index.html’,

<td><a href="{% url 'delete_new' item.id %}"><span class="glyphicon glyphicon-trash"></span></a></td>

If you are not using Bootstrap simply replace the span tags with ‘Delete’.

<td><a href="{% url 'delete_new' item.id %}">Delete</a></td>

We can see here that the hyper-link takes us to a url called ‘delete_new’. Also the ‘id’ of the row is passed. We need to create this url in ‘urls.py’ add the following,

url(r'^delete/(?P\d+)/$', home.delete_new, name='delete_new'),

This creates a url for example ‘delete/27’ where 27 is the ‘id’ and this is then passed to the view ‘delete_new’.
Let’s create this view in ‘views.py’. We will need to import ‘get_object_or_404’.

from django.shortcuts import render, get_object_or_404
........
 
def delete_new(request, id):
     post = get_object_or_404(Members, pk=id)
     post.delete()
     return redirect(init)

Here we see that we have passed ‘id’ along with ‘request’. ‘post’ is passed the instance of the ‘Members’ model with pk=id. This object ‘post’ has a method ‘.delete()’, which in the case deletes an instance of the ‘Members’ model. An instance of a class, i.e. ‘Members’ is a row in the database. Next we use ‘redirect’ to go back to the ‘init’ view which renders ‘index.html’.

Now we have an example of the ‘D’ for ‘delete’ in CRUD.

Part 6: Django CRUD, Update

Part 4: Django CRUD, Create

Continued from Part 3: Django CRUD, Display Models

Full code on https://github.com/shanegibney/djangoCRUD

Before starting this section it would be a good idea to include Bootstrap to make use of the classes in the html, but it is not necessary. It is only to make it look nice! To do that add the following lines inside the head tags of index.html.

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css">

CRUD is an acronym for Create, Read, Update and Delete. First we would like to make a form and send this data to the database or our ‘Members’ model. This will be the Create part of CRUD.
First we need to create a form. But to do that we need to tell Django which fields from the model members to put in the form. Create a new file called ‘forms.py’ and place it in the same place as ‘models.py’.

‘forms.py’ must import forms from Django and your model Members from models. This done by adding to the top of ‘forms.py’

from django import forms
from .models import Members

We create a new model here for the form, but it takes from the current model ‘Members’. This is done with a ‘class Meta’ and we can choose which fields from ‘Members’ we want in the form,

 class MemberForm(forms.ModelForm):
    class Meta:
        model = Members
        # which fields to put in form
        fields = ('first_name', 'last_name', 'description')

We need a link to the url which we are calling ‘member_new’. So in urls.py add in,

url(r'^post/new/$', home.member_new, name='member_new'),

This gives the url a name of ‘member_new’. To get to this url you need a hyper-link in ‘index.html’,

<a href="{% url 'member_new' %}">Add a post</a>

This causes Django to look in urls.py for a url named ‘member_new’ where it is associated with the url ‘post/new/’. Note that is not actually a path called ‘post/new/’. Then Django looks through all these urls again to find the url ‘post/new/’ and see what view it is associated with. In this case the view is ‘home.members_new’. Now will create this view in ‘views.py’,

def member_new(request):

Django first checks if the “POST” method exists. Of course it doesn’t because we haven’t used a form yet. Therefore this section is ignored and Django carries on to the ‘else’.

    if request.method == "POST":
        ..... we will come here after the form is sent ......
    else:
        form = MemberForm()
    return render(request, 'member_edit.html', {'form': form})

The ‘MemberForm’ which we created earlier and has the fields in it is now passed to ‘form’, and the last line renders ‘member_edit.html’ by sending it {‘form’: form}.
We need to create ‘member_edit.html’ in the templates folder. This file will extend ‘index.html’. To create the form itself we only need to wrap in form tags {{ form.as_p }} like this,

{% extends 'index.html' %}

{% block content %}
    <th1>Member form&lt/h1>
    <form method="POST" class="post-form">{% csrf_token %}
        {{ form.as_p }}in the form
        <button type="submit" class="save btn btn-default">Save<button>
    <form>
{% endblock %}

This creates a block called ‘content’ which will be placed by Django in ‘index.html’ if we add to ‘index.html’ the following,

{% block content %}
{% endblock %}

When you run the server you should have a link on the ‘index.html’ page to a form with fields. But you won’t be able to submit because we haven’t finished writing the view ‘member_new’, which is where this form will submit to.

But this time “POST” does exist and so the if statement is not ignored. We need to fill this view in so that completed it looks like this,

def member_new(request):
    if request.method == "POST":
        form = MemberForm(request.POST)
        if form.is_valid():
            post = form.save(commit=False)
            post.save()
            return redirect('post_detail', pk=post.pk)
    else:
        form = MemberForm()
    return render(request, 'member_edit.html', {'form': form})

Note that we are using ‘redirect’, this needs to be imported by placing the following line at the top of ‘views.py’,

from django.shortcuts import redirect

You can see this passes everything in “POST” to form and validates ‘form’ with ‘.is_valid’. The line ‘form.save…’ saves the form data to memory, not to the database yet. ‘post.save()’ does that. Therefore this is where a new row is added to the database or where the actual ‘create’ in CRUD happens. The next line redirects us to the ‘init’ view. Which recreates the home page and the table of data from the ‘Members’ model.
This concludes the ‘C’ or ‘create’ in CRUD and we have already dealt with the ‘R’ for ‘read’.

Part 5: Django CRUD, Delete

Part 3: Django CRUD, Display Models

Continued from Part 2: Setting up Django, URL’s & Views

Full code on https://github.com/shanegibney/djangoCRUD

Add to the crudapp/models.py file

from django.db import models

In the same file create a model called ‘Members’ with columns for ‘first_name’, ‘last_name’ and ‘description’. This is equivalent to a table called ‘Members’ with fields for ‘first_name’, ‘last_name’ and ‘description’.

class Members(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    description = models.CharField(max_length=600)
    # pub_date = models.DateTimeField('date published')
    def __str__(self):
        return ' '. join([ self.first_name, self.last_name, ])

Give the model an admin interface, in crudapp/admin.py

from .models import Members

admin.site.register(Members)

Go to http://localhost:8000/admin and you will see a model called ‘Memberss’ with effectively rows of the database or as we say in Django instances of the class Member. Note Django places an extra ‘s’ on the class name in admin. Using the Django admin you can now view, edit and delete this model.

Next we will change the cruduapp/views.py file so that it takes data from the model or class Members

from django.shortcuts import render
from .models import Members
# Create your views here.

def init(request):
    details = Members.objects.all()
    context = {'details': details}
    return render(request, 'index.html', context)

This passes all the data in the class Members to index.html where we can display it,

{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
  {% if details %}
  <ul>
    {% for item in details %}
    <li>{{ item.description}}</li>
    {% endfor %}
  </ul>
  {% else %}
  <p>No polls are available.</p>
  {% endif %}
</body>

Part 4: Django CRUD. Create

Part 2: Setting up Django, URLs & Views

Continued from Part 1: Setting up Django and virtualenv
Will will add a url to out crudapp. Add the following into urls.py

...
from crudapp import views as home

urlpatterns = [
    ...
    url(r'^$', home.init),
]

This means when we go to the root url http://localhost:8000 we will be directed to views where Django will look for a function or view called init(). Let us create that next. Add the following to crudapp/views.py

def init(request):
    return render(request, 'index.html')

This will direct us to index.html. However, index.html needs to be created in a new folder called templates. Inside the root folder djangoCRUD create templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>

</head>
<body>
  <p>hello forum</p>
</body>

We have not told Django where the templates folder is. Add

os.path.join(BASE_DIR, "templates")

to settings.py like this,

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, "templates")],
....

Part 3: Django CRUD, Display Models

Accessing an sqlite3 database

To access sqlite3 from the command line.

$ sqlite3

Now you are in the sqlite3 shell. Next connect to an sqlite3 database called db.sqlite3

sqlite> .open db.sqlite3

List tables in database

sqlite> .tables

Let us see what is in the table called table_name

sqlite> select * from table_name;

Not forgetting the trailing semicolon.
Ctrl+D will allow you exit this shell.
To view a table’s field names,

sqlite> PRAGMA table_info(table_name);

To view a table’s schema,

sqlite> .schema table_name

Part 1: Setting up Django and virtualenv

First create a new directory for your project

$ mkdir djangoCRUD

Move to that directory

$ cd djangoCRUD

Set up a virtual environment.

$ virtualenv .

$ source bin/activate

Use pip list to see the modules in this virtual environment.

$ pip list

Now we can install the Django package

$ pip install django

Run pip list again and you will see that django is now part of this environment.

If requested to do so, it is a good idea to upgrade pip,

$ pip install --upgrade pip

Next set up your Django project

$ django-admin startproject crudProject

Change directory into your Django project directory,

$ cd crudProject

Now create an app for your project. To do this you must be in the same directory as the manage.py file.

$ python manage.py startapp crudapp

Note: it is also possible to start a new app using with,

$ django-admin startapp crudapp

Make the database tables with,

$ python manage.py makemigrations
$ python manage.py migrate

After this has been done we can create a super user.

$ python manage.py createsuperuser

Next we will turn on the server,

$ python manage.py runserver

Navigate in your browser to localhost:8000

sqlite is the default database. Ignore the following if you do not want to use a mysql database.
Presuming you have a mysql database set up and running with a user associated with it then in mysite/settings.py

DATABASES = {
    `default' = {
        `ENGINE' : `django.db.backends.mysql',
        `NAME' : `&lt db-name>',
        `USER' : `&lt db-user>',
        `PASSWORD' : `&lt password>',
        `HOST' : `localhost', 
        `PORT' : `',
   }
}

Part 2: Setting up Django, URLs & Views