Configuration du projet
Créer un projet et une application
pip install django django-admin startproject mysite cd mysite python manage.py startapp blog
Commandes courantes
runserverDémarrer le serveur de dev sur le port 8000
makemigrationsGénérer les fichiers de migration depuis les modèles
migrateAppliquer les migrations à la base de données
createsuperuserCréer un superutilisateur admin
shellShell Python interactif avec Django
testExécuter la suite de tests
Structure du projet
manage.pyPoint d'entrée CLI
settings.pyConfiguration du projet
urls.pyConfiguration des URL racine
wsgi.py / asgi.pyPoints d'entrée serveur
apps/models.pyModèles de base de données
apps/views.pyGestionnaires de requêtes
Modèles
Définir un modèle
from django.db import models class Post(models.Model): title = models.CharField(max_length=200) body = models.TextField() created = models.DateTimeField(auto_now_add=True) published = models.BooleanField(default=False)
Types de champs
CharField(max_length=N)Texte court (max_length requis)
TextField()Texte long (sans limite)
IntegerField()Valeur entière
FloatField()Nombre à virgule flottante
BooleanField()Vrai / Faux
DateTimeField()Date et heure
EmailField()Email avec validation
FileField(upload_to='')Téléversement de fichier
Relations
author = models.ForeignKey( User, on_delete=models.CASCADE ) tags = models.ManyToManyField(Tag, blank=True) profile = models.OneToOneField(User, on_delete=models.CASCADE)
Meta et méthodes
class Meta: ordering = ['-created'] verbose_name_plural = 'posts' def __str__(self): return self.title
Vues
Vue basée sur une fonction
from django.shortcuts import render, get_object_or_404 def post_list(request): posts = Post.objects.filter(published=True) return render(request, 'blog/list.html', {'posts': posts})
Vues basées sur des classes
from django.views.generic import ListView, DetailView class PostListView(ListView): model = Post template_name = 'blog/list.html' context_object_name = 'posts' paginate_by = 10
CBV courantes
ListViewAfficher une liste d'objets
DetailViewAfficher un seul objet
CreateViewFormulaire pour créer un objet
UpdateViewFormulaire pour modifier un objet
DeleteViewConfirmer et supprimer un objet
TemplateViewRendre un template (sans modèle)
Réponse JSON
from django.http import JsonResponse def api_posts(request): data = list(Post.objects.values('id', 'title')) return JsonResponse(data, safe=False)
Templates
Syntaxe des templates
{{ variable }} {{ post.title|truncatewords:30 }} {% if user.is_authenticated %}

Bienvenue, {{ user.username }} !

{% endif %}
Boucles et conditions
{% for post in posts %}

{{ post.title }}

{% if forloop.last %}
{% endif %} {% empty %}

Aucun article.

{% endfor %}
Héritage de templates
{# base.html #} {% block content %}{% endblock %} {# child.html #} {% extends "base.html" %} {% block content %}

Hello

{% endblock %}
Filtres courants
|date:"Y-m-d"Formater une date
|default:"N/A"Valeur de repli pour les champs vides
|lengthCompter les éléments d'une liste
|truncatewords:NLimiter à N mots
|safeMarquer comme HTML sûr (pas d'échappement)
|slugifyChaîne en minuscules compatible URL
URLs
Patterns d'URL
from django.urls import path, include urlpatterns = [ path('', views.index, name='index'), path('post//', views.detail, name='detail'), path('blog/', include('blog.urls')), ]
Convertisseurs de chemin
<int:pk>Entier (ex. 42)
<str:slug>Chaîne sans barres obliques
<slug:slug>Slug (lettres, chiffres, tirets)
<uuid:id>Format UUID
<path:rest>Chemin complet avec barres obliques
URLs inversées
from django.urls import reverse url = reverse('detail', kwargs={'pk': 1}) # Dans les templates : {% url 'detail' pk=post.pk %}
Formulaires
ModelForm
from django import forms class PostForm(forms.ModelForm): class Meta: model = Post fields = ['title', 'body', 'published']
Traiter le formulaire dans la vue
def create_post(request): form = PostForm(request.POST or None) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.save() return redirect('detail', pk=post.pk) return render(request, 'blog/form.html', {'form': form})
Formulaire dans le template
{% csrf_token %} {{ form.as_p }}
Validation
def clean_title(self): title = self.cleaned_data['title'] if len(title) < 5: raise forms.ValidationError("Titre trop court.") return title
Admin
Enregistrer un modèle
from django.contrib import admin from .models import Post @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ['title', 'author', 'created', 'published'] list_filter = ['published', 'created'] search_fields = ['title', 'body']
Options admin
list_displayColonnes dans la vue liste
list_filterOptions de filtre dans la barre latérale
search_fieldsChamps recherchables
prepopulated_fieldsAuto-remplissage (ex. slug depuis le titre)
readonly_fieldsNon modifiables dans l'admin
orderingOrdre de tri par défaut
Requêtes ORM
Requêtes de base
Post.objects.all() # tous les enregistrements Post.objects.get(pk=1) # unique (lève une exception si absent) Post.objects.filter(published=True) # queryset Post.objects.exclude(draft=True) # exclure les correspondances Post.objects.count() # nombre total
Lookups de champs
field__exactCorrespondance exacte (par défaut)
field__icontainsContient sans distinction de casse
field__gt / __ltSupérieur / inférieur à
field__gte / __lteSupérieur/inférieur ou égal à
field__in=[1,2,3]Valeur dans la liste
field__isnull=TrueEst NULL
field__startswithCommence par une chaîne
field__range=(a,b)Entre a et b inclus
Chaînage et agrégation
from django.db.models import Q, Count, Avg Post.objects.filter( Q(title__icontains='django') | Q(body__icontains='django') ).order_by('-created')[:10] Post.objects.aggregate(avg_views=Avg('views'))
Créer, mettre à jour, supprimer
post = Post.objects.create(title='New', body='...') post.title = 'Updated' post.save() Post.objects.filter(draft=True).update(published=False) post.delete()
Authentification
Connexion / Déconnexion
from django.contrib.auth import authenticate, login, logout user = authenticate(request, username='admin', password='pw') if user is not None: login(request, user)
Protéger les vues
from django.contrib.auth.decorators import login_required @login_required def dashboard(request): return render(request, 'dashboard.html')
URLs d'auth
# urls.py path('accounts/', include('django.contrib.auth.urls')) # Fournit : login, logout, password_change, password_reset
Auth dans les templates
{% if user.is_authenticated %}

Bonjour, {{ user.username }}

Déconnexion {% else %} Connexion {% endif %}
Paramètres
Paramètres clés
DEBUGTrue en développement, False en production
ALLOWED_HOSTSListe des noms d'hôtes valides
SECRET_KEYClé de signature cryptographique (à garder secrète)
DATABASESMoteur DB, nom, hôte, identifiants
INSTALLED_APPSListe des applications enregistrées
STATIC_URLPréfixe URL pour les fichiers statiques
MEDIA_URL / MEDIA_ROOTChemins des fichiers uploadés par les utilisateurs
Config base de données
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'mydb', 'USER': 'dbuser', 'HOST': 'localhost', 'PORT': '5432', } }
Fichiers statiques
STATIC_URL = '/static/' STATICFILES_DIRS = [BASE_DIR / 'static'] # Dans les templates : {% load static %} #