Django项目基础

0.安装环境

pip install django
pip install pymysql
#-i https://pypi.tuna.tsinghua.edu.cn/simple 国内镜像


#保存本地python库
pip freeze > requirements.txt
#下载
pip install -r requirements.txt

#pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
#pip install  -i https://pypi.tuna.tsinghua.edu.cn/simple django


#打包   pyinstaller -F 文件路径(要先下载pyinstaller)
#pyinstaller -F 文件地址 -p D:\pyCharm\PQ
#pyinstaller --paths=文件路径    多个文件打包


#设置虚拟环境

pip install virtualenv #安装

python -m venv .venv (.venv是目录路劲及名称)

# 进入Scripts文件夹后,启动
#./.venv/Scripts/activate
# linux中  source .venv/bin/activate

activate 
#关闭
deactivate





# git指令
# 先下载对应的仓库到文件夹 然后进入到项目文件夹内

git init # 初始化仓库
git add . # 添加需要更改的文件 .为所有文件
git commit -m "Initial commit"  # 上传的说明
git push origin master # 直接上传到master分支


1.如何创建Django项目

1.1用指令生成项目

启动终端:按住win+r,输入cmd打开终端;进入使用cd指令进入自己准备好的项目文件夹

#1.创建项目   ***为名字,自己定
django-admin startproject *** #项目名
#2.进入到项目中创建一个app应用(一个Django项目有多个应用)
python manage.py startapp *** #app应用名

1.2配置文件 settings.py

1.2.1项目结构

  • 项目文件夹
    • 项目同名文件夹
      • __init__.py
      • asgi.py
      • settings.py
      • urls.py
      • wsgi.py
    • app应用文件夹
      • __init__.py
      • admin.py
      • apps.py
      • models.py
      • tests.py
      • views.py
    • manage.py

1.2.2.注册应用,解决跨域

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "应用名"
]
#解决frame跨域问题
X_FRAME_OPTIONS = 'ALLOWALL url'

#把英文改为中文
LANGUAGE_CODE = 'zh-hans'
 
#把国际时区改为中国时区
TIME_ZONE = 'Asia/Shanghai'
USE_TZ = False

1.2.3.配置视图文件,静态文件

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',
            ],
            'builtins': ['django.templatetags.static'],
        },
    },
]

STATIC_URL = '/static/'

STATICFILES_DIRS=[ 
    os.path.join(BASE_DIR,'static'),
] 


MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

配置完成后,在项目中分别创建templates、static、media三个文件夹

1.2.4.数据库连接

在项目同名文件夹下的 settings.py文件中

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME': '库名',
    'USER':'数据库用户名',
    'PASSWORD':'密码',
    'HOST':'IP地址',
    'PORT':端口
    }
}

在项目同名文件夹下的 __init__.py文件中

import pymysql
pymysql.version_info=(1,4,13,"final",0)
pymysql.install_as_MySQLdb()

2.运行Django项目

2.1.首先要进行数据迁移

首次启动过后,下次启动如果没有修改模型文件也就是models.py,则可以省略此步骤

在终端中依次运行

1.生成数据迁移文件
python manage.py makemigrations
2.数据迁移至数据库
python manage.py migrate

#python manage.py  migrate --database=chen

2.2.然后终端输入指令启动项目

在终端中按ctrl+c可项目终止运行

python manage.py runserver 0.0.0.0:8000
#省略ip
python manage.py runserver 8000
#ip和端口可自定也可不写,默认是8000端口

2.3.访问网站

打开任意浏览器,最好不是IE;输入网址 127.0.0.1:8000(需要注意端口要和你启动的端口一致)

确认项目跑起来了可以直接点击这里127.0.0.1:8000

如果设置了路由直接在后面加自己设置的路劲,例如:127.0.0.1:8000/index/


3.建立模型

3.1.模型代码

在应用文件夹下找到 models.py文件

填写如下代码

from django.db import models

class departInfo(models.Model):
    class Meta:
        app_label = 'app'
        db_table = 'depart'# 指定表名
        # verbose_name = "部门"  #后台名称 复数
        verbose_name_plural = "部门"  #后台名称 单数
  
    dname = models.CharField(verbose_name="部门名称", null=True, blank=True, max_length=200)
    gnum = models.IntegerField(verbose_name="人数", null=True, blank=True)

