Skip to content

Django

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. Built by experienced developers, it takes care of much of the hassle of Web development, so you can focus on writing your app without needing to reinvent the wheel. It’s free and open source.

Useful Links:

Install Django

You need python and pip installed in your system

In Terminal

python --version

pip --version

pip install django

Start a project with Django

after you installed django, the django-admin command will be available, try to run your server

In Terminal

django-admin startproject project_name

cd project_name

python manage.py runserver 8000

Let’s look at project_name structure. there is only 2 important files here:

  • settings.py : django project setting/configuration
  • urls.py : the table of content, contain routes

Create application with Django

What’s the difference between a project and an app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a small poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps

In Terminal

python manage.py startapp app_name

Structure

those are the important files

app_name/
    __init__.py
    admin.py
    apps.py
    migrations/
        __init__.py
    models.py           ---> our data persistance
    tests.py
    urls.py             ---> where routes lives
    views.py            ---> where views functions goes (controllers)

Configuration

after creating our app we must add it to the INSTALLED_APPS array in the settings.py of our project

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app_name', #<--------> add this
]

In Terminal

mkdir templates

# in settings.py
# in TEMPLATES list
# we must set the proprety DIRS like this
'DIRS': [os.path.join(BASE_DIR, 'templates')]

the best practices says : for every app we have: make sure to create a folder with the app_name under templates

views

django view can return 3 things HttpResponse, JsonResponse or a html page, lets create those 3 types

#in views.py of the application

from django.http import HttpResponse, JsonResponse
from django.shortcuts import render

def example_http(request):
  return HttpResponse("hello from your example app")

def example_http_with_param(request, id):
  return HttpResponse("hello from your example app with id = {}".format(id))

def example_json(request):
  data = [
    {'id': 1, 'name': 'example1'},
    {'id': 2, 'name': 'example2'}
  ]
  return JsonResponse(data, safe=False)

def example_html(request):
  return render(request, 'exampleapp/example.html')

routes

to access your views you must add routes a route for eath view

#in urls.py of the application

from django.urls import path

from . import views

app_name = 'exampleapp'
urlpatterns = [
  path('http/', views.example_http, name='http_example'),
  path('http/<int:id>/', views.example_http_with_param, name='http_example_with_param'),
  path('json/', views.example_json, name='json_example'),
  path('html/', views.example_html, name='html_example'),
]

until now our views are not accessible, we must plug the project routes with the application route.

#in urls.py of the project

from django.urls import include # add this import
path('example/', include('exampleapp.urls')), # add this line

Get your hands dirty with templates

Configuration

we must configure the static folder

# in settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"),]


# in urls.py of the project
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)


#in templates
{% load static %}
<img src="{% static "my_app/example.jpg" %}" alt="My image">

Data and templates

we need to pass data to our template first

def example_html(request):
  dictionary = {
    'display': True,
    'students': [
      {'fullname': 'flen ben flen 1', 'level': 1},
      {'fullname': 'flen ben flen 2', 'level': 2},
      {'fullname': 'flen ben flen 3', 'level': 3}
    ]
  }
  return render(request, 'exampleapp/example.html', dictionary)

then we can use it in the html

{% if display == True %}
    <ul>
    {% for student in students %}
        <li>{{ student.fullname }} - {{ student.level }}</li>
    {% endfor %}
    </ul>
{% endif %}

paths in templates

to make links between pages we must use the routes already created

<a href="{% url 'app_name:route_name' route_param %}">click here</a>

<a href="{% url 'exampleapp:http_example' %}">click here</a>
<a href="{% url 'exampleapp:http_example_with_param' id %}">click here</a>
<a href="{% url 'exampleapp:json_example' %}">click here</a>
<a href="{% url 'exampleapp:html_example' %}">click here</a>

Template inheritance

inheritance of template is used to avaoid code duplication, and clean your code first of all you must set the layout (a htmlpage with blocks) that you will extend

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

<head>
    <title>{% block title %}{% endblock %}</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    {% load static %}
    <link rel="stylesheet" href="{% static "css/bootstrap.min.css" %}">
    <link rel="stylesheet" href="{% static "css/yeti.min.css" %}">
    {% block stylesheets %}{% endblock %}
</head>

<body>
    {% block content %}{% endblock %}

    <script src="{% static "js/jquery.min.js" %}"></script>
    <script src="{% static "js/popper.min.js" %}"></script>
    <script src="{% static "js/bootstrap.min.js" %}"></script>
    {% block javascript %}{% endblock %}
</body>

</html>

and then create a page that extend the layout

{% extends 'layout.html' %}

{% block title %}Example app{% endblock %}

{% block content %}
  <div class="container mt-5">
    <h1>Hello World</h1>
  </div>
{% endblock %}

Django data

django come with a strong ORM (object-relational-mapping) in this section we will use it.

