Vue学习笔记-Django REST framework3后端接口API学习
一 使用环境
开发系统: windows
后端IDE: PyCharm
前端IDE: VSCode
数据库: msyql,navicat
编程语言: python3.7 (Windows x86-64 executable installer)
虚拟环境: virtualenvwrapper
开发框架: Django 2.2
二 Vue学习笔记-Djiang REST framework3 后端接口API学习
官网: https://www.django-rest-framework.org
学习博客:
https://www.cnblogs.com/wupeiqi/articles/7805382.html
https://www.cnblogs.com/Hades123/p/11488667.html#%E8%A7%86%E5%9B%BE%E5%B1%82-apiviewspy
https://www.cnblogs.com/derek1184405959/p/8733194.html
1.按装配置,基于Django实现
pip install djangorestframework
也可以在pycharm这样按装
2.settings.py文件配置
INSTALLED_APPS = [ 'rest_framework', ]
3.基本流程(展示用户信息)
3.1 A03cabj下的 url.py 和 A001qyyh下的 url.py
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('qyyh/', include('A001qyyh.urls')), # 分发到A001qyyh.urls
# 方法一 from django.urls import path from A001qyyh import views urlpatterns = [ path('users/', views.UserInfoAPIView.as_view()) ]
3.2 models.py
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 导包规范-1.Python标准模块 # 导包规范-2.第三方模块 # 导包规范-3.自已的模块 from datetime import datetime from django.db import models from django.contrib.auth.models import AbstractUser # AbstractUser继承原用django中的用户原有字段再扩展 from db.base_model import BaseModel # 模型抽象基类 # 登录系统用户信息 class UserProfile(AbstractUser, BaseModel): # 必需在settings中设定,配置django认证系统使用的模型类AbstractUse,必需配置 AUTH_USER_MODEL= "APP名.模型类名" # AbstractUser中已有字段: # id(主键字段) # password(密码) # last_login(最后登录时间) # is_superuser(是否超级用户) # username(用户名,不要改动) # first_name(第一次用户名) # last_name(最后一次用户名) # email(邮箱) # is_staff(是否职员) # is_active(是否激活) # date_joined(加入时间) number = models.CharField(verbose_name='编号', max_length=16, unique=True, null=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, null=True) # 必填,可重复 gender = models.SmallIntegerField(verbose_name='性别', blank=True, default=1, choices=((1, '男'), (2, '女'))) # 可填 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='userProfile_company', verbose_name='公司') # 当前表名+关系表名 token = models.OneToOneField('UsersToken', on_delete=models.CASCADE, unique=True, null=True,blank=True) class Meta: verbose_name = '登录用户信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 if self.real_name: return self.real_name else: return self.username # 返回此对象的用户名 # 登录系统用户信息token表 class UsersToken(models.Model): token = models.CharField(max_length=3000, null=True, blank=True) # 用户认证用 expiration_time = models.DateTimeField(verbose_name='过期时间', default=datetime.now, null=True, blank=True) # token过期时间 add_time = models.DateTimeField(verbose_name='添加时间', default=datetime.now, null=True, blank=True) # token添加时间 # 部门信息 class Department(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 必填,唯一. department = models.CharField(verbose_name='部门', max_length=24, unique=True) # 必填,唯一. company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='department_company', verbose_name='公司') # 当前表名+关系表名 class Meta: verbose_name = '公司部门信息' verbose_name_plural = verbose_name def __str__(self): return self.department # 员工信息(非登录人员表) class InternalStaff(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, ) # 必填,可重复 gender = models.SmallIntegerField(verbose_name='性别', blank=True, default=1, choices=((1, '男'), (2, '女'))) # 可填 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, department = models.ForeignKey('Department', on_delete=models.PROTECT, null=True, related_name='internalStaff_department', verbose_name='部门名称', ) # 当前表名+关系表名 class Meta: verbose_name = '公司员工信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.real_name # 返回此对象的用户名 # 订单联系人信息表(非登录人员表) class Contacts(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, ) # 必填,可重复 email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, # models.PROTECT,返回1451错误,admin.py中重写方法 delete_view 后,更改为删除提示页面 # related_name='人员_公司'就是通过此表UserProfile查公司企业信息表Company,直接就是:全部公司信息 = Company.人员公司.all() company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='contacts_company', verbose_name='公司名称', ) # 当前表名+关系表名 telephone = models.ForeignKey('Telephone', on_delete=models.PROTECT, null=True, related_name='contacts_telephone', verbose_name='电话', ) # 当前表名+关系表名 class Meta: verbose_name = '联系人信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.real_name # 返回此对象的用户名 # 订单联系人电话信息表(非登录人员表) class Telephone(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, telephone = models.CharField(verbose_name='座机号码', max_length=48, unique=True, blank=True, null=True) # 可填 class Meta: verbose_name = '电话信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.mobile # 返回此对象的用户名 # 企业信息表 class Company(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 必填,唯一,自动生成 full_name = models.CharField(verbose_name='全称', max_length=64, unique=True, help_text='默认开发票的单位名称') # 必填,唯一. shorter_form = models.CharField(verbose_name='简称', max_length=32, unique=True, help_text='重庆长安镖局科技有限公司海南分公司===>简称:长安镖局海南分公司') # 必填,唯一. # 使用ImageField类型,需要按装图像处理标准库Pillow,default=''相当于blank=True, null=True logo = models.ImageField(verbose_name='LOGE', max_length=1280, upload_to='logo/%y/%m', null=True, blank=True) # 可填 address = models.CharField(verbose_name='地址', max_length=128, blank=True, null=True) # 可填 class Meta: verbose_name = '客商公司信息' verbose_name_plural = verbose_name def __str__(self): return self.shorter_form
3.3 新建一个序列化类(将数据转成json格式): serializers.py
3.4 serializers.py
from rest_framework import serializers from A001qyyh.models import UserProfile # 序列化的是数据库的表,尽量用ModelSerializer # 序列化登录系统用户信息UserProfile class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = UserProfile # 被序列化的表名 # fields = '__all__' # 序列化表中的所有字段,用得少. fields = ('last_login', # 最后登录时 'is_superuser', # 是否超级用户 'username', # 用户名,不要改动 'is_staff', # 是否职员 'date_joined', # 加入时间 'number', # 编号 'real_name', # 真实姓名 'gender', # 性别 'email', # 电子邮箱 'company', # 关联公司表 ) # 序列化表中的指定字段,一般用这个方法 depth = 1 # 显示关系表层数(1表示显示到2层),外键值显示对应的全部值
3.5 views.py
from rest_framework.response import Response from django.http import JsonResponse from A001qyyh.models import UserProfile from A001qyyh.serializers import UserProfileSerializer from rest_framework.views import APIView # 方法一:APIView, # 查询所有用户和单个用户*args, **kwargs class UserInfoAPIView(APIView): # 查询所有用户和单个用户 def get(self, request, *args, **kwargs): user_list = UserProfile.objects.all().filter(delete_mark=False) # 查询所有没有删除标志的用户 user_list_serializers = UserProfileSerializer(user_list, many=True) return Response(data=user_list_serializers.data) # return JsonResponse(data=user_list_serializers.data, safe=False) # 直接返回JSON格式,不显示rest_framework页面
3.6 A001qyyh下的 url.py
# 方法一 from django.urls import path from A001qyyh import views urlpatterns = [ path('users/', views.UserInfoAPIView.as_view()) ]
3.7 数据迁移(如果前面django项目已准备好,就不用再迁移文件了),后在admin中添加一些数据
- makemigrations
- migrations
A001qyyh下的 admin.py 中注册表
from django.contrib import admin from A001qyyh import models # Register your models here. admin.site.register(models.UserProfile) # 登录系统用户信息 admin.site.register(models.Telephone) # 订单联系人电话信息表(非登录人员表) admin.site.register(models.InternalStaff) # 员工信息(非登录人员表) admin.site.register(models.Department) # 部门信息 admin.site.register(models.Contacts) # 订单联系人信息表(非登录人员表) admin.site.register(models.Company) # 企业信息表
A001qyyh下的 apps.py
from django.apps import AppConfig class A001QyyhConfig(AppConfig): name = 'A001qyyh' verbose_name = '企业用户信息' main_menu_index = 1 # 数字越大排的越靠前
3.7 运行项目
http://127.0.0.1:8000/qyyhAPI/users/
4.外键字段显示部份字段和choices中显示中文
models.py
# 重写关联字段company,用@property包装成字段属性 @property def shorter_form_company(self): return self.company.shorter_form # 重写关联字段gender,choices中显示性别的中文,get_字段名_display(). def gender_choices(self): return self.get_gender_display()
serializers.py
from rest_framework import serializers from A001qyyh.models import UserProfile # 序列化的是数据库的表,尽量用ModelSerializer # 序列化登录系统用户信息UserProfile class UserProfileSerializer(serializers.ModelSerializer): class Meta: model = UserProfile # 被序列化的表名 # fields = '__all__' # 序列化表中的所有字段,用得少. fields = ('last_login', # 最后登录时 'is_superuser', # 是否超级用户 'username', # 用户名,不要改动 'is_staff', # 是否职员 'date_joined', # 加入时间 'number', # 编号 'real_name', # 真实姓名 'gender', # 性别 'gender_choices', # 性别 'email', # 电子邮箱 'company', # 关联公司表 'shorter_form_company', # 关联公司表显示公司名称 ) # 序列化表中的指定字段,一般用这个方法 # 1.外键值显示对应的全部值 # depth = 1 # 显示关系表层数(1表示显示到2层),外键值显示对应的全部值 # 2.外键值只显示部份值,可序列化也可返序列化,在models.py中用方法重写字段. extra_kwargs = { 'company': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'shorter_form_company': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. 'gender': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'gender_choices': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. }
5.序列化日期格式显示调整
serializers.py
from rest_framework import serializers from A001qyyh.models import UserProfile # 序列化的是数据库的表,尽量用ModelSerializer # 序列化登录系统用户信息UserProfile class UserProfileSerializer(serializers.ModelSerializer): date_joined = serializers.DateTimeField(format='%Y-%m-%d', read_only=True) # 序列化日期显示格式 class Meta: model = UserProfile # 被序列化的表名 # exclude = ('id', 'password') # 排除不显示字段 # fields = '__all__' # 序列化表中的所有字段,用得少. fields = ('last_login', # 最后登录时 'is_superuser', # 是否超级用户 'username', # 用户名,不要改动 'is_staff', # 是否职员 'date_joined', # 加入时间 'number', # 编号 'real_name', # 真实姓名 'gender', # 性别 'gender_choices', # 性别 'email', # 电子邮箱 'company', # 关联公司表 'shorter_form_company', # 关联公司表显示公司名称 ) # 序列化表中的指定字段,一般用这个方法 # 1.外键值显示对应的全部值 # depth = 1 # 显示关系表层数(1表示显示到2层),外键值显示对应的全部值 # 2.外键值只显示部份值,可序列化也可返序列化,在models.py中用方法重写字段. extra_kwargs = { 'company': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'shorter_form_company': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. 'gender': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'gender_choices': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. }
6.jwt多方式登录(用户名,手机号,邮箱)
6.1按装配置 rest_framework_jwt
pip install djangorestframework-jwt
INSTALLED_APPS = [ 'django.contrib.admin',# admin依赖 'django.contrib.auth',# admin依赖 'django.contrib.contenttypes',# admin依赖 'django.contrib.sessions',# admin依赖 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', # 按装包:djangorestframework 'rest_framework_jwt', # 按装包:djangorestframework-jwt 'corsheaders', # 跨域设置4-(1-2):按装,注册跨域包(django-cors-headers),中间件中注册 'A001qyyh.apps.A001QyyhConfig', 'A002ywxx.apps.A002YwxxConfig', ]
6.2使用用户名,手机号,邮箱都可以登录
setting.py
# JWT配置 import datetime JWT_AUTH = { 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # 配置token过期时间 }
views.py
from rest_framework.response import Response from A001qyyh.serializers import LoginSerializer from rest_framework.viewsets import ViewSet # 自定议jwt多种方式登录 # jwt手动签发token class LoginView(ViewSet): def login(self, request, *args, **kwargs): # 序列化传入的值 login_Serializer = LoginSerializer(data=request.data, context={'request': request}) # 生成序列化对象,调用对像的is_valid login_Serializer.is_valid(raise_exception=True) token = login_Serializer.context.get('token') # 取LoginSerializer里手动签发的token username = login_Serializer.context.get('username') return Response({'code': 20000, 'data': {'token': token}, 'username': username})
serializers.py
from rest_framework import serializers from rest_framework.exceptions import ValidationError from rest_framework_jwt.serializers import jwt_payload_handler from rest_framework_jwt.utils import jwt_encode_handler from A001qyyh.models import UserProfile import re # 多种用户登录用户序列化 class LoginSerializer(serializers.ModelSerializer): username = serializers.CharField() # 重新覆盖username字段,数据库中是unique,post,认为是保存数据,校验不过. class Meta: model = UserProfile fields = ['username', 'password'] def validate(self, attrs): username = attrs.get('username') password = attrs.get('password') # 正则匹配不同传入的数据查询数据库 # 手机号匹配 if re.match('^1[3-9][0-9]{9}$', username): user = UserProfile.objects.filter(mobile=username).first() # 邮箱匹配 elif re.match('^.+@[a-zA-Z\d]+\.[a-zA-Z]{2,4}$', username): user = UserProfile.objects.filter(email=username).first() # 用户名匹配 else: user = UserProfile.objects.filter(username=username).first() if user: # 签发taken payload = jwt_payload_handler(user) # 把user传入,得到payload token = jwt_encode_handler(payload) # 把payload传入,得到token self.context['token'] = token # 将token放到context里,views.py中就可以取到返回给前端 self.context['username'] = user.username # 校验密码,因为是密文的,所以要用check_password. if user.check_password(password): return attrs else: raise ValidationError('密码错误!') else: raise ValidationError('用户不存在!')
三 基础学习
1 序列化组件
- 序列化: 将django模型对像转换成json格式,返回给前端使用.
- 反序列化:将客户端传回的数据,校验并转换成字典,存入数据库.
1.1 常用字段和参数
字段 | 字段构造方式 |
---|---|
BooleanField | BooleanField() |
NullBooleanField | NullBooleanField() |
CharField | CharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True) |
EmailField | EmailField(max_length=None, min_length=None, allow_blank=False) |
RegexField | RegexField(regex, max_length=None, min_length=None, allow_blank=False) |
SlugField | SlugField(maxlength=50, min_length=None, allow_blank=False) 正则字段,验证正则模式 [a-zA-Z0-9-]+ |
URLField | URLField(max_length=200, min_length=None, allow_blank=False) |
UUIDField | UUIDField(format='hex_verbose') format: 1) 'hex_verbose' 如"5ce0e9a5-5ffa-654b-cee0-1238041fb31a" 2) 'hex' 如 "5ce0e9a55ffa654bcee01238041fb31a" 3)'int' - 如: "123456789012312313134124512351145145114" 4)'urn' 如: "urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a" |
IPAddressField | IPAddressField(protocol='both', unpack_ipv4=False, **options) |
IntegerField | IntegerField(max_value=None, min_value=None) |
FloatField | FloatField(max_value=None, min_value=None) |
DecimalField | DecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None) max_digits: 最多位数 decimal_palces: 小数点位置 |
DateTimeField | DateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None) |
DateField | DateField(format=api_settings.DATE_FORMAT, input_formats=None) |
TimeField | TimeField(format=api_settings.TIME_FORMAT, input_formats=None) |
DurationField | DurationField() |
ChoiceField | ChoiceField(choices) choices与Django的用法相同 |
MultipleChoiceField | MultipleChoiceField(choices) |
FileField | FileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ImageField | ImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL) |
ListField | ListField(child=, min_length=None, max_length=None) |
DictField | DictField(child=) |
参数名称 | 作用 |
---|---|
max_length | 最大长度 |
min_lenght | 最小长度 |
allow_blank | 是否允许为空 |
trim_whitespace | 是否截断空白字符 |
max_value | 最小值 |
min_value | 最大值 |
参数名称 | 说明 |
---|---|
read_only | 表明该字段仅用于序列化输出,默认False,只读,不进行反序列化 |
write_only | 表明该字段仅用于反序列化输入,默认False,只写,不进行序列化 |
required | 表明该字段在反序列化时,必须输入,默认True, False就可以不传 |
default | 反序列化时使用的默认值 |
allow_null | 表明该字段是否允许传入None,默认False |
validators | 该字段使用的验证器 |
error_messages | 包含错误编号与错误信息的字典 |
label | 用于HTML展示API页面时,显示的字段名称 |
help_text |
用于HTML展示API页面时,显示的字段帮助提示信息 |
1.2 序列化器 ModelSerializer
目的:可以使用ModelSerializer根据模型类生成序列化字段
作用:
1.可以参考模型类生成序列化字段,也可以自已编写字段
2.提供了create创建方法和update更新方法
class Meta 属性:
1.model = UserProfile # 指定模型类生成字段
2.read_only_fields = ['company','gender'] # 设置只读字段,extra_kwargs中也可以设置
3.exclude = ('id', 'password') # 排除不显示字段
4.fields = '__all__' # 序列化表中的所有字段,用得少.
5.fields = ["字段1","字段2"] 指定字段,可以是模型类,也可以自定义
6.extra_kwargs = {
'company': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段.
'shorter_form_company': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段.
'gender': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段.
'gender_choices': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段.
}
7.depth = 1 # 显示关系表层数(1表示显示到2层),外键值显示对应的全部值
# 1.外键字段ForeignKey-主键显示 PrimaryKeyRelatedField 中选项==>1.read_only=True,2.queryset=UserProfile.objects.all() # company = serializers.PrimaryKeyRelatedField(read_only=True) # company = serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()) # 2.外键字段ForeignKey-名字显示 使用关联模型表(Company)中的__str__方法返回值,StringRelatedField. # company = serializers.StringRelatedField(read_only=True) # 3.外键字段ForeignKey-所有信息显示 关联外键对应定义的序列化器 CompanyProfileSerializer # company = CompanyProfileSerializer()
2 视图组件
2.1 一级视图 : APIView(Class-based Views)
获取数据的方式:
GET : request.query_params
POST/put/delete : request.data
返回数据方式: Response (APIView的Response 可以响应各种数据和状态)
from rest_framework import status # 状态码
return Response(data, status=status.HTTP_200_OK)
urls.py
urlpatterns = [ path('users/', views.UserProfileListAPIView.as_view()), # 列表视图,获取所有用户-GET/创建单个用户-POST re_path(r'^users/(?P<pk>\d+)/$', views.UserProfileDetailsAPIView.as_view()), # 详情视图,获取单个用户-GET/修改单个用户-PUT/删除单个用户-DELETE ]
models.py
# 导包规范-1.Python标准模块 # 导包规范-2.第三方模块 # 导包规范-3.自已的模块 from datetime import datetime from django.db import models from django.contrib.auth.models import AbstractUser # AbstractUser继承原用django中的用户原有字段再扩展 from db.base_model import BaseModel # 模型抽象基类 # 登录系统用户信息 class UserProfile(AbstractUser, BaseModel): # 必需在settings中设定,配置django认证系统使用的模型类AbstractUse,必需配置 AUTH_USER_MODEL= "APP名.模型类名" # AbstractUser中已有字段: # id(主键字段) # password(密码) # last_login(最后登录时间) # is_superuser(是否超级用户) # username(用户名,不要改动) # first_name(第一次用户名) # last_name(最后一次用户名) # email(邮箱) # is_staff(是否职员) # is_active(是否激活) # date_joined(加入时间) number = models.CharField(verbose_name='编号', max_length=16, unique=True, null=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, null=True) # 必填,可重复 gender = models.SmallIntegerField(verbose_name='性别', blank=True, default=1, choices=((1, '男'), (2, '女'))) # 可填 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='userProfile_company', verbose_name='公司') # 当前表名+关系表名 class Meta: verbose_name = '登录用户信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 if self.real_name: return self.real_name else: return self.username # 返回此对象的用户名 # 重写关联字段company,用@property包装成字段属性 @property def shorter_form_company(self): return self.company.shorter_form # 重写关联字段gender,choices中显示性别的中文,get_字段名_display(). def gender_choices(self): return self.get_gender_display() # 部门信息 class Department(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 必填,唯一. department = models.CharField(verbose_name='部门', max_length=24, unique=True) # 必填,唯一. company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='department_company', verbose_name='公司') # 当前表名+关系表名 class Meta: verbose_name = '公司部门信息' verbose_name_plural = verbose_name def __str__(self): return self.department # 员工信息(非登录人员表) class InternalStaff(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, ) # 必填,可重复 gender = models.SmallIntegerField(verbose_name='性别', blank=True, default=1, choices=((1, '男'), (2, '女'))) # 可填 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, department = models.ForeignKey('Department', on_delete=models.PROTECT, null=True, related_name='internalStaff_department', verbose_name='部门名称', ) # 当前表名+关系表名 class Meta: verbose_name = '公司员工信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.real_name # 返回此对象的用户名 # 订单联系人信息表(非登录人员表) class Contacts(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 real_name = models.CharField(verbose_name='真实姓名', max_length=16, ) # 必填,可重复 email = models.EmailField(verbose_name='电子邮箱', unique=True, null=True, help_text='不能有中文!') # 必填,唯一, # models.PROTECT,返回1451错误,admin.py中重写方法 delete_view 后,更改为删除提示页面 # related_name='人员_公司'就是通过此表UserProfile查公司企业信息表Company,直接就是:全部公司信息 = Company.人员公司.all() company = models.ForeignKey('Company', on_delete=models.PROTECT, null=True, related_name='contacts_company', verbose_name='公司名称', ) # 当前表名+关系表名 telephone = models.ForeignKey('Telephone', on_delete=models.PROTECT, null=True, related_name='contacts_telephone', verbose_name='电话', ) # 当前表名+关系表名 class Meta: verbose_name = '联系人信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.real_name # 返回此对象的用户名 # 订单联系人电话信息表(非登录人员表) class Telephone(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 不重复,自动生成 mobile = models.CharField(verbose_name='手机号码', max_length=11, unique=True, null=True) # 必填,唯一, telephone = models.CharField(verbose_name='座机号码', max_length=48, unique=True, blank=True, null=True) # 可填 class Meta: verbose_name = '电话信息' verbose_name_plural = verbose_name # 控制对象输出内容 def __str__(self): # 必需有值的字段,当前对象的描写 return self.mobile # 返回此对象的用户名 # 企业信息表 class Company(BaseModel): number = models.CharField(verbose_name='编码', max_length=16, unique=True, help_text='保存时自动生成') # 必填,唯一,自动生成 full_name = models.CharField(verbose_name='全称', max_length=64, unique=True, help_text='默认开发票的单位名称') # 必填,唯一. shorter_form = models.CharField(verbose_name='简称', max_length=32, unique=True, help_text='重庆长安镖局科技有限公司海南分公司===>简称:长安镖局海南分公司') # 必填,唯一. # 使用ImageField类型,需要按装图像处理标准库Pillow,default=''相当于blank=True, null=True logo = models.ImageField(verbose_name='LOGE', max_length=1280, upload_to='logo/%y/%m', null=True, blank=True) # 可填 address = models.CharField(verbose_name='地址', max_length=128, blank=True, null=True) # 可填 class Meta: verbose_name = '客商公司信息' verbose_name_plural = verbose_name def __str__(self): return self.shorter_form
serializers.py
from rest_framework import serializers from A001qyyh.models import UserProfile, Company # 定义公司序列化器 class CompanySerializers(serializers.ModelSerializer): # 可以额外填加模型类中没有的字段 # re_password = serializers.CharField(read_only=True) # 核对密码,注册时两个密码比对一致性,只反序列化时用,不存数据库. class Meta: model = Company # 参考模型类生成字段 fields = "__all__" # 生成所有字段 # 定义用户序列化器 class UserProfileSerializers(serializers.ModelSerializer): # 可以额外填加模型类中没有的字段 # re_password = serializers.CharField(read_only=True) # 核对密码,注册时两个密码比对一致性,只反序列化时用,不存数据库. # 1.外键字段ForeignKey-主键显示 PrimaryKeyRelatedField 中选项==>1.read_only=True,2.queryset=UserProfile.objects.all() # company = serializers.PrimaryKeyRelatedField(read_only=True) # company = serializers.PrimaryKeyRelatedField(queryset=UserProfile.objects.all()) # 2.外键字段ForeignKey-名字显示 使用关联模型表(Company)中的__str__方法返回值,StringRelatedField. # company = serializers.StringRelatedField(read_only=True) # 3.外键字段ForeignKey-所有信息显示 关联外键对应定义的序列化器 CompanySerializers,只能放到引用上面 # company = CompanySerializers() date_joined = serializers.DateTimeField(format='%Y-%m-%d', read_only=True) # 序列化日期显示格式,只读. class Meta: model = UserProfile # 参考模型类生成字段 # exclude = ('id', 'password') # 排除不显示字段 # fields = '__all__' # 序列化表中的所有字段,用得少. # read_only_fields = ['company','gender'] # 设置只读字段,extra_kwargs中也可以设置 fields = ('last_login', # 最后登录时 'is_superuser', # 是否超级用户 'username', # 用户名,不要改动 'password', # 用户名,不要改动 'is_staff', # 是否职员 'date_joined', # 加入时间 'number', # 编号 'real_name', # 真实姓名 'gender', # 性别 'gender_choices', # choices中显示性别的中文,在models.py中用方法重写字段. 'email', # 电子邮箱 'company', # 关联公司表 'shorter_form_company', # 关联公司表显示公司名称 ) # 序列化表中的指定字段,一般用这个方法 # 1.外键值显示对应的全部值 # depth = 1 # 显示关系表层数(1表示显示到2层),外键值显示对应的全部值 # 2.外键值只显示部份值,可序列化也可返序列化,在models.py中用方法重写字段. # 对字段进行设制限制验证条件 extra_kwargs = { 'company': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'shorter_form_company': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. 'gender': {'write_only': True}, # 表示只能写,不能读,能存进数据库,数据库字段. 'gender_choices': {'read_only': True}, # 只能读,不能进行修改,不能存进数据库,重写字段. }
views.py
""""""""" 视图说明 功能 请求方式 请求路径 列表视图 获取所有用户 GET /users 列表视图 创建单个用户 POST /users 详情视图 获取单个用户 GET /users/{pk} 详情视图 修改单个用户 PUT /users/{pk} 详情视图 删除单个用户 DELETE /users/{pk} """ from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status from A001qyyh.models import UserProfile from A001qyyh.study_02.serializers import UserProfileSerializers # 1 列表视图 class UserProfileListAPIView(APIView): # 获取所有用户 def get(self, request): # 1查询所有的用户 users = UserProfile.objects.all() # 2数据转换(创建序列化器序列化多个对象,转换成json数据) serializers = UserProfileSerializers(instance=users, many=True) # many=True表示序列化多个对象 # 3返回响应 # return JsonResponse(serializers.data, safe=False) # 非字典要加上safe=False,表示可以安全返回非字典 return Response(serializers.data, status=status.HTTP_200_OK) # status是内置的状态码 # 创建单个用户 def post(self, request): # 1获取参数 dict_data = request.data # 2序列化 serializers = UserProfileSerializers(data=dict_data) # 前端传过来的数据用data # 3校验参数 serializers.is_valid(raise_exception=True) # 4数据入库 serializers.save() # 5返回响应 return Response(serializers.data, status=status.HTTP_201_CREATED) # 2 详情视图,带参数pk或id都是一样的 class UserProfileDetailsAPIView(APIView): # 获取单个用户 def get(self, request, pk): # 1通过pk获取对象 user = UserProfile.objects.get(pk=pk) # 2转换数据(创建序列化器序列化单个对象,转换成json数据) serializers = UserProfileSerializers(instance=user) # 单个数据不用传many=True,表示序列化多个对象 # 3返回响应 return Response(serializers.data, status=status.HTTP_200_OK) # 修改单个用户(传两个数据) def put(self, request, pk): # 1通过request.data获取前端传过来的数据 dict_data = request.data user = UserProfile.objects.get(pk=pk) # 2创建序列化器对象 serializers = UserProfileSerializers(instance=user, data=dict_data) # 将接收到的dict_data数据更新到user对象中 # 3校验数据 serializers.is_valid(raise_exception=True) # 数据入库 serializers.save() # 5返回响应 return Response(serializers.data, status=status.HTTP_201_CREATED) # 删除单个用户 def delete(self, request, pk): # 1通过pk获取参数,对象 user = UserProfile.objects.get(pk=pk) # 2删除数据 user.delete() # 3返回响应 return Response(status=status.HTTP_204_NO_CONTENT)
2.2 二级视图 : GenericAPIView和 Mixin
特点:
1.GenericAPIView继承自APIView,为列表视图和详情视图添加了常用的方法和属性.
主要方法(3个):
get_queryset : 获取queryset的数据集
get_object : 根据lookup_field获取单个对象
get_serializer : 获取serializer_class序列化器对象
主要属性(3个):
queryset : 通用的视图集
serializer_class : 通用的序列化器
lookup_field : 默认是pk,可以手动改为id,不能改为其它的.
2.可以和一个或多个Mixins类配合使用,可以提供通用的增删改查功能
from rest_framework.generics import GenericAPIView from rest_framework.mixins import ListModelMixin
""""""""" 视图 类名称 提供方法 功能 列表视图 ListModelMixin return self.list(request, *args, **kwargs) 查询所有的数据 列表视图 CreateModelMixin return self.create(request, *args, **kwargs) 创建单个对象 详情视图 RetrieveModelMixin return self.retrieve(request, *args, **kwargs) 获取单个对象 详情视图 UpdateModelMixin return self.update(request, *args, **kwargs) 更新单个对象 详情视图 DestroyModelMixin return self.destroy(request, *args, **kwargs) 删除单个对象 """
# 1 列表视图 class UserProfileListAPIView(GenericAPIView,ListModelMixin ): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 获取所有用户 def get(self, request): return self.list(request)
2.3 三级视图 : 通用视图 Concrete View Classes(具体的视图类)
特点:
1.如果没有大量的自定义行为,就可以使用通用视图解决(三级视图)
from rest_framework.generics import ListAPIView, CreateAPIView
""""""""" 视图 类名称 父类 提供方法 功能 列表视图 CreateAPIView GenericAPIView post 创建单个对象 CreateModelMixin 列表视图 ListAPIView GenericAPIView get 获取所有数据 ListModelMixin 详情视图 RetrieveAPIView GenericAPIView get 获取单个对象 RetrieveModelMixin 详情视图 DestroyAPIView GenericAPIView delete 删除单个对象 DestroyModelMixin 详情视图 UpdateAPIView GenericAPIView put/patch 更新单个对象 UpdateModelMixin """
# 1 列表视图-获取所有数据和创建单个对象 class UserProfileListAPIView(ListAPIView, CreateAPIView): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers
3 视图集(ViewSets)
特点:
1.可以装一组相关的操作放在一个类中进行完成
2.不再提供get,post方法,使用list
和retrieve方
法来替代
3.可以将标准的请求方式(get,post,delete),和mixin中的方面法做映射.
""""""""" 类名称 父类 功能 ViewSet APIView 可以做路由映射 ViewSetMixin GenericViewSet GenericAPIView 可以做路由映射,可以使用三个属性,三个方法 ViewSetMixin ModelViewSet GenericViewSet 所有的增删改查功能,可以使用三个属性,三个方法 5个mixin类 ReadOnlyModelViewSet RetrieveModelMixin 获取单个,所有数据,可以使用三个属性,三个方法 ListModelMixin GenericViewSet """
4.使用 ViewSet 获联单个和所有用户,官方例子:Example
urls.py
urlpatterns = [ path('users/', views.UserViewSet.as_view({'get': 'list'})), # 列表视图,获取所有用户-GE re_path(r'^users/(?P<pk>\d+)/$', views.UserViewSet.as_view({'get': 'retrieve'})), # 详情视图,获取单个用户-GET ]
views.py
from django.contrib.auth.models import User from django.shortcuts import get_object_or_404 from myapps.serializers import UserSerializer from rest_framework import viewsets from rest_framework.response import Response class UserViewSet(viewsets.ViewSet): """ A simple ViewSet for listing or retrieving users. """ def list(self, request): queryset = User.objects.all() serializer = UserSerializer(queryset, many=True) return Response(serializer.data) def retrieve(self, request, pk=None): queryset = User.objects.all() user = get_object_or_404(queryset, pk=pk) serializer = UserSerializer(user) return Response(serializer.data)
4.使用 ReadOnlyModelViewSet 获联单个和所有用户
urls.py
urlpatterns = [ path('users/', views.UserProfileListAPIView.as_view({'get': 'list'})), # 列表视图,获取所有用户-GET re_path(r'^users/(?P<pk>\d+)/$', views.UserProfileListAPIView.as_view({'get': 'retrieve'})), # 详情视图,获取单个用户-GET ]
views.py
from rest_framework.viewsets import ReadOnlyModelViewSet # 1 列表视图-获联单个和所有用户 class UserProfileListAPIView(ReadOnlyModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers
5.使用 ModelViewSet 实现列表视图和详情视图(如下5个功能)
""""""""" 视图说明 功能 请求方式 请求路径 列表视图 获取所有用户 GET /users 列表视图 创建单个用户 POST /users 详情视图 获取单个用户 GET /users/{pk} 详情视图 修改单个用户 PUT /users/{pk} 详情视图 删除单个用户 DELETE /users/{pk} """
urls.py
urlpatterns = [ path('users/', views.UserProfileListAPIView.as_view({'get': 'list', 'post': 'create'})),# 列表视图,获取所有用户-GET/创建单个用户-POST re_path(r'^users/(?P<pk>\d+)/$',views.UserProfileListAPIView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),# 详情视图,获取单个用户-GET/修改单个用户-PUT/删除单个用户-DELETE ]
views.py
from rest_framework.viewsets import ModelViewSet # 5个功能一起上 class UserProfileListAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers
6.视图集的额外动作方法(不带参数和带参数partial=True,带参数局部更新,不写报错.)
urls.py
from django.urls import path from A001qyyh.study_03 import views urlpatterns = [ # 列表视图,获取所有用户-GET/创建单个用户-POST path('users/', views.UserProfileModelViewSeAPIView.as_view({'get': 'list', 'post': 'create'})), # 详情视图,获取单个用户-GET/修改单个用户-PUT/删除单个用户-DELETE path('users/<int:pk>/', views.UserProfileModelViewSeAPIView.as_view({ 'get': 'retrieve', 'put': 'update', 'delete': 'destroy' })), # 1.自定议的方法路由-查询获取所有为男的的用户-不带参数 path('users/bread_users/', views.UserProfileModelViewSeAPIView.as_view({'get': 'bread_users'})), # 2.自定议的方法路由-修改用户名称-带参数partial=True修改部分数据,局部更新 path('users/update_user/<int:pk>/', views.UserProfileModelViewSeAPIView.as_view({'put': 'update_user'})), ]
views.py
from A001qyyh.models import UserProfile from A001qyyh.study_03.serializers import UserProfileSerializers from rest_framework.viewsets import ModelViewSet from rest_framework.response import Response # 5个功能一起上ModelViewSet class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 1.查询获取所有为男的的用户-不带参数 def bread_users(self, request): # 1.获取指定用户 users = UserProfile.objects.filter(gender=1) # 2.创建序列化器对象-将模型类的数据转换成json-序列化-多个 serializer = UserProfileSerializers(users, many=True) # 3.返回响应 return Response(serializer.data) # 2.修改用户名称-带参数 def update_user(self, request, pk): # 1.从模型中获取id=pk的这本书的书名 # user = self.get_object() user = UserProfile.objects.get(pk=pk) # 2.获取前端传过更新的数据 data = request.data # 3.创建序列化器对象-partial=True修改部分数据 # serializer = UserProfileSerializers(instance=user, data=data, partial=True) serializer = self.get_serializer(instance=user, data=data, partial=True) # 用这个后面写方代码没有提示 # 4.校验数据 serializer.is_valid(raise_exception=True) # 5.保存入库 serializer.save() # 6.返回数据 return Response(serializer.data)
3 路由 Routers 只能给视图集自动生成路由,其它的不能。
1.可以通过 DefaultRouter 和 SimpleRouter 两个类来自动生成路由
2.DefaultRouter生成路由格式(DRF页面+json页面)
""" [ 列表路由(DRF页面+json页面) <URLPattern '^users/$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users/ <URLPattern '^users\.(?P<format>[a-z0-9]+)/?$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users.json 详情路由(DRF页面+json页面) <URLPattern '^users/(?P<pk>[^/.]+)/$' [name='users-detail']>, ===> http://127.0.0.1:8000/S2APIV/users/1/ <URLPattern '^users/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='users-detail']>, ===> http://127.0.0.1:8000/S2APIV/users/1.json 根路由(DRF页面+json页面) <URLPattern '^$' [name='api-root']>, ===> http://127.0.0.1:8000/S2APIV/ <URLPattern '^\.(?P<format>[a-z0-9]+)/?$' [name='api-root']> ===> http://127.0.0.1:8000/S2APIV/.json ] """
urls.py
from A001qyyh.study_04_Routers import views from rest_framework.routers import SimpleRouter, DefaultRouter urlpatterns = [] # 1创建路由(SimpleRouter, DefaultRouter) router = DefaultRouter() # 2注册视图集(users是指定的路径和别名) router.register('users', views.UserProfileModelViewSeAPIView, basename='users') # 3.将生成路由加入到urlpatterns中 urlpatterns += router.urls # 4输入结果 print(urlpatterns)
views.py
from A001qyyh.models import UserProfile from A001qyyh.study_03.serializers import UserProfileSerializers from rest_framework.viewsets import ModelViewSet # 5个功能一起上ModelViewSet class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers
3.SimpleRouter生成路由格式(DRF页面)
""" [<URLPattern '^users/$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users/ <URLPattern '^users/(?P<pk>[^/.]+)/$' [name='users-detail']>] ===> http://127.0.0.1:8000/S2APIV/users/1/ """
4.自定方法中SimpleRouter生成路由格式(DRF页面)加装饰器 ---> @action(methods=['GET'], detail=False)
urls.py
from A001qyyh.study_04_Routers import views from rest_framework.routers import SimpleRouter, DefaultRouter urlpatterns = [] # 1创建路由(SimpleRouter, DefaultRouter) router = SimpleRouter() # 2注册视图集(users是指定的路径和别名) router.register('users', views.UserProfileModelViewSeAPIView, basename='users') # 3.将生成路由加入到urlpatterns中 urlpatterns += router.urls # 4输入结果 print(urlpatterns) """ 1.DefaultRouter(DRF页面+json页面) [ 列表路由(DRF页面+json页面) <URLPattern '^users/$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users/ <URLPattern '^users\.(?P<format>[a-z0-9]+)/?$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users.json 详情路由(DRF页面+json页面) <URLPattern '^users/(?P<pk>[^/.]+)/$' [name='users-detail']>, ===> http://127.0.0.1:8000/S2APIV/users/1/ <URLPattern '^users/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$' [name='users-detail']>, ===> http://127.0.0.1:8000/S2APIV/users/1.json 根路由(DRF页面+json页面) <URLPattern '^$' [name='api-root']>, ===> http://127.0.0.1:8000/S2APIV/ <URLPattern '^\.(?P<format>[a-z0-9]+)/?$' [name='api-root']> ===> http://127.0.0.1:8000/S2APIV/.json ] 2.SimpleRouter(DRF页面) [ 列表路由(DRF页面) <URLPattern '^users/$' [name='users-list']>, ===> http://127.0.0.1:8000/S2APIV/users/ 详情路由(DRF页面) <URLPattern '^users/(?P<pk>[^/.]+)/$' [name='users-detail']>] ===> http://127.0.0.1:8000/S2APIV/users/1/ ] """ """ SimpleRouter(DRF页面 [ <URLPattern '^users/$' [name='users-list']>, <URLPattern '^users/(?P<pk>[^/.]+)/$' [name='users-detail']>, 1.自定义不带参数方法路由 <URLPattern '^users/bread_users/$' [name='users-bread-users']>, 2.自定义带参数方法路由 <URLPattern '^users/(?P<pk>[^/.]+)/update_user/$' [name='users-update-user']> ] """
views.py
from A001qyyh.models import UserProfile from A001qyyh.study_04_Routers.serializers import UserProfileSerializers from rest_framework.viewsets import ModelViewSet from rest_framework.decorators import action from rest_framework.response import Response # 5个功能一起上ModelViewSet class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 1.查询获取所有为男的的用户-不带参数 # 将自已的方法自动添加到路由中, # 生成规则:主路由+方法名:<URLPattern '^users/bread_users/$' [name='users-bread-users']>, # detail=True是否带参数,不带就取False(GET就是false). @action(methods=['GET'], detail=False) # 1.查询获取所有为男的的用户-不带参数 def bread_users(self, request): # 1.获取指定用户 users = UserProfile.objects.filter(gender=1) # 2.创建序列化器对象-将模型类的数据转换成json-序列化-多个 serializer = UserProfileSerializers(users, many=True) # 3.返回响应 return Response(serializer.data) # 2.修改用户名称-带参数 # 生成规则:主路由+{pk}+方法名:<URLPattern '^users/(?P<pk>[^/.]+)/update_user/$' [name='users-update-user']>, # detail=True是否带参数,不带就取False(GET就是false). @action(methods=['PUT'], detail=True) def update_user(self, request, pk): # 1.从模型中获取id=pk的这本书的书名 # user = self.get_object() user = UserProfile.objects.get(pk=pk) # 2.获取前端传过更新的数据 data = request.data # 3.创建序列化器对象-partial=True修改部分数据 # serializer = UserProfileSerializers(instance=user, data=data, partial=True) serializer = self.get_serializer(instance=user, data=data, partial=True) # 用这个后面写方代码没有提示 # 4.校验数据 serializer.is_valid(raise_exception=True) # 5.保存入库 serializer.save() # 6.返回数据 return Response(serializer.data)
4 认证 Authentication
配置 Setting the authentication scheme
全局配置:settings.py
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ] }
局部配置:views.py
class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication]
配置了全局和局部,默认使用局部认证,认证要与权限一起用!
4 权限 Permissions
配置 Setting the permission policy
全局配置:settings.py
权限用户说明:API Reference
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ] }
局部配置:views.py
class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限,普通用户 permission_classes = [IsAuthenticated]
配置了全局和局部,默认使用局部权限,认证要与权限一起用!
4 限流/频率 Throttling 通过配置限制不同用户的访问次数
配置 Setting the throttling policy
全局配置:settings.py
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ], # 限流配置 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', # 未认证匿名用户 'rest_framework.throttling.UserRateThrottle' # 认证用户 ], 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', # 匿名用户一天访问100次 'user': '1000/day' # 认证用户一天访问1000次 } }
局部配置:views.py
from rest_framework.authentication import SessionAuthentication,BasicAuthentication from rest_framework.permissions import IsAuthenticated from rest_framework.throttling import UserRateThrottle # 5个功能一起上ModelViewSet class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限 permission_classes = [IsAuthenticated] # 局部限流 throttle_classes = [UserRateThrottle]
配置了全局和局部,默认使用局部权限
自定义限流 ScopedRateThrottle 全局定义,局部使用
settings.py
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ], # 限流配置 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', # 未认证匿名用户 'rest_framework.throttling.UserRateThrottle' # 认证用户 ], # 可选限流 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', # 匿名用户一天访问100次 'user': '1000/day', # 认证用户一天访问1000次 'downloads': '1000/minute' # 每分钟下载次数1000次,可选限流,全局定义,局部使用直接在views.py中使用 } }
views.py 局部使用
class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限 permission_classes = [IsAuthenticated] # 局部限流 throttle_classes = [UserRateThrottle] # 可选自定义限流 throttle_scope = 'downloads'
5 分页 Pagination
配置 Setting the pagination style
全局配置:settings.py
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ], # 限流配置 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', # 未认证匿名用户 'rest_framework.throttling.UserRateThrottle' # 认证用户 ], # 可选限流 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', # 匿名用户一天访问100次 'user': '1000/day', # 认证用户一天访问1000次 'downloads': '1000/minute' # 每分钟下载次数1000次,可选限流,全局定义,局部使用直接在views.py中使用 }, # 全局分页 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 100 }
局部配置:views.py
class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限 permission_classes = [IsAuthenticated] # 局部限流 throttle_classes = [UserRateThrottle] # 可选自定义限流 throttle_scope = 'downloads' # 局部分页 # 方式一 # http://api.example.org/accounts/?limit=100 # http://api.example.org/accounts/?offset=400&limit=100 # pagination_class = LimitOffsetPagination # 方式二 # http://api.example.org/accounts/?page=4 # http://api.example.org/accounts/?page=4&page_size=100 pagination_class = PageNumberPagination
配置了全局和局部,默认使用局部
自定义分页:Modifying the pagination style
6 过滤器 DjangoFilterBackend
按装:
pip install django-filter
注册:settings.py
INSTALLED_APPS = [ 'django.contrib.admin',# admin依赖 'django.contrib.auth',# admin依赖 'django.contrib.contenttypes',# admin依赖 'django.contrib.sessions',# admin依赖 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', # 按装包:djangorestframework 'rest_framework_jwt', # 按装包:djangorestframework-jwt 'corsheaders', # 跨域设置4-(1-2):按装,注册跨域包(django-cors-headers),中间件中注册 'django_filters', # 过滤器,包:django-filter ]
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ], # 限流配置 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', # 未认证匿名用户 'rest_framework.throttling.UserRateThrottle' # 认证用户 ], # 可选限流 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', # 匿名用户一天访问100次 'user': '1000/day', # 认证用户一天访问1000次 'downloads': '1000/minute' # 每分钟下载次数1000次,可选限流,全局定义,局部使用直接在views.py中使用 }, # 全局分页 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 100, # 全局过滤器 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'] }
局部使用:views.py
class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限 permission_classes = [IsAuthenticated] # 局部限流 throttle_classes = [UserRateThrottle] # 可选自定义限流 throttle_scope = 'downloads' # 局部分页 # 方式一 # http://api.example.org/accounts/?limit=100 # http://api.example.org/accounts/?offset=400&limit=100 # pagination_class = LimitOffsetPagination # 方式二 # http://api.example.org/accounts/?page=4 # http://api.example.org/accounts/?page=4&page_size=100 pagination_class = PageNumberPagination # 局部过滤(精确过滤) filter_backends = [DjangoFilterBackend] search_fields = ['username', 'email'] # 模型中的字段, # 局部过滤使用 # http://example.com/api/users?search=russell
7 排序 OrderingFilter
views.py
from rest_framework import filters # 5个功能一起上ModelViewSet class UserProfileModelViewSeAPIView(ModelViewSet): queryset = UserProfile.objects.all() serializer_class = UserProfileSerializers # 局部认证 authentication_classes = [SessionAuthentication, BasicAuthentication] # 局部权限 permission_classes = [IsAuthenticated] # 局部限流 throttle_classes = [UserRateThrottle] # 可选自定义限流 throttle_scope = 'downloads' # 局部分页 # 方式一 # http://api.example.org/accounts/?limit=100 # http://api.example.org/accounts/?offset=400&limit=100 # pagination_class = LimitOffsetPagination # 方式二 # http://api.example.org/accounts/?page=4 # http://api.example.org/accounts/?page=4&page_size=100 pagination_class = PageNumberPagination # 局部过滤(精确过滤) filter_backends = [DjangoFilterBackend, filters.OrderingFilter] search_fields = ['username', 'email'] # 模型中的字段, # 局部过滤使用 # http://example.com/api/users?search=russell # 局部排序 # filter_backends = [filters.OrderingFilter] ordering_fields = ['username', 'email'] # 排序查询格式 # http://example.com/api/users?ordering=username
8 异常处理 Exceptions
自定义设置 Custom exception handling
在根目录下自定义方法新建一个py文件,my_exception.py
from django.db import DatabaseError # 数据异常 from rest_framework.response import Response from rest_framework.views import exception_handler def custom_exception_handler(exc, context): # 调用系统方法,处理了APIException的异常.或者其子类的异常 response = exception_handler(exc, context) # 判断response是不有值 if response is not None: response.data['status_code'] = response.status_code else: if isinstance(exc, DatabaseError): response = Response("数据库相关的错误!") # 中间可以分细再处理其它错误!(Exception/ValidationError等) else: response = Response("其它相关的错误!") return response
views.py
# REST_FRAMEWORK 配置 REST_FRAMEWORK = { # 全局认证 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.BasicAuthentication', # 基本认证,常用于测式. 'rest_framework.authentication.SessionAuthentication', # Token令牌认证. ], # 全局权限 'DEFAULT_PERMISSION_CLASSES': [ # 'rest_framework.permissions.IsAuthenticated', # 普通用户 'rest_framework.permissions.AllowAny', # 所有用户 # 'rest_framework.permissions.IsAuthenticated', # 管理员用户 ], # 限流配置 'DEFAULT_THROTTLE_CLASSES': [ 'rest_framework.throttling.AnonRateThrottle', # 未认证匿名用户 'rest_framework.throttling.UserRateThrottle' # 认证用户 ], # 可选限流 'DEFAULT_THROTTLE_RATES': { 'anon': '100/day', # 匿名用户一天访问100次 'user': '1000/day', # 认证用户一天访问1000次 'downloads': '1000/minute' # 每分钟下载次数1000次,可选限流,全局定义,局部使用直接在views.py中使用 }, # 全局分页 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination', 'PAGE_SIZE': 100, # 全局过滤器 'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend'], # 全局异常 'EXCEPTION_HANDLER': 'A02CABJBE.my_exception.custom_exception_handler' }
9 文档接口
按装
pip install coreapi
urls.py
from rest_framework.documentation import include_docs_urls urlpatterns = [ path('admin/', admin.site.urls), path('api_docs/', include_docs_urls(title='长安镖局开发文档')) ]
10 其它
10.1前端传过来的数据从哪取?
1.原生地址栏传过来的用: request.GET
DRF地址栏传过来的用: query_params
请求首行,请求地址,请求式,htt版本,请求头,请求体
2.原生从请求体中传过来的用: request.POST(json格式解析不了) ===> 最终是从 request.body 中取
DRF从请求体中传过来的用: request.data
3.从请求头中传过来的用: request.META.get("HTTP_变成大写")
注意:
-
如果headerkey为auth-token,即headers={'auth-token':'1234'}
-
应该使用request.META.get("HTTP_AUTH_TOKEN")获取
-
headerkey中的小写转为大写,横线“-”转为下划线“_”,并且加上前缀HTTP
-
尤其注意headerkey中不应该包含 HTTP前缀,以及符号"_",否则会取不到对应的值