登录后进入欢迎页
from django.contrib.auth.decorators import login_required, permission_required
@login_required(login_url="/myauth/login/") #在使用welcome 处理前,先查看用户是否登录,if not,跳转到login_url处理,登录成功后,继续跳转到welcome页面
def welcome(request):
return render(request,'welcome.html')
更新数据
@permission_required(perm="myapp.change_student",login_url="/myauth/login/")
def update_student(request):
return render(request,'student_permission.html')
登录
def login_view(request):
# request.session #一个既可读又可写的类似于字典的对象,表示当前的会话
# login()是向django_session 表中添加记录,代表当前用户的会话
if request.method == "GET":
return render(request,'userlogin.html')
else:
logname = request.POST.get("logname")
logpwd = request.POST.get("logpwd")
user = authenticate(username=logname,password=logpwd) # 认证用户,该方法不检查is_active标志位
print("authenticate()的结果:user=",user)
if user is not None:
if user.is_active:
login(request,user) # login向session中添加SESSION_KEY, 便于对用户进行跟踪
request.session["uname"] = logname # 手工向Session中设置登录名
return redirect(reverse("myauth:welcome"))
return redirect(reverse("myauth:login"))
django_session表
中间件
from django.shortcuts import redirect
from django.urls import reverse
from django.utils.deprecation import MiddlewareMixin
REQUIRED_LOGIN = ['/fruit/buy/','/fruit/cart/']
class LoginMiddleware(MiddlewareMixin):
def process_request(self,request):
path = request.path # 获取当前请求路径
print("当前请求路径:",path)
if path in REQUIRED_LOGIN:
if not request.session.get("uname"): #检查session 确定用户在请求当前页面是否有登录
return redirect(reverse("home:login"))
自定义权限
class Meta:
verbose_name = "电影模型"
verbose_name_plural = verbose_name
permissions = ( # 在auth_permission 表中添加以下两个权限,可以通过django 后台管理系统 or 代码修改某个用户的权限
("vip","vip can do"),
("ordinary","ordinary can do")
)
{% if perms.homeworkapp.ordinary %} <!-- 调用方法为perms.projectname.permissionname-->
<ul>
{% for movie in movies %}
<li> {{ movie.name }} </li>
{% endfor %}
</ul>
{% endif %}
自定义表格
<form action="{% url 'formapp:reg' %}" method="post">
{% csrf_token %}
{{ regform.as_p }} <!-- {{ formname.as_p }} 将表单的每个输入框包裹在一个<p>标签内 tags-->
<input type="submit" value="注册"/>
</form>
自定义某模型类的序列化对象
- 在某应用的根目录下创建serializers.py
from rest_framework import serializers
from restapp.models import Student
# 自定义学生序列化类
class StudentSerializers(serializers.ModelSerializer):
class Meta:
model = Student # 关联学生模型
# fields = "__all__" # 序列化学生模型的所有类属性
fields = (
"name",
"age",
"sex",
"score",
)
- 子路由
from django.urls import path
from restapp.views.student_class_view import StudentView
from restapp.views.student_func_view import student_view
urlpatterns = [
path('students/',StudentView.as_view()), # as_view()
path('student/<sid>/',student_view),
]
- 在views文件夹中
student_class_view
from rest_framework import status
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from rest_framework.views import APIView
from restapp.models import Student
from restapp.serializers import StudentSerializers
# 基于类的视图
class StudentView(APIView):
def get(self,request):
students = Student.objects.all()
pg = PageNumberPagination() # 实例化Rest framework中的分页器对象
# 获取分页数据,参数一 分页的数据,QuerySet类型,请求request,分页的视图,self代表自己
# 此处不理解的是 分页的数据是所有学生, view是自己是啥意思???
page = pg.paginate_queryset(queryset=students,request=request,view=self)
# 为了能够序列化一个查询集或者一个对象列表 而不是一个单独的对象,需要在实例化序列化器类的时候传一个many=True参数。这样就能序列化一个查询集或一个对象列表。
sers = StudentSerializers(instance=page,many=True) # 将所有学生对象序列化,对分完页码的数据进行序列化
return Response(sers.data,status=status.HTTP_200_OK)
def post(self,request): # 添加新数据
sers = StudentSerializers(data=request.data) # 将POST请求数据封装到序列化对象中
if sers.is_valid(): # 验证数据是否有效
sers.save() # 保存
return Response(sers.data,status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_400_BAD_REQUEST)
student_func_view
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from restapp.models import Student
from restapp.serializers import StudentSerializers
@api_view(["GET","PUT","DELETE","PATCH"])
def student_view(request,sid):
try:
student = Student.objects.get(pk=sid)
except Student.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
sers = StudentSerializers(instance=student)
return Response(sers.data,status=status.HTTP_200_OK)
elif request.method == "PUT": # 添加新数据
sers = StudentSerializers(instance=student,data=request.data) # 使用提交的新数据覆盖查询的旧数据
if sers.is_valid():
sers.save() # 更新
return Response(sers.data)
return Response(status=status.HTTP_400_BAD_REQUEST)
elif request.method == "PATCH":
# 默认情况下,序列化器必须传递所有必填字段的值,否则就会引发验证错误。但是我们可以将 partial参数指定为True,来允许部分更新,而不至于产生错误
# instance 为从数据库中查询到模型类
# data 为从用户发来的请求数据的字典类
sers = StudentSerializers(instance=student, data=request.data,partial=True) # 使用提交的新数据覆盖查询的旧数据
if sers.is_valid():
sers.save() # 更新
return Response(sers.data)
return Response(status=status.HTTP_400_BAD_REQUEST)
elif request.method == "DELETE":
student.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
URL分发器是如何定位到应该交给那个视图函数处理呢?
不懂为啥,请参考:
python_装饰器入门教程哦
url_view_map = {}
def route(path_url_map):
def inner(func):
def second_dec(*args, **kwargs):
url_view_map[path_url_map['path']] = func
func(*args,**kwargs)
return second_dec
return inner
@route({'path': r'/index'}) # 自定义url,并且将'/index' 和index视图函数关联起来
def index(request):
print(request)
pass
index(123)
url_view_map = {}
def route(path_url_map):
def inner(func, request):
url_view_map[path_url_map['path']] = func
func(request)
return inner
@route({'path': r'/index'}) # 自定义url,并且将'/index' 和index视图函数关联起来
def index(request):
print(request)
pass
# index(index('123'), '123')
# index('123') #此处inner函数还需要func,虽然此处同时传入参数
# 目前不知道为啥 # 猜测是函数及其形式参数无法同屏出现,我明明传入request,到底被谁吞了?
# 程序会不会无法识别一个index 调用和index 函数对象?
# TypeError: inner() missing 1 required positional argument: 'request'
# 测试2
我把index()设置成无参的函数,显示TypeError: 'NoneType' object is not callable