class userInfo(models.Model):
    class Meta:
        db_table = 'user'  # 指定表名
    img = models.TextField(verbose_name="头像", blank=True, null=True)#长文本类型
    name = models.CharField(verbose_name="姓名", max_length=200)#字符类型
    y = ((0, "女"), (1, "男"))
    sex = models.SmallIntegerField(verbose_name="性别", choices=y, default=1)
    startdate = models.DateTimeField(verbose_name="时间", null=True, blank=True)#时间类型
  
    #外键
    departname = models.ForeignKey(verbose_name="所在部门", to="departInfo", to_field="id", on_delete=models.SET_DEFAULT, default=-1)
    # null=True,blank=True,on_delete=models.SET_NULL 是设置为空
    # on_delete=models.SET_DEFAULT,default=Category.objects.get(pk=2)||default=4  是设置为默认值
    #  on_delete=models.CASCADE 全删!!
  
  
  
  
  
  
from django.core.files.storage import FileSystemStorage



class ImageStorage(FileSystemStorage):
    from django.conf import settings
 
    def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
        # 初始化
        super(ImageStorage, self).__init__(location, base_url)
 
    # 重写 _save方法
    def _save(self, name, content):
        # name为上传文件名称
        import os, time, random
        # 文件扩展名
        ext = os.path.splitext(name)[1]
        # 文件目录
        d = os.path.dirname(name)
        # 定义文件名,年月日时分秒随机数
        fn = time.strftime('%Y%m%d%H%M%S')
        fn = fn + '_%d' % random.randint(0, 100)
        # 重写合成文件名
        name = os.path.join(d, fn + ext)
        # 调用父类方法
        return super(ImageStorage, self)._save(name, content)
  
    class AboutInfo(models.Model):
    class Meta:
        app_label = 'app'
        db_table = 'about'
        verbose_name_plural = "关于页" 
    photo = models.ImageField(verbose_name="图片", default=None, max_length=1024, upload_to="rotation/%Y%m",storage=ImageStorage())

3.2.模型基础操作

userInfo.objects.create(字段名=添加字段)

userInfo.objects.filter(字段=查找字段).delete()

userInfo.objects.filter(字段=查找字段).update(字段=修改字段)

userInfo.objects.all()#查询所有
userInfo.objects.filter(字段=查找字段)#没有查询对象不会报错,查找的是集合
userInfo.objects.get(字段=查找字段)#没有查询对象会报错,查找后返回model对象

orm操作详情


4.建立网站

当前目录结构

  • 项目文件夹
    • media
    • static
    • templates
    • 项目同名文件夹
      • __init__.py
      • asgi.py
      • settings.py
      • urls.py
      • wsgi.py
    • app应用文件夹
      • __init__.py
      • admin.py
      • apps.py
      • models.py
      • tests.py
      • views.py
    • manage.py

4.1.视图函数

在应用文件夹下找到 views.py文件

填写如下代码

from django.shortcuts import render, redirect
from django.http import HttpRequest, HttpResponse, JsonResponse
from django.db.models import Q,Avg, Max, Min, Count, Sum

from app.models import *
def index(request):
    x=userInfo.objects.all()#查询所有
    return render(request, "index.html", {"x": x})#locals() 是返回全部局部变量

4.2.配置路由

以下方法二选一即可

在项目同名文件夹下找到 urls.py

填写如下代码

from django.contrib import admin
from django.urls import path,re_path

from django.conf import settings
from django.views.static import serve

from app import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
    #配置静态资源路由(可选)
   #re_path(r'media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]

因为在Django项目中可以有多个app,所以更加推荐用自创app的 urls.py

在项目同名文件夹下的 urls.py中填写如下代码

from django.contrib import admin
from django.urls import path,include,re_path

from django.conf import settings
from django.views.static import serve

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('app.urls')),
    #配置静态资源路由(可选)
   #re_path(r'media/(?P<path>.*)$', serve, {'document_root': settings.MEDIA_ROOT}),
]

在app文件夹下创建 urls.py并填写如下代码

from django.urls import path, include
from app import views
urlpatterns = [
    path('index/', views.index),
]

4.3.创建模板文件

