Django框架基本语法(二)

Django 框架(二)

六、 请求与响应

官方文档地址:https://docs.djangoproject.com/en/4.0/ref/request-response/

1、 HttpRequest

1.1 介绍

页面被请求,Django创建一个HttpRequest对象,该对象里有请求的源数据。django会加载适当的视图,将HttpRequest作为第一个参数传递给视图函数,每个视图负责返回一个HttpResponse对象。

服务器接收到http协议的请求后,会根据报文创建HttpRequest对象视图函数的第一个参数是HttpRequest对象在django.http模块中定义了HttpRequest对象的API

1.2 接口

1.3 表单

这里默认会将文件写入相应路径,同时提交表单,推荐使用post方式提交,更加安全

index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form表单</title>
</head>
<body>
<form action="{% url 'student:index' %}" method="post"> {% csrf_token %} <!--如果action为空,则将数据提交给当前页面,使用csrf_token离开解决跨域问题-->
<label for="username">用户名</label>
<input type="text" name="username" id="username" placeholder="please input your name"/>
<label for="pwd">密码</label>
<input type="password" name="pwd" id="pwd" placeholder="please input your password">
<input type="submit" value="提交">
</form>
</body>
</html>

csrf跨域问题:

  • django的配置中设置了跨站请求的限制,默认禁止的状态
  • form表单发送post请求时,服务端要求客户端加上csrfmiddlewatetoken字段,该字段的值为当前会话ID加上一个密钥的散列值。
  • 防止跨域请求

解决方法:

  1. form表单后边加上{% csrf_token %},推荐使用这种方式

  2. 修改配置文件

    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware', # 把这一行注释掉,不进行视图的csrf验证,防止其他网站伪造请求进行访问
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

views.py

from django.shortcuts import render
from django.http import HttpResponse
import json
# Create your views here.
# path("index/", views.index, name="index") 路由地址
def index(request):
"""这里的操作只是测试,在实际中会对提交的密码和账户进行校验,成功返回首页面,失败返回登录页面"""
if request.method == "POST":
# 返回数据
username = request.POST.getlist('username') # 返回列表
pwd = request.POST.getlist('pwd') # 也可以通过get方法来获取,推荐使用getlist()
resp = {'code': 200, 'username': username[0], "pwd": pwd[0]}
return HttpResponse(json.dumps(resp), content_type="application/json")
return render(request, "student/index.html")

总结:

  1. GET:如其名,是从服务器获取数据,不会更改服务器的状态和数据,在URL中可携带参数
  2. POST:将一定数据发送给服务器,一般都会更改服务器的数据
  3. 相对来说,POST提交数据的方式比GET安全一点

1.4 文件上传

index.html修改成

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form表单</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data"> {% csrf_token %}
<input type="file" name="file" multiple="multiple"> <!--可以进行多文件上传-->
<input type="submit" value="提交">
</form>
</body>
</html>

views.py修改成

from django.shortcuts import render
from django.http import JsonResponse
from CRM.settings import MEDIA_ROOT # 导入配置文件,在配置文件中设置了文件存储路径
# MEDIA_ROOT = os.path.join(BASE_DIR, 'static/media')
from datetime import datetime
import os
# Create your views here.
# path("index/", views.index, name="index") 路由地址
def index(request):
if request.method == "POST":
file = request.FILES.getlist("file") # 建议使用getlist,当然,也可以使用get方法
day_dir_name = datetime.now().strftime("%Y%m%d") # 定义目录名
day_dir = os.path.join(MEDIA_ROOT, day_dir_name) # 设置路径
# 创建路径,存在则不创建
if not os.path.exists(day_dir):
os.mkdir(day_dir)
for file in files:
with open(f"{day_dir}/{file.name}", "wb") as f:
for line in file:
f.write(line) # 防止文件过大,进行逐行逐行写入
return JsonResponse({"code": 200}, content_type="application/json")
return render(request, "student/index.html")

2、 HttpResponse

2.1 常用方法

当进行前后端分离的时候,可以需要将我们的响应数据传递给前端页面,然后由前端页面进行渲染,可以使用类视图,我们暂时学的是前后端不分离,使用context参数进行上下文管理

同时,响应的更多方法,请到官网进行查看!

2.2 类视图

