Django 速查表
快速查找 Django 常用语法和配置。
项目管理命令
# 创建项目
django-admin startproject myproject
# 创建应用
python manage.py startapp myapp
# 运行开发服务器
python manage.py runserver
python manage.py runserver 0.0.0.0:8000
# 数据库迁移
python manage.py makemigrations
python manage.py migrate
python manage.py migrate app_name 0001
# 创建管理员
python manage.py createsuperuser
# 进入 Shell
python manage.py shell
# 收集静态文件
python manage.py collectstatic
# 检查项目
python manage.py check
python manage.py check --deploy
# 运行测试
python manage.py test
python manage.py test app_name
python manage.py test app_name.tests.TestClass
模型字段
# 数值类型
models.IntegerField()
models.SmallIntegerField()
models.BigIntegerField()
models.PositiveIntegerField()
models.FloatField()
models.DecimalField(max_digits=10, decimal_places=2)
models.AutoField(primary_key=True)
# 字符串类型
models.CharField(max_length=100)
models.TextField()
models.SlugField()
models.EmailField()
models.URLField()
models.FilePathField()
# 布尔类型
models.BooleanField()
models.BooleanField(default=True)
# 日期时间
models.DateField()
models.TimeField()
models.DateTimeField()
models.DateTimeField(auto_now=True) # 保存时更新
models.DateTimeField(auto_now_add=True) # 创建时设置
models.DurationField()
# 文件类型
models.FileField(upload_to='files/')
models.ImageField(upload_to='images/')
# 其他类型
models.JSONField()
models.UUIDField(default=uuid.uuid4)
models.GenericIPAddressField()
models.BinaryField()
字段参数
# 通用参数
null=True # 数据库允许 NULL
blank=True # 表单允许为空
default=value # 默认值
choices=CHOICES # 选项
unique=True # 唯一约束
db_index=True # 创建索引
verbose_name='名称' # 显示名称
help_text='帮助文本' # 帮助文本
editable=False # 不可编辑
# 关系字段
on_delete=models.CASCADE # 级联删除
on_delete=models.PROTECT # 保护
on_delete=models.SET_NULL # 设为 NULL
on_delete=models.SET_DEFAULT # 设为默认值
related_name='items' # 反向关系名
关系字段
# 多对一(外键)
models.ForeignKey(
'Category',
on_delete=models.CASCADE,
related_name='posts'
)
# 多对多
models.ManyToManyField('Tag', blank=True)
# 一对一
models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name='profile'
)
QuerySet 操作
# 查询
Post.objects.all()
Post.objects.filter(status='published')
Post.objects.exclude(status='draft')
Post.objects.get(pk=1)
Post.objects.get_or_create(title='标题')
Post.objects.first()
Post.objects.last()
# 链式查询
Post.objects.filter(status='published').filter(author=user)
# 排序
Post.objects.order_by('created')
Post.objects.order_by('-created')
# 限制
Post.objects.all()[:10]
Post.objects.all()[10:20]
# 查询表达式
.filter(title__contains='Django')
.filter(title__icontains='django')
.filter(title__startswith='Django')
.filter(title__endswith='教程')
.filter(id__gt=10)
.filter(id__gte=10)
.filter(id__lt=10)
.filter(id__lte=10)
.filter(id__in=[1, 2, 3])
.filter(created__year=2024)
.filter(created__month=1)
.filter(created__day=1)
.filter(category__isnull=True)
.filter(author__username='admin')
# 聚合
from django.db.models import Count, Sum, Avg, Max, Min
Post.objects.aggregate(count=Count('id'))
Post.objects.values('author').annotate(count=Count('id'))
# 创建和更新
Post.objects.create(title='标题', content='内容')
Post.objects.bulk_create([post1, post2])
Post.objects.filter(status='draft').update(status='published')
# 删除
Post.objects.filter(status='draft').delete()
# 关联查询优化
Post.objects.select_related('author', 'category')
Post.objects.prefetch_related('tags')
URL 配置
# 基本路径
path('articles/', views.article_list),
path('article/<int:pk>/', views.article_detail),
path('article/<slug:slug>/', views.article_detail),
# 正则路径
re_path(r'^article/(?P<year>\d{4})/$', views.article_year),
# 包含其他 URLconf
path('blog/', include('blog.urls')),
path('blog/', include('blog.urls', namespace='blog')),
# 反向解析
from django.urls import reverse, reverse_lazy
url = reverse('blog:post_detail', kwargs={'pk': 1})
url = reverse_lazy('blog:post_list')
视图
# 函数视图
def post_list(request):
posts = Post.objects.all()
return render(request, 'blog/post_list.html', {'posts': posts})
# 快捷函数
from django.shortcuts import render, redirect, get_object_or_404
post = get_object_or_404(Post, pk=pk)
return redirect('blog:post_list')
# 类视图
from django.views import View
class PostView(View):
def get(self, request):
pass
def post(self, request):
pass
# 通用视图
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
paginate_by = 10
模板语法
<!-- 变量 -->
{{ title }}
{{ post.title }}
{{ user.username }}
<!-- 过滤器 -->
{{ name|upper }}
{{ name|lower }}
{{ text|truncatewords:30 }}
{{ text|truncatechars:100 }}
{{ date|date:"Y-m-d" }}
{{ price|floatformat:2 }}
{{ value|default:"默认值" }}
{{ html|safe }}
{{ list|length }}
<!-- 条件 -->
{% if user.is_authenticated %}
欢迎,{{ user.username }}
{% else %}
请登录
{% endif %}
{% if score >= 90 %}优秀{% endif %}
<!-- 循环 -->
{% for post in posts %}
{{ forloop.counter }}. {{ post.title }}
{% empty %}
暂无文章
{% endfor %}
<!-- URL -->
{% url 'blog:post_detail' pk=post.pk %}
<!-- 静态文件 -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<!-- 模板继承 -->
{% extends 'base.html' %}
{% block title %}页面标题{% endblock %}
{% block content %}页面内容{% endblock %}
<!-- 包含 -->
{% include 'sidebar.html' %}
<!-- CSRF -->
{% csrf_token %}
表单
# 表单定义
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'content', 'status']
widgets = {
'title': forms.TextInput(attrs={'class': 'form-control'}),
}
# 视图中使用
def create_post(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('post_detail', pk=post.pk)
else:
form = PostForm()
return render(request, 'post_form.html', {'form': form})
用户认证
# 登录验证装饰器
from django.contrib.auth.decorators import login_required
@login_required
def profile(request):
pass
# 权限装饰器
from django.contrib.auth.decorators import permission_required
@permission_required('blog.add_post')
def create_post(request):
pass
# 类视图 Mixin
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
class CreatePostView(LoginRequiredMixin, CreateView):
pass
# 认证操作
from django.contrib.auth import authenticate, login, logout
user = authenticate(username=username, password=password)
login(request, user)
logout(request)
Admin 配置
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'author', 'status', 'publish']
list_filter = ['status', 'category']
search_fields = ['title', 'content']
date_hierarchy = 'publish'
ordering = ['-publish']
prepopulated_fields = {'slug': ('title',)}
raw_id_fields = ['author']
filter_horizontal = ['tags']
fieldsets = (
('基本信息', {'fields': ('title', 'content')}),
('发布设置', {'fields': ('status', 'category')}),
)
中间件
# 自定义中间件
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# 请求处理前
response = self.get_response(request)
# 响应处理后
return response
# 注册中间件
MIDDLEWARE = [
# ...
'myapp.middleware.MyMiddleware',
]
设置配置
# 基本设置
DEBUG = True
SECRET_KEY = 'your-secret-key'
ALLOWED_HOSTS = ['example.com']
# 数据库
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydb',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
# 静态文件
STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
STATICFILES_DIRS = [BASE_DIR / 'static']
# 媒体文件
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
# 国际化
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = True
常用导入
# 模型
from django.db import models
# 视图
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse, JsonResponse, Http404
# URL
from django.urls import path, include, reverse, reverse_lazy
# 表单
from django import forms
# 用户认证
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
# 通用视图
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
# 分页
from django.core.paginator import Paginator
# 消息
from django.contrib import messages
# 序列化
from django.core.serializers import serialize