一  使用环境  

  开发系统: 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

# 导包规范-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('用户不存在!')

三  基础学习

序列化组件

  • 序列化: 将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.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

视图集(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_变成大写")

   注意:

  1. 如果headerkey为auth-token,即headers={'auth-token':'1234'}
  2.  应该使用request.META.get("HTTP_AUTH_TOKEN")获取
  3.  headerkey中的小写转为大写,横线“-”转为下划线“_”,并且加上前缀HTTP
  4.  尤其注意headerkey中不应该包含 HTTP前缀,以及符号"_",否则会取不到对应的值

Vue学习笔记-Django REST framework3后端接口API学习的更多相关文章

  1. python学习笔记--Django入门四 管理站点--二

    接上一节  python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...

  2. Java web与web gis学习笔记(二)——百度地图API调用

    系列链接: Java web与web gis学习笔记(一)--Tomcat环境搭建 Java web与web gis学习笔记(二)--百度地图API调用 JavaWeb和WebGIS学习笔记(三)-- ...

  3. golang学习笔记7 使用beego swagger 实现API自动化文档

    golang学习笔记7 使用beego swagger 实现API自动化文档 API 自动化文档 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/doc ...

  4. UFLDL深度学习笔记 (三)无监督特征学习

    UFLDL深度学习笔记 (三)无监督特征学习 1. 主题思路 "UFLDL 无监督特征学习"本节全称为自我学习与无监督特征学习,和前一节softmax回归很类似,所以本篇笔记会比较 ...

  5. VS2013中Python学习笔记[Django Web的第一个网页]

    前言 前面我简单介绍了Python的Hello World.看到有人问我搞搞Python的Web,一时兴起,就来试试看. 第一篇 VS2013中Python学习笔记[环境搭建] 简单介绍Python环 ...

  6. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  7. Java学习笔记16---抽象类与接口的浅显理解

    抽象类是由abstract修饰的类,定义方式如public abstract class A{...}. 接口由interface修饰,定义方式如public interface B{...}. 抽象 ...

  8. Unity3D学习笔记4——创建Mesh高级接口

    目录 1. 概述 2. 详论 3. 其他 4. 参考 1. 概述 在文章Unity3D学习笔记2--绘制一个带纹理的面中使用代码的方式创建了一个Mesh,不过这套接口在Unity中被称为简单接口.与其 ...

  9. python3.8.0 Django 开发后端接口api 部署到 Linux Centos7上

    经历了两天的时候终于把本地使用python3 django开发的接口API部署到服务器上了,还是记录一下,以免之后忘记,哈哈 注意一点,就是,centos7是基于python2的,我这边默认的是pyt ...

随机推荐

  1. 【疑】接入交换机lacp port-channel连接核心突然中断

    现状: 职场网络架构为接入交换机2个端口通过lacp协议的active模式组成port-channel上联到核心. 具体配置如下 接入: 核心: 故障现象: zabbix监控到核心交换机对应该接入交换 ...

  2. 设计模式(一)——Java单例模式(代码+源码分析)

    1)单例模式保证了 系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能 2)当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不 ...

  3. 掌握数位dp

    最近遇到了数位dp题目,于是就屁颠屁颠的跑过来学习数位dp了~ "在信息学竞赛中,有这样一类问题:求给定区间中,满足给定条件的某个D 进制数或此类数的数量.所求的限定条件往往与数位有关,例如 ...

  4. AtCoder Beginner Contest 188 C - ABC Tournament (模拟)

    题意:有\(2^n\)个人站成一排比赛,刚开始每个人都和自己右边的人进行比赛,赢得人晋级下一轮(下标的小的在前面),不断重复这个过程,问最后拿到第二名的人的编号. 题解:根据题意,可以用vector直 ...

  5. UVA442 矩阵链乘 Matrix Chain Multiplication

    题意: 这道题也是在不改变原序列每个元素位置的前提下,看每个元素与他身边的两个元素那个先结合能得到最大的能量 题解: 很明显这是一道区间dp的题目,这道题要断环成链,这道题需要考虑在这个区间上某个元素 ...

  6. 2017, X Samara Regional Intercollegiate Programming Contest M. Last Man Standing (贪心,双指针)

    题意:有\(n\)个吃鸡玩家,在某个时间段给你他们每个人的杀敌数,判断数据是否合法,并输出每个人对应的杀敌情况. 题解:刚开始写的是直接暴力枚举,向后去找并且标记,然后存到vector最后输出,结果一 ...

  7. jackson学习之十(终篇):springboot整合(配置类)

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  8. 自己动手实现springboot运行时执行java源码(运行时编译、加载、注册bean、调用)

    看来断点.单步调试还不够硬核,根本没多少人看,这次再来个硬核的.依然是由于apaas平台越来越流行了,如果apaas平台选择了java语言作为平台内的业务代码,那么不仅仅面临着IDE外的断点.单步调试 ...

  9. 334A Candy Bags

    A. Candy Bags time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  10. HDU - 5115 Dire Wolf (非原创)

    Dire wolves, also known as Dark wolves, are extraordinarily large and powerful wolves. Many, if not ...