from django.views import View
from django.http import JsonResponse
# path("test/", views.ViewTest.as_view(), name="test"), # 注册类视图的方法,这个主要用于前后端分离开发,作为后端的响应
class ViewTest(View):
def get(self, request):
return JsonResponse({"code": 200, "data": {"page": "1", "title": "test文档"}}) # 将我们后端的数据进行封装成JSON数据后,传递给前端进行渲染
def post(self, request):
return JsonResponse({"code": 200, "data": {"name": "lihua", "age": 1}})

2.3 Cookies

HTTP(超文本传输协议)是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。HTTP是一个无状态的协议。

服务器无法区分请求是哪个客户端发送过来的,故这时候就可以使用Cookies来区分了。客户端向服务器发送请求,服务器在http协议加上请求头,通过响应,传送并保存在客户端,客户端再次访问时,就会自动带上这个cookie。

from django.http import JsonResponse, HttpResponse
# 这里我们使用类视图来演示
class ViewTest(View):
def get(self, request):
if not request.COOKIES.get("name"): # 如果没有cookies,设置cookies,
resp = HttpResponse() # 创建一个请求
resp.set_cookie("name", "lihua") # 设置cookies,可以通过 max_age 设置cookies的有效时间,单位是秒
resp["headers"] = "xxxxx" # 设置 Response Headers
resp.content = json.dumps({"code": 200, "msg": "登录成功"}) # 设置返回的内容
resp.content_type="application/json" # 设置返回数据的类型
return resp # 返回响应
return JsonResponse({"code": 200})

但是这个cookies没有进行加密,容易篡改,如何解决呢?我们使用session来进行会话的加密。

3、 Session

浏览器存储cookie的方式不太安全,那有没有更好些的来存储登入状态的方式呢?

使用sesison方式,所有数据存储在服务器端,在客户端cookie中存储session_id

session基于cookierequest.session.get()

注意:

  • 使用前记得查看是否注册sessionsapp

    INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions', # session的app
    'django.contrib.messages',
    'django.contrib.staticfiles',
    ]

    . 一般来说,sessionapp的注册好的

  • 使用前也需要查看是否添加session的中间件

    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware', # session的中间件
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
  • 同时,也需要对session进行数据库的迁移

    python manage.py makemigrations sessions # 对sessions数据库进行迁移
    python manage.py migrate sessions # 使得迁移生效

    数据库中主要存储session_key,用来设置cookies

比如,登录状态的保持

def login(request):
if request.method == "POST":
data = request.POST
user = data.get("username")
pwd = data.get("password")
if user == "kun" and pwd == "1":
# 把用户名设置到session中去
request.session.update({
"user": user, # 这个为敏感信息,故需要保存到session中
})
return redirect("student:index")
return render(request, "student/login.html")

删除当前的状态:request.session.flush()

设置会话过期时间:

request.session.set_expiry(1) # 设置过期时间为1秒

通过配置文件来配置会话过期时间:

SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得session过期,默认是False
SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存
SESSION_COOKIE_AGE = 12.96000 # Session的cookie失效日期,默认是2周

4、 分页器

Django中内置了分页的对象

分页功能位于django.core.paginator模块。

Paginator提供包含一些对象的列表,以及你想每一页显示几条,比如每页5条、10条、20条、100条等等,它就会为你提供访问的一系列API方法,示例如下:

>>> from django.core.paginator import Paginator
>>> objects = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(objects, 2) # 对objects进行分页,虽然objects只是个字符串列表,但没关系,一样用。每页显示2条。
>>> p.count # 对象个数
4
>>> p.num_pages # 总共几页
2
>>> type(p.page_range) # `<type 'rangeiterator'>` in Python 2.
<class 'range_iterator'>
>>> p.page_range # 分页范围
range(1, 3)
>>> page1 = p.page(1) # 获取第一页
>>> page1
<Page 1 of 2>
>>> page1.object_list # 获取第一页的对象
['john', 'paul']
>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']
>>> page2.has_next() # 判断是否有下一页
False
>>> page2.has_previous()# 判断是否有上一页
True
>>> page2.has_other_pages() # 判断是否有其它页
True
>>> page2.next_page_number() # 获取下一页的页码
Traceback (most recent call last):
...
EmptyPage: That page contains no results
>>> page2.previous_page_number() # 获取上一页的页码
1
>>> page2.start_index() # 从1开始计数的当前页的第一个对象
3
>>> page2.end_index() # 从1开始计数的当前页最后1个对象
4
>>> p.page(0) # 访问不存在的页面
Traceback (most recent call last):
...
EmptyPage: That page number is less than 1
>>> p.page(3) # 访问不存在的页面
Traceback (most recent call last):
...
EmptyPage: That page contains no results