models

this link contain all the possible fields of any model (https://docs.djangoproject.com/en/3.0/topics/db/models/)

#example of a model

from django.db import models


class Event(models.Model):
    name = models.CharField(max_length=120, null=False, blank=False)
    event_date = models.DateTimeField(null=False, blank=False)
    venue = models.CharField(max_length=120, null=False, blank=False)
    description = models.TextField(null=False, blank=False)

models relations

This link contain all the possible models relations (https://hackernoon.com/django-orm-relationships-cheat-sheet-14433d6cf68c)

migrations

In Terminal

python manage.py makemigrations

python manage.py migrate

ORM methods

in general the orm methods will be used in our views to get data from the DB and pass it to the templates

#get many
Model.objects.all()
Model.objects.filter(Field=Value)

#get One
Model.objects.get(id=1)
Model.objects.get(pk=1)
Model.objects.get(field=Value)

#save a record
d = Model(field=Value, Field=Value) #here you must set the mandatory fields
d.save()

#update a record
d.field = Value
d.save()

#delete a record
d2 = Model.objects.get(pk=1)
d2.delete()

#count
Model.objects.all().count()

users and admin site

django came with a predefined Back-office which is the admin site. in the admin site we must add our models that need to be managed

# in the admin.py of our application

from .models import Event  #import your model
admin.site.register(Event) # register your model
but the admin site need to be managed by a user, so we need our superadmin user

In Terminal

python manage.py createsuperuser

Django form

handling from is very easy in django, simply you must create a form in the template and then recieve the fields in a view

<form action="{% url 'app_name:route_name' %}" method="post">
    {% csrf_token %}
    <input type="text" name="x" value="" placeholder="add an x">
    <input type="submit" value="Add">
</form>

#import reverse from django.urls
#import HttpResponseRedirect from django.http

def add(request):
    x = request.POST.get('x')
    return HttpResponseRedirect(reverse('app_name:route_name', args=(x,))) #args is mandatory if the route have paramaters

Django users and authentication

here are some useful links for the users and authentication system

authentication Example

here a sample of code: our authentication system based on the user model of django

if the user is_staff so he will be redirected to admin_portal,

if the user is_not_staff he will be redirected to the club_portal

first of all we need our routes

from django.urls import path

from . import views

urlpatterns = [
  path('', views.index, name='index'), # route for the authentication page

  path('club/', views.club, name='club_portal'),  # route for the club space
  path('admin/', views.admin, name='admin_portal'), # route for the admin space

  path('login/', views.login_view, name='login'), # route for login
  path('logout/', views.logout_view, name='logout'), # route for logout
]

then we must code our views

from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse


def index(request):
  if request.user.is_authenticated: # we test if the user already authenticated
    if request.user.is_staff: # make redirection based on is_staff or not
      return HttpResponseRedirect(reverse('admin_portal', args=()))
    elif not request.user.is_staff:
      return HttpResponseRedirect(reverse('club_portal', args=()))
  else: # if the user not authenticated, we must show him the login page
    return render(request, 'login.html')

def login_view(request):
  # get the form params
  username = request.POST.get('username', False)
  password = request.POST.get('password', False)

  user = authenticate(username=username, password=password)   #autheticate
  if user is not None and user.is_active: # if the authetication goes well and the user is active
    login(request, user) # do the login in django sytem
    # make redirection based on user is_staff or not
    # if is_staff --> admin page
    # if not is_staff --> club page
    # otherwise --> login page
    if user.is_staff:
      return HttpResponseRedirect(reverse('admin_portal', args=()))
    elif not user.is_staff:
      return HttpResponseRedirect(reverse('club_portal', args=()))
    else:
      return render(request, 'login.html')

def logout_view(request):
  logout(request)
  return render(request, 'login.html')

def club(request):
  return render(request, 'club.html')

def admin(request):
  return render(request, 'admin.html')

and finally our html pages

<!--login page-->
<form method="post"  role="form" action="{% url 'login' %}">
{% csrf_token %}
<input type="text" name="username" placeholder="Utilisateur">
<input type="password" name="password" placeholder="Mot de passe">
<input type="submit" value="login" />
</form>



<!--club portal-->
{% if user.is_authenticated and not user.is_staff %}
  Hi {{ user.username }}!, you are a club
  <br>
  <a href="{% url 'logout' %}">logout</a>
{% else %}
  <p>You are not logged in</p>
  <a href="{% url 'index' %}">login from here</a>
{% endif %}


<!--admin portal-->
{% if user.is_authenticated and user.is_staff %}
  Hi {{ user.username }}!, you are administrator
  <br>
  <a href="{% url 'logout' %}">logout</a>
{% else %}
  <p>You are not logged in</p>
  <a href="{% url 'index' %}">login from here</a>
{% endif %}