在templates文件夹下创建 index.html文件

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>展示数据</h1>
        <table border="1">
            <tr>
                <th>id</th>
                <th>姓名</th>
                <th>性别</th>
                <th>加入时间</th>
                <th>部门</th>
            </tr>
            {%for i in x%}
            <tr>
                 <td>
                    {{i.id}}
                     {#也可以用在选择 {{forloop.counter}}  不暴露ID#}
                </td>
                <td>
                    {{i.name}}
                </td>
                <td>
                    {{i.get_sex_display}}
                    {#因为sex是可选字段,值是0或1,用get_sex_display可以直接获取字段名#}
                    {#也可以用if判断的写法,如下
                        {%if i.sex == 1%}
                        男
                        {%else%}
                        女
                        {%endif%}
                    #}
                </td>
                <td>
                    {{i.startdate|date:"Y-m-d D H:i"}}
                    {#可视化时间类型的变量#}
                </td>
                 <td>
                    {{i.departname.dname}}
                </td>
            </tr>
            {%endfor%}
        </table>
    </body>
</html>

重新启动项目,参考运行Django项目


5.静态资源引入

5.1.创建静态文件

在static文件夹下依次创建css、js、img等文件夹

  • static
    • css
    • js
    • img

在css文件夹下创建 index.css文件,填写代码如下

body{
    background-color: red;
}

5.2.静态文件引入

在模板文件夹templates中的 index.html

有三种引入方法

5.2.1.相对路径引用

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {#引入静态文件#}
        <link rel="stylesheet" href="../../static/css/index.css">
        <title>Document</title>
    </head>
... ...

5.2.2.直接用/static/引用

个人最推荐的使用方法,因为这种方法在套用前端模板时最好修改

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {#引入静态文件#}
        <link rel="stylesheet" href="/static/css/index.css">
        <title>Document</title>
    </head>
... ...

5.2.3.使用引用

...很麻烦,自己写的时候可以用着玩玩;js和图片、链接等都可以用此写法

{% load static%}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        {#引入静态文件#}
        <link rel="stylesheet" href="{% static 'css/index.css'%}">
        <title>Document</title>
    </head>
... ...

其他静态文件引用都是类似,不一一举例了,重启项目参考运行Django项目

6.发送请求和传参

当前目录结构

  • 项目文件夹
    • media
    • static
      • css
        • index.css
      • js
      • img
    • templates
      • index.html
    • 项目同名文件夹
      • __init__.py
      • asgi.py
      • settings.py
      • urls.py
      • wsgi.py
    • app应用文件夹
      • __init__.py
      • admin.py
      • apps.py
      • models.py
      • tests.py
      • urls.py(可选)
      • views.py
    • manage.py

6.0通用操作

重点注意

setting.py文件中

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',这个是Django自带的保护机制,开发时候可以注释掉,但是为了安全最好不要注释
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

先进行通用操作,在模板文件夹templates下创建 dome.html,代码如下

<!DOCTYPE html>
  <html lang="en">
   <head>
         <meta charset="UTF-8">
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1.0">
         <title>Document</title>
     </head>
     <body>
         <a href="/get/?name='cwm'">发送get请求</a>
         <form action="/post/" method="post">
              {# 如果在setting.py文件中注释了安全协议,可以不加 {% csrf_token %} #}
             {# 否则所有的post请求中都必须加上{% csrf_token %} #}
             {% csrf_token %}
  
             <input type="text" name="name" value="cwm">
             <button type="submit">发送post请求</button>
         </form>
     </body>
 </html>

然后配置路由在app文件夹下的 urls.py;代码如下

urlpatterns = [
     path('index/', views.index),
     path('dome/', views.dome),
     path('get/', views.request_get),
     path('post/', views.request_post),
 ]

如果没有选择创建app的urls.py可以用项目同名文件夹下的 urls.py,一样一样的

在视图函数文件中 views.py

def dome(request):
    return render(request, "dome.html")

6.1.GET请求

在视图函数文件中的 views.py

def request_get(request):
    x=request.GET.get('name')
    return HttpResponse(x)

6.2.POS请求

在视图函数文件中的 views.py

def request_post(request):
    x=request.POST.get('name')
    return HttpResponse(x)

在不出意外的情况下,启动项目后运行Django项目,进入网址http://127.0.0.1:8000/dome/

无论点击哪一个请求都会跳转网页显示cwm;当然出bug另外

6.3.路径传参

在模板文件夹templates下的 dome.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <a href="/get/1/?name='cwm'">发送get请求</a>
        <form action="/post/xxx/" method="post">
            {% csrf_token %}
            <input type="text" name="name" value="cwm">
            <button type="submit">发送post请求</button>
        </form>
    </body>
</html>

路由 urls.py

urlpatterns = [
    path('index/', views.index),
    path('dome/', views.dome),
    #int为整数,str为字符,传什么用什么
    path('get/<int:y>/', views.request_get),
    path('post/<str:y>/', views.request_post),
]

在视图函数文件 views.py

#参数名要和路由上的变量名一致,传参的类型也要一致
def request_post(request,y):
    x=request.POST.get('name')
    print(y)
    return HttpResponse(x)
  
def request_get(request,y):
    x=request.GET.get('name')
    print(y)
    return HttpResponse(x)

在不出意外的情况下,启动项目后运行Django项目,进入网址http://127.0.0.1:8000/dome/

无论点击哪一个请求都会跳转网页显示cwm,并且终端会输出y值:get请求为1,post请求为xxx;

当然出bug另外

6.4.整合写法

其实不用分两个视图函数来写,可以整合成一个视图函数

dome.html文件用通用时的模板,即不用路由传参

路由 urls.py

urlpatterns = [
    path('index/', views.index),
    path('dome/', views.dome),
	#两个路由跳一个方法
    path('get/', views.r_get_post),
    path('post/', views.r_get_post),
]

视图函数 views.py

#request.method用来判断请求,request.get_full_path()路由
def r_get_post(request,):
    if request.method == "GET":
    	x=request.GET.get('name')
    	return HttpResponse(x)
    else:
        x=request.POST.get('name')
    	return HttpResponse(x)

#访问时的IP:request.META['HTTP_X_FORWARDED_FOR'],request.META['REMOTE_ADDR']
'''
def lg(request):
    if request.META.get('HTTP_X_FORWARDED_FOR'):
        ip =  request.META['HTTP_X_FORWARDED_FOR']
    else:
        ip = request.META['REMOTE_ADDR']
    return ip
'''

在不出意外的情况下,启动项目后运行Django项目,进入网址http://127.0.0.1:8000/dome/

情况和上面一致

Django项目精通

1.页面拼接和继承

在templates文件夹下创建两个视图文件 dome1.htmldome2.html

dome1.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
    以下部分会被拼接
 	{% block a %}
    这里会被拼接
	{% endblock a%}
</body>
</html>

dome2.html

{% extends "dome1.html"%}
{% load static %}
{% block a %}
我是拼接的内容
{% endblock a%}

2.form和modelform组件

3.会话session

4.多应用(app)多数据库连接

5.admin内置后台

python manage.py createsuperuser(创建超级用户)

5.1 设置后台管理的表

from django.contrib import admin
from myApp.models import *
# Register your models here.
class JobManager(admin.ModelAdmin):
    list_display = ["id", "title", "address", "type", "educational", "workExperience", "workTag", "salary", "salaryMonth",
                        "companyTags", "hrWork", "hrName", 'pratice', "companyTitle", "companyAvatar", "companyNature",
                        "companyStatus", "companyPeople", "detailUrl", "companyUrl", "dist"]
    list_display_links = ["title"]
    # list_editable = ["workTag"]
    list_filter = ['type']
    search_fields = ['title']
    readonly_fields = ['id']
    list_per_page = 10
    date_hierarchy = 'createTime'

class UserManager(admin.ModelAdmin):
    list_display = ['id',"username",'password','educational','workExpirence','address','work','avatar','createTime','chromeUrl','tempUrl']
    list_display_links = ["username"]
    readonly_fields = ['id']
    list_filter = ['educational']

    search_fields = ['username']
    list_per_page = 10
    date_hierarchy = 'createTime'

class PetManager(admin.ModelAdmin):
    # 展示
    list_display = [ "id",'pname',"price","address","psex","notes","pnum","ptype"]
    # 点击详情
    list_display_links = ["pname"]
    # 不可更改
    readonly_fields = ['id']
    # 条件查询,下拉菜单
    list_filter = ["ptype"]
    # 搜索
    search_fields = ["pname"]
    # 每页数
    list_per_page = 10
    # 时间检索
    # date_hierarchy = 'add_time'
  
    # 直接修改
    list_editable=["pnum"]

class HistoryManager(admin.ModelAdmin):
    list_display = ['id','job','user']
    list_display_links = ["job"]
    readonly_fields = ['id']
    search_fields = ['job']
    list_per_page = 10
    list_filter = ['user']
  
  

@admin.register(RotationInfo)
class RotationInfoManager(admin.ModelAdmin):
      # 展示
    list_display = [ "id",'pname',"price","address","psex","notes","pnum","ptype"]
    # 点击详情
    list_display_links = ["pname"]
    # 不可更改
    readonly_fields = ['id']
    # 条件查询,下拉菜单
    list_filter = ["ptype"]
    # 搜索
    search_fields = ["pname"]
    # 每页数
    list_per_page = 10
    # 时间检索
    # date_hierarchy = 'add_time'
  
    # 直接修改
    list_editable=["pnum"]
    # 排序
    ordering = ['id']

'''
from django.utils.html import format_html

    def view_button(self, obj):
        format_html(f'<a href="">查看说明使用</a>')
    view_button.short_description = "操作"
    view_button.allow_tags = True
  
  
  
    def leave_info(self, obj):
    	return obj.__str__()
    leave_info.short_description = "留言信息"
  
  
  
  
    def get_items(self):
        return len(self.aboutusitemsinfo_set.all())
    get_items.short_description = '条规数'
  
  
  
  
    def xx(self,*arg):
        print(arg[1][0].content)
    xx.short_description="导出Markdown文件"
    actions = [xx]
   '''
admin.site.register(JobInfo,JobManager)
admin.site.register(UserInfo,UserManager)
admin.site.register(HistoryInfo,HistoryManager)

5.2美化后台

#在setting.py文件中
INSTALLED_APPS = [
    'simpleui', # 新增
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]
STATIC_ROOT = os.path.join(BASE_DIR, "/static/")  # 新增

pip install django-simpleui
python manage.py collectstatic  #(打包静态资源)

django3目前可以用的UI:django-simpleuidjango-adminlte-ui

6.DRF序列化

6.1 创建序列化器

在app应用下创建 api_serializers.py 文件

## 基础写法
from rest_framework import serializers

class mkSerializers(serializers.Serializer):
    name =serializers.CharField(max_length=200)
    bir =serializers.DateTimeField(required=False)
    num=serializers.IntegerField(source="price")
    def create(self, validated_data):
        return super().create(validated_data)
    def update(self, instance, validated_data):
        return super().update(instance, validated_data)

## 进阶写法
from rest_framework import serializers
from .models import *

class NoteSerializers(serializers.ModelSerializer):
    class Meta:
        model=NoteInfo
        fields = '__all__'
        # exclude=[""]

6.2 APIView基础视图函数写法

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin
from rest_framework.viewsets import ViewSet,ModelViewSet,GenericViewSet

from rest_framework.response import Response
from .models import *
from .api_serializers import *

class DrfIndexView(APIView):
    def get(self,request):
        #获取路由的值
        y=request.query_params.get("f")
        xx=mkInfo.objects.all()
        print(xx)

        yy=mkSerializers(instance=xx,many=True)  ##多个数据 many=True 单个数据many=False
        c={
            "code":"成功",
            "list":yy.data
        }
        return Response(c)
  

    def post(self,request):
        print("data",request.data)
        yy=mkSerializers(data=request.data)
        if yy.is_valid():
            print(yy)
            x=mkInfo.objects.create(**yy.validated_data)
            return Response(yy.data)
        else:
            return Response(yy.errors)

6.3 GenericAPIView+Minin进阶视图函数写法

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin
from rest_framework.viewsets import ViewSet,ModelViewSet,GenericViewSet

from rest_framework.response import Response
from .models import *
from .api_serializers import *


## 只使用GenericAPIView
class DrfNoteIndexView(GenericAPIView):
    queryset=NoteInfo.objects.all()
    serializer_class=NoteSerializers

    def get(self,request,pk):
        print(pk)
        note_list=self.get_queryset()
        print(note_list)
        # self.get_serializer_class()(instance=self.get_queryset(),many=True)
        self.get_serializer(instance=self.get_object(),many=False)
        c={
            "code":"成功",
            "list":""
        }
        return Response(c)
  

## 使用GenericAPIView+对应的Minin
class DrfNotesView(GenericAPIView,ListModelMixin):
    queryset=NoteInfo.objects.all()
    serializer_class=NoteSerializers
    def get(self,request):
        return self.list(request)
  

## 使用GenericAPIView+对应的Minin结合体
class DrfNotessView(ListCreateAPIView):
    queryset=NoteInfo.objects.all()
    serializer_class=NoteSerializers

6.4 ViewSet终极视图函数写法

from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView
from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,RetrieveModelMixin,DestroyModelMixin
from rest_framework.viewsets import ViewSet,ModelViewSet,GenericViewSet

from rest_framework.response import Response
from .models import *
from .api_serializers import *

class DrfNotessssView(ViewSet):
    pass


class DrfNotesssssView(GenericViewSet,ListModelMixin):
    queryset=NoteInfo.objects.all()
    serializer_class=NoteSerializers



class DrfNotessxxxxsView(ModelViewSet):
    queryset=NoteInfo.objects.all()
    serializer_class=NoteSerializers

7.JWT 双Token及权限认证

7.1 初始配置

下载库

djangorestframework
djangorestframework-simplejwt

注册应用

INSTALLED_APPS = [
    ...
    'rest_framework',#序列化
    'rest_framework_simplejwt',#权限认证
    "rest_framework_simplejwt.token_blacklist",  # 黑名单
    ...
]

7.2 配置文件

SIMPLE_JWT = {
    # 访问令牌的有效期,设置为5分钟。
    'ACCESS_TOKEN_LIFETIME': datetime.timedelta(minutes=5),
  
    # 刷新令牌的有效期,设置为1天。
    'REFRESH_TOKEN_LIFETIME': datetime.timedelta(days=1),

    # 是否在刷新访问令牌时旋转刷新令牌。如果设置为True,则每次刷新访问令牌时都会生成一个新的刷新令牌。
    'ROTATE_REFRESH_TOKENS': False,
  
    # 在刷新令牌旋转后,是否将旧的刷新令牌加入黑名单。如果设置为True,则可以防止旧的刷新令牌再次使用。
    'BLACKLIST_AFTER_ROTATION': True,
  
    # 是否在用户登录时更新他们的最后登录时间。如果设置为True,则会在每次用户使用他们的令牌时更新这个时间。
    'UPDATE_LAST_LOGIN': False,
  
    # 用于签名JWT的算法。HS256表示HMAC-SHA256。
    'ALGORITHM': 'HS256',
  
    # 用于签名JWT的密钥。通常与Django的SECRET_KEY相同。
    'SIGNING_KEY': SECRET_KEY,
  
    # 用于验证JWT的公钥。如果使用私钥/公钥对,则需要设置这个值。
    'VERIFYING_KEY': None,
  
    # 指定JWT的audience(受众)声明。如果设置,每个JWT必须包含这个audience值。
    'AUDIENCE': None,
  
    # 指定JWT的issuer(发行者)声明。如果设置,每个JWT必须包含这个issuer值。
    'ISSUER': None,
  
    # JWK(JSON Web Key)的URL,用于获取公钥。如果使用JWK,则需要设置这个值。
    'JWK_URL': None,
  
    # 允许的时间偏差,用于处理时钟不同步的问题。
    'LEEWAY': 0,

    # 认证头部的类型,这里设置为Bearer,意味着JWT通常放在Authorization头部中,前缀为"Bearer "。
    'AUTH_HEADER_TYPES': ('Bearer',),
  
    # 认证头部的名称,这里设置为HTTP_AUTHORIZATION,即HTTP请求的Authorization头部。
    'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
  
    # 用户模型中的字段,用于唯一标识用户。
    'USER_ID_FIELD': 'id',
  
    # JWT中的声明,用于存储用户ID。
    'USER_ID_CLAIM': 'user_id',
  
    # 用于确定用户是否通过认证的规则。
    'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',

    # 允许的认证令牌类。
    'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
  
    # JWT中的声明,用于标识令牌类型。
    'TOKEN_TYPE_CLAIM': 'token_type',
  
    # 自定义的用户类,用于表示JWT中的用户信息。
    'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
  
    # JWT中的声明,用于存储JWT的唯一标识符。
    'JTI_CLAIM': 'jti',
  
    # 滑动窗口令牌的刷新过期声明。
    'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
  
    # 滑动窗口令牌的有效期。
    'SLIDING_TOKEN_LIFETIME': datetime.timedelta(minutes=5),
    # 滑动窗口令牌的刷新令牌有效期。
    'SLIDING_TOKEN_REFRESH_LIFETIME': datetime.timedelta(days=1),
}

# 指定认证方式
AUTHENTICATION_BACKENDS = (
    'chen.api_views.CustomBackend',
)