简单地说,使用Paginator分四步走:

  • 使用任何方法,获取要展示的对象列表QuerySet
  • 将对象列表和每页展示数量传递给Paginator,返回一个分页对象
  • 调用该对象的各种方法,获取各种分页信息
  • 在HTML模板中,使用上面的分页信息构建分页栏

七、 表单类

1、 普通表单

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "form.py"
__time__ = "2022/8/29 18:44"
from django.shortcuts import render
from django import forms
class RegisterForm(forms.Form):
"""创建一个普通表单"""
username = forms.CharField(label="用户名", max_length=20)
pwd = forms.CharField(
label="密码",
max_length=8,
min_length=6,
widget=forms.PasswordInput(attrs={
"placeholder": "请输入6~8位的密码" # 设置表单的一些属性,可以设置类名等
}), # 设置输入框类型,默认为文本输入框
error_messages={
"min_length": "密码长度小于六位",
"max_length": "密码长度大于八位"
}, # 设置报错信息
)
pwd_repeat = forms.CharField(
label="密码",
widget=forms.PasswordInput(attrs={
"placeholder": "请再次输入密码",
}),
error_messages={
"min_length": "密码长度小于六位",
"max_length": "密码长度大于八位"
} # 设置报错信息
)
email = forms.EmailField(required=False) # 邮箱字段
def clean(self):
""""扩展校验功能,使得多个字段可以相互检验"""
cleaned_data = super(RegisterForm, self).clean() # 继承父类的clean方法
# 扩展校验功能
pwd = cleaned_data.get("pwd")
pwd_ = cleaned_data.get("pwd_repeat")
if pwd_ != pwd:
msg = "两次密码不一致"
self.add_error("pwd_repeat", msg)
# path("", form.register, name="register") # 注册路由
def register(request):
if request.method == "GET":
form = RegisterForm()
if request.method == "POST":
data = request.POST
form = RegisterForm(data) # 构建一个填充好数据的对象
if form.is_valid():
# 判断校验是否成功,成功返回True
username = form.cleaned_data.get("username", None) # 从校验后的数据中,获取用户名
print("用户名为", username)
return render(request, "student/register.html", {
"form": form,
})

创建表单的参数:

  • max_length:最大长度
  • min_length:最小长度
  • widget:负责渲染网页上HTML表单的输入元素和提取提交的原始数据
  • attrs:包含渲染后的Widget将要设置的HTML属性
  • error_messages:报错信息
  • validators:验证器

可以参考我以前的博客中flask的表单验证,原理大概相同

2、 模型表单

官方文档地址:https://docs.djangoproject.com/zh-hans/4.0/topics/forms/modelforms/

使用示例:

from django.shortcuts import render
from django import forms
from django.db import models
class Student(models.Model):
"""我们创建的模型类"""
name = models.CharField("姓名", max_length=20, ) # verbose_name 用来设置字段前边的标签文字
age = models.SmallIntegerField()
SEX_CHOICE = (
[0, "女"],
[1, "男"]
)
sex = models.SmallIntegerField(choices=SEX_CHOICE, default=1) # 其生成字段后,是一个下拉框
qq = models.CharField(max_length=20, unique=True, error_messages={
"unique": "qq号码重复" # 设置报错信息
})
phone = models.CharField(max_length=20, unique=True)
c_time = models.DateTimeField("创建时间", auto_now_add=True)
e_time = models.DateTimeField("修改时间", auto_now=True)
is_delete = models.BooleanField(default=False) # 逻辑删除,False代表没删除
grade = models.ForeignKey("Grade", on_delete=models.SET_NULL, null=True)
def __str__(self):
return f"{self.name}-{self.age}"
class StudentForm(forms.ModelForm):
class Meta:
"""在这里指定要映射的模型类"""
model = Student # 指定我们创建的学生模型
# fields = "__all__" # 所有字段都进行展示
exclude = ["is_delete"] # 指定不需要展示的字段
widgets = {
"sex": forms.RadioSelect(attrs={}) # 设置字段类型
}
def clean_qq(self):
"""对单个字段进行校验"""
data = self.cleaned_data # 校验后的数据,再对该字段进行校验
if not data.isdigit():
self.add_error("qq", "你输入的qq号码有问题")
return data # 要记得将数据返回
def register(request):
if request.method == "GET":
form = StudentForm()
if request.method == "POST":
data = request.POST
student = None # 获取到学生对象
form = StudentForm(data, instance=student) # 构建一个填充好数据的对象,instance参数,覆盖原来的数据
if form.is_valid():
# 判断校验是否成功,成功返回True
username = form.cleaned_data.get("username", None) # 从校验后的数据中,获取用户名
print("用户名为", username)
return render(request, "student/register.html", {
"form": form,
})

