官方文档
View官方快速上手文档:点击查看
rest_framework视图类
自定义过滤器
drf中,过滤、搜索、排序都叫filter
过滤器官方文档:drf官方文档 django-filter文档
2025年11月28日大约 14 分钟
View官方快速上手文档:点击查看
drf中,过滤、搜索、排序都叫filter
过滤器官方文档:drf官方文档 django-filter文档
/users/ /users/<pk>/?search= ?ordering=/users/1.jsonHyperlinkedModelSerializerstatus.HTTP_400_BAD_REQUEST本教程是基于python3.13、django5.2、djangorestframework3.16版本。
由于前后端分离已经是行业默认标准,本教程会结合django-rest-framework的第三方框架进行统一讲解。
本文字教程是不适合完全没有接触django的同学进行学习,可以利用网上其他入门教程搭配学习。
其他文档:
awesome-django
techempower web框架性能排行榜
Benchmarker web框架性能排行榜
uv文档:点击访问
# 安装uv
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
# 配置pypi包的国内源
[System.Environment]::SetEnvironmentVariable('UV_DEFAULT_INDEX', 'https://mirrors.aliyun.com/pypi/simple', 'User')
# 配置python版本包为南京大学源
[System.Environment]::SetEnvironmentVariable('UV_PYTHON_INSTALL_MIRROR', 'https://mirror.nju.edu.cn/github-release/astral-sh/python-build-standalone/', 'User')
docker run -d --name mysql --restart=always -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -v C:/docker-data/mysql:/var/lib/mysql mysql:latest
docker run -d --name postgres --restart=always -e POSTGRES_PASSWORD=123456 -e POSTGRES_USER=postgres -e POSTGRES_DB=testdb -p 5432:5432 -v C:/docker-data/postgres:/var/lib/postgresql postgres:latest
docker run -d --name redis --restart=always -p 6379:6379 -v C:/docker-data/redis:/data redis:latest redis-server --appendonly yes --requirepass "123456"
from django.contrib import admin
from django.contrib.auth.hashers import make_password
from django.contrib import messages
from django.contrib.auth.models import AbstractUser, Group, Permission, User
from django.contrib.auth import get_user_model
UserModel = get_user_model()
# admin.site.unregister(User) # 如果使用原生用户模型,需要先取消注册
@admin.register(UserModel)
class UserAdmin(admin.ModelAdmin):
list_display_links = ('username',)
search_fields = ('username', 'first_name')
def get_list_display(self, request):
"""列表页展示的字段,管理员添加可见字段"""
list_display = ('username', 'first_name', 'area', 'is_staff', 'is_superuser_display', 'date_joined', 'last_login')
return list_display
# 自定义显示字段
@admin.display(description='超级管理员')
def is_superuser_display(self, obj):
return '是' if obj.is_superuser else ''
# 列表过滤器功能的字段
def get_list_filter(self, request):
if request.user.is_superuser:
list_filter = ('area',)
self.list_filter_multiples = ('area',)
return list_filter
else:
return super().get_list_filter(request)
def get_fieldsets(self, request, obj=None):
"""详情页字段"""
self.filter_horizontal = ['user_permissions', 'groups']
fieldsets = [
("账号信息", {"fields": [('username', 'password', 'first_name', 'email')]}),
("登录权限", {"fields": ['area', 'is_staff', 'is_superuser']}),
("使用权限", {"fields": ['user_permissions', 'groups'], "classes": ['collapse']}),
]
return fieldsets
def get_changeform_initial_data(self, request):
"""详情页中初始值的修改"""
initial = super().get_changeform_initial_data(request)
initial['is_staff'] = True
return initial
def save_model(self, request, obj, form, change):
"""创建或修改某条数据的功能"""
if obj.is_superuser: # 如果是超管,无需配置区域
obj.area = None
if change:
# 修改密码
if obj.password != User.objects.get(pk=obj.pk).password: # 如果有修改密码行为
if obj.pk != request.user.pk and request.user.is_superuser is False: # 如果不是超管,不可以修改其他人密码
messages.error(request, '您不是超管,不能修改其他人密码。')
return
obj.password = make_password(obj.password)
else: # 如果是创建用户
obj.password = make_password(obj.password)
super().save_model(request, obj, form, change)
def delete_model(self, request, obj):
"""删除时做一些处理"""
obj.delete()
def save_related(self, request, form, formsets, change):
"""保存外键和多对多关系数据"""
super().save_related(request, form, formsets, change)
obj = form.instance
# 默认权限(必须先添加数据才能修改权限)
if not change: # 如果是新建用户
if not obj.user_permissions.exists() and not obj.groups.exists(): # 如果没有手动添加权限
permissions = Permission.objects.filter(content_type__app_label__in=['children', 'women', 'users'])
obj.user_permissions.add(*permissions)
user_permissions = Permission.objects.filter(content_type__app_label='auth', content_type__model='user') # 用户表权限
obj.user_permissions.add(*user_permissions)
def get_queryset(self, request):
"""列表页的查询集"""
qs = super().get_queryset(request)
if not request.user.is_superuser:
qs = qs.filter(area=request.user.area, is_superuser=False)
return qs
用户模型必须在第一次迁移前就确定下来,后期如果修改则需要重新构建数据库。因为一旦迁移应用到数据库,内置应用(比如 admin)的迁移就会依赖于原有的用户模型(默认是 auth.User),而修改后会导致迁移依赖关系不一致,从而产生错误。
扩展完用户表,必须要在settings.py文件内设置:
AUTH_USER_MODEL = 'users.UserModel'