表单属性:

from student.form import *
forms = StudentForm()
for form in forms:
print(form.label) # 获取字段对应的标签
print(form.id_for_lable) # 获取标签对应的id
form.as_widget(attrs={
"class": "class_str"
}) # 使用这个方法,给该字段增加样式、属性
print(form.errors) # 获取报错信息
print(form.value) # 获取该字段的值
# 这些属性可以用来自定义我我们的表单,使其个性化

八、 中间件

django中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量其中每一个元素就是一个中间件

官方网站地址:https://docs.djangoproject.com/zh-hans/4.1/topics/http/middleware/

1、 创建中间件

顾名思义:请求送入之前和响应送出之前对请求和响应进行处理的组件

中间件的命名和存储是可以任意的,只要是可以导入就行

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "middleware.py"
__time__ = "2022/8/30 19:24"
"""使用装饰器作为中间件"""
# 函数中间件
def simple_middleware(get_response):
"""get_response参数名不可以修改"""
print("初始化")
def middleware(request):
print("视图函数调用之前,进行检验")
response = get_response(request) # 视图函数执行
print("视图函数调用之后,进行检验")
return response
return middleware
# 类中间件
class SimpleMiddleware:
"""也可以使用类来作为装饰器"""
print("初始化")
def __init__(self, get_response):
self.get_response = get_response
print("初始化")
def __call__(self, request):
print("请求前")
if "chrome" not in request.META.get("HTTP_USER_AGENT").lower():
"如果不是使用Chrome浏览器,则拒绝访问"
return HttpResponseForbidden()
response = self.get_response(request)
print(response)
return response # 将响应返回

2、 注册中间件

我们需要在配置文件中,注册我们自定义的中间件

MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'student.middleware.SimpleMiddleware', # 注册类中间件
'student.middleware.simple_middleware' # 注册函数中间件
]

九、 上下文处理器

1、 创建

#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "customer_context.py"
__time__ = "2022/8/30 20:08"
def my_name(request):
return {
"name": "fei" # 将name对应的值添加到全局变量中,这个变量可以通过request中的数据进行获取
}

2、 注册

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.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'student.customer_context.my_name', # 注册创建的上下文处理器
],
},
},
]

所有页面共用的变量,如果同时存在,优先使用context中的变量

十、 管理系统

1、 配置

要求

  1. app注册
  2. 中间件注册
  3. 路径配置

根据路径访问管理员站点:http://127.0.0.1:1236/admin/

创建管理员账号:在项目根目录下运行shell

python manage.py createsuperuser

根据要求来创建超级用户

2、 管理模型

studentapp中,来注册我们的模型,使得我们可以通过管理员用户来修改:

Django提供了admin.ModelAdmin

通过定义ModelAdmin的子类,来定义模型在Admin界面的显示方式

  • 列表页属性

    list_display:显示字段,可以点击列头进行排序

    list_filter:过滤字段,过滤框会出现在右侧

    search_fields:搜索字段,搜索框会出现在上侧

    list_per_page:分页,分页框会出现在下侧

  • 添加、修改页属性

    fields:属性的先后顺序

    fieldsets:属性分组

注意:上面两个属性,二者选一

from django.contrib import admin
from .models import Student, StudentDetail
# Register your models here.
# 自定义
class StudentAdmin(admin.ModelAdmin):
list_display = ['id', 'name', 'sex', 'age', 'qq', 'phone'] # 指定显示字段
list_display_links = ['name', 'sex'] # 指定跳转详情字段
search_fields = ['name', 'qq', 'phone'] # 自定义搜索字段
list_filter = ['sex'] # 过滤
list_per_page = 5 # 每页显示数量
# fields = ['age'] # 只允许修改的字段,和字段分组设置二选一
# exclude = [] # 排除字段
# 分组设置
fieldsets = [
(None, {'fields': ['name', 'sex']}),
('详细信息', {'fields': ['age', 'qq', 'phone']}),
('设置', {'fields': ['is_delete']}),
]
admin.site.register(Student, StudentAdmin) # 注册自定义模型
admin.site.register(StudentDetail) # 注册模型

3、 auth

3.1 数据表

auth系统中的数据表

UserUser是auth模块中维护用户信息的关系模式(继承了models.Model), 数据库中该表被命名为auth_user.

GroupUser对象中有一个名为groups的多对多字段, 多对多关系由auth_user_groups数据表维护。Group对象可以通过user_set反向查询用户组中的用户。

PermissionDjangoauth系统提供了模型级的权限控制, 即可以检查用户是否对某个数据表拥有增(add), 改(change), 删(delete)权限。

3.2 验证系统

配置文件讲解:

INSTALLED_APPS = [
'django.contrib.admin', # 管理系统
'django.contrib.auth', # 权限系统
'django.contrib.contenttypes', # 把权限和模型关联起来
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'student'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', # 会话管理
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware', # 权限管理
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

注意:使用权限管理前,需要对模型进行迁移

用户身份验证系统:

用户身份验证系统:

  1. 身份验证:验证用户是否是用户

  2. 授权:决定用户做什么

当前登录用户,是一个user对象,或者是一个AnonymousUser匿名用户实例,它会被存储在模板变量{{ user }}

登录功能的实现:

from django.contrib.auth import authenticate # 对用户进行校验
from django.contrib.auth import login as login_ # 进行登录,反正重名
# path("", views.login, name="login")
def login(request):
# 判断是否登录
if request.user.is_authenticated: # 匿名用户返回false
return redirect("student:index")
if request.method == "POST":
data = request.POST
user = data.get("username")
pwd = data.get("password")
usr = authenticate(username=user, password=pwd) # 如果验证失败,返回空;验证正确,返回一个用户对象
if usr: # 如果验证正确
# 把用户名设置到session中去
login_(request, usr) # 将请求与用户关联起来
return redirect("student:index")
return render(request, "student/login.html")
# path("/", views.login, name="login")
def login_out(request):
logout(request) # 登出功能

登录验证:

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator # 将函数装饰器,转换为方法装饰器
from django.views import View
# Create your views here.
@method_decorator(login_required) # 进行登录验证
class Register(View):
def get(self, request):
return "正在注册"
@login_required # 对是否登录进行验证,如果没有登录,跳转到登录页面
def index(request):
students = None # 声明学生为空,查看post请求是否得到数据
name = request.session.get("user", "游客")
search = '' # 默认搜索内容为空
if request.method == "POST":
search = request.POST.get("search", "").strip() # 获取到数据
if search: # 如果search有值,则筛选,否则返回全部数据
if search.isdigit():
students = Student.objects.filter(Q(qq=search) | Q(phone=search), is_delete=False)
else:
students = Student.objects.filter(name=search, is_delete=False)
if not students:
students = Student.objects.filter(is_delete=False)
section = "学生列表"
return render(request, "student/index.html", context={
"section": section,
"students": students,
"search_val": search,
"name": name,
})

登录页面的路径在配置文件中配置:

from django.urls import reverse_lazy
LOGIN_URL = reverse_lazy("student:login") # 懒加载

登录常用接口

create_user 创建用户
authenticate 验证登录
login 记住用户的登录状态
logout 退出登录
is_authenticated 判断用户是否登录
login_required 判断用户是否登录的装饰器
permission_required 权限验证装饰器

3.3 User模型

User模型常用属性和方法:

User对象有两个多对多字段:groupsuser_permissionsUser对象可以通过他们访问管理对象

3.4 Group模型

# user 为登录用户
# 组操作
user.groups.add(g2) # 将用户添加到g2组
user.groups.clear() # 清空用户添加的组
user.groups.set([g1, g2]) # 将用户添加到g1, g2组
user.groups.remove(g1, g2) # 将用户从g1, g2组中移除
g1.user_set.add() # 通过反向代理来把用户添加到组中

3.5 Permission模型

# user 为登录用户
# 权限操作
user.user_permissions.set([25,26,27,28]) # 设置
user.user_permissions.remove(25,28) # 移除
user.user_permissions.add(25,28) # 添加
user.user_permissions.clear() # 清空,对应功能的id
# 对组进行权限操作
gl.permissions.add(permission) # 添加某个权限
# 查看用户是否有某个app下某个模型的某个操作功能(增add删delete改change查view)
user.has_perm('student.view_student') # app.add_模型

权限会被存储在模板变量{{ perms }}

posted @   Kenny_LZK  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示