Book接口
Book系列连表接口

from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet from app01.models import Book # from app01.ser import BookSerializers from rest_framework.decorators import action from rest_framework.response import Response from rest_framework.authentication import SessionAuthentication, BasicAuthentication # class TestView(APIView): # def get(self,request): # 1/0 # return Response({'msg':'个人中心'}) # # class BookViewSet(ModelViewSet): # authentication_classes = [BasicAuthentication,] # queryset = Book.objects.all() # serializer_class = BookSerializers # @action(methods=['get'], detail=False) # def login(self, request): # Book.objects.update_or_create() # return Response({'msg':'登陆成功'}) # @action(methods=['put'], detail=True) # def get_new_5(self, request,pk): # return Response({'msg':'获取5条数据成功'}) from rest_framework.permissions import AllowAny,IsAuthenticated,IsAdminUser,IsAuthenticatedOrReadOnly from app01.response import APIResponse from app01 import models from app01 import ser as serializers class PublishAPIView(APIView): def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: publish_obj = models.Publish.objects.filter(pk=pk).first() if not publish_obj: return APIResponse(1, 'pk error', http_status=400) publish_data = serializers.PublishModelSerializer(publish_obj).data return APIResponse(results=publish_data) publish_query = models.Publish.objects.all() return APIResponse(0, 'ok', data=serializers.PublishModelSerializer(publish_query, many=True).data) class BookAPIView(APIView): # 单查、群查 def get(self, request, *args, **kwargs): pk = kwargs.get('pk') if pk: book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first() if not book_obj: return APIResponse(1, 'pk error', http_status=400) book_data = serializers.BookModelSerializer(book_obj).data print(book_data) return APIResponse(data=book_data) book_query = models.Book.objects.filter(is_delete=False).all() return APIResponse(0, 'ok', data=serializers.BookModelSerializer(book_query, many=True).data) # 单删、群删 def delete(self, request, *args, **kwargs): """ 单删:前台数据为pk,接口为 /books/(pk)/ 群删:前台数据为pks,接口为 /books/ """ pk = kwargs.get('pk') # 将单删群删逻辑整合 if pk: # /books/(pk)/的接口就不考虑群删,就固定为单删 pks = [pk] else: pks = request.data.get('pks') # 前台数据有误(主要是群删没有提供pks) if not pks: return APIResponse(1, 'delete error', http_status=400) # 只要有操作受影响行,就是删除成功,反之失败 rows = models.Book.objects.filter(is_delete=False, pk__in=pks).update(is_delete=True) if rows: return APIResponse(0, 'delete ok') return APIResponse(1, 'delete failed') # 单增、群增 def post(self, request, *args, **kwargs): """ 单增:前台提交字典,接口 /books/ 群增:前台提交列表套字典,接口 /books/ """ request_data = request.data if isinstance(request_data, dict): # 单增 book_ser = serializers.BookModelSerializer(data=request_data) if book_ser.is_valid(): book_obj = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj).data) return APIResponse(1, msg=book_ser.errors) elif isinstance(request_data, list) and len(request_data) != 0 : # 群增 book_ser = serializers.BookModelSerializer(data=request_data, many=True) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj_list, many=True).data) else: return APIResponse(1, 'data error', http_status=400) # 单整体改、群整体改 defput(self, request, *args, **kwargs): """ 单整体改:前台提交字典,接口 /books/(pk)/ 群整体改:前台提交列表套字典,接口 /books/,注每一个字典都可以通过pk """ pk = kwargs.get('pk') request_data = request.data if pk: # 单改 try: book_obj = models.Book.objects.get(pk=pk) except: return APIResponse(1, 'pk error') # 修改和新增,都需要通过数据,数据依旧给data,修改与新增不同点,instance要被赋值为被修改对象 book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data) book_ser.is_valid(raise_exception=True) book_obj = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj).data) else: # 群改 ifnot isinstance(request_data, list) or len(request_data) == 0: return APIResponse(1, 'data error', http_status=400) # [{pk:1,...}, {pk:3,...}, {pk:100,...}] => [obj1, obj3, obj100] + [{...}, {...}, {...}] # 要考虑pk对应的对象是否被删,以及pk没有对应的对象 # 假设pk3被删,pk100没有 => [obj1] + [{...}] # 注:一定不要在循环体中对循环对象进行增删(影响对象长度)的操作 obj_list = [] data_list = [] for dic in request_data: # request_data可能是list,单内部不一定是dict try: pk = dic.pop('pk') try: obj = models.Book.objects.get(pk=pk, is_delete=False) obj_list.append(obj) data_list.append(dic) except: pass except: return APIResponse(1, 'data error', http_status=400) book_ser = serializers.BookModelSerializer(instance=obj_list, data=data_list, many=True) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj_list, many=True).data) # 单局部改、群局部改 defpatch(self, request, *args, **kwargs): """ 单整体改:前台提交字典,接口 /books/(pk)/ 群整体改:前台提交列表套字典,接口 /books/,注每一个字典都可以通过pk """ pk = kwargs.get('pk') request_data = request.data if pk: try: book_obj = models.Book.objects.get(pk=pk) except: return APIResponse(1, 'pk error') # 局部修改就是在整体修改基础上设置partial=True,将所有参与反序列化字段设置为required=False book_ser = serializers.BookModelSerializer(instance=book_obj, data=request_data, partial=True) book_ser.is_valid(raise_exception=True) book_obj = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj).data) else: # 群改 ifnot isinstance(request_data, list) or len(request_data) == 0: return APIResponse(1, 'data error', http_status=400) # [{pk:1,...}, {pk:3,...}, {pk:100,...}] => [obj1, obj3, obj100] + [{...}, {...}, {...}] # 要考虑pk对应的对象是否被删,以及pk没有对应的对象 # 假设pk3被删,pk100没有 => [obj1] + [{...}] # 注:一定不要在循环体中对循环对象进行增删(影响对象长度)的操作 obj_list = [] data_list = [] for dic in request_data: # request_data可能是list,单内部不一定是dict try: pk = dic.pop('pk') try: obj = models.Book.objects.get(pk=pk, is_delete=False) obj_list.append(obj) data_list.append(dic) except: pass except: return APIResponse(1, 'data error', http_status=400) book_ser = serializers.BookModelSerializer(instance=obj_list, data=data_list, many=True, partial=True) book_ser.is_valid(raise_exception=True) book_obj_list = book_ser.save() return APIResponse(data=serializers.BookModelSerializer(book_obj_list, many=True).data) classAuthorAPIView(APIView): defget(self,request,*args,**kwargs): authors=models.Author.objects.all() author_ser=serializers.AuthorModelSerializer(authors,many=True) return APIResponse(data=author_ser.data) defput(self,reuqest,*args,**kwargs): pass defpost(self,request,*args,**kwargs): author_ser=serializers.AuthorModelSerializer(data=request.data) author_ser.is_valid(raise_exception=True) author_ser.save() return APIResponse() defdelete(self,request,*args,**kwargs): pass

from rest_framework import serializers from app01 import models class BookListSerializer(serializers.ListSerializer): # 1、create方法父级ListSerializer已经提供了 # def create(self, validated_data): # # 通过self.child来访问绑定的ModelSerializer # print(self.child) # raise Exception('我不提供') # 2、父级ListSerializer没有通过update方法的实现体,需要自己重写 def update(self, instance, validated_data): # print(instance) # print(validated_data) return [ self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data) ] class BookModelSerializer(serializers.ModelSerializer): # 通过BookModelSerializer.Meta.list_serializer_class来访问绑定的ListSerializer class Meta: # 关联ListSerializer完成群增群改 list_serializer_class = BookListSerializer model = models.Book # fields = ('name', 'price', 'publish', 'authors') # fields = ('name', 'price', 'publish_name', 'author_list') # 了解 # fields = '__all__' # exclude = ('id', ) # depth = 1 # 序列化与反序列化整合 fields = ('name', 'price', 'publish_name', 'author_list', 'publish', 'authors') extra_kwargs = { 'publish': { 'write_only': True }, 'authors': { 'write_only': True } } # 前提:如果只有查需求的接口,自定义深度还可以用子序列化方式完成 class PublishModelSerializer(serializers.ModelSerializer): # 子序列化都是提供给外键(正向方向)完成深度查询的,外键数据是唯一:many=False;不唯一:many=True # 注:只能参与序列化,且反序列化不能写(反序列化外键字段会抛异常) books = BookModelSerializer(many=True) class Meta: model = models.Publish fields = ('name', 'address', 'books') class AuthorModelSerializer(serializers.ModelSerializer): class Meta: model=models.Author fields=('name','sex','mobile','mobile_in') extra_kwargs={ 'mobile':{ 'read_only': True }, } mobile_in=serializers.CharField(write_only=True) # def validate_mobile_in(self, data): # print(data) # return data def create(self, validated_data): print(validated_data) mobile=validated_data.pop('mobile_in') author=models.Author.objects.create(**validated_data) authordetail=models.AuthorDetail.objects.create(mobile=mobile,author=author) return author

from django.db import models # 一、基表 # Model类的内部配置Meta类要设置abstract=True,这样的Model类就是用来作为基表 # 多表:Book,Publish,Author,AuthorDetail class BaseModel(models.Model): is_delete = models.BooleanField(default=False) create_time = models.DateTimeField(auto_now_add=True) class Meta: # 基表必须设置abstract,基表就是给普通Model类继承使用的,设置了abstract就不会完成数据库迁移完成建表 abstract = True class Book(BaseModel): name = models.CharField(max_length=16) price = models.DecimalField(max_digits=5, decimal_places=2) publish = models.ForeignKey(to='Publish', related_name='books', db_constraint=False, on_delete=models.DO_NOTHING) # 重点:多对多外键实际在关系表中,ORM默认关系表中两个外键都是级联 # ManyToManyField字段不提供设置on_delete,如果想设置关系表级联,只能手动定义关系表 authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False) # 自定义连表深度,不需要反序列化,因为自定义插拔属性不参与反序列化 @property def publish_name(self): return self.publish.name @property def author_list(self): temp_author_list = [] for author in self.authors.all(): temp_author_list.append({ 'name': author.name, 'sex': author.get_sex_display(), 'mobile': author.detail.mobile }) return temp_author_list class Publish(BaseModel): name = models.CharField(max_length=16) address = models.CharField(max_length=64) class Author(BaseModel): name = models.CharField(max_length=16) sex = models.IntegerField(choices=[(0, '男'),(1, '女')], default=0) class AuthorDetail(BaseModel): mobile = models.CharField(max_length=11) # 有作者可以没有详情,删除作者,详情一定会被级联删除 # 外键字段为正向查询字段,related_name是反向查询字段 author = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE) # 二、表断关联 # 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段) # 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作) # 3、断关联一定要通过逻辑保证表之间数据的安全 # 4、断关联 # 5、级联关系 # 作者没了,详情也没:on_delete=models.CASCADE # 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING # 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL # 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT # 三、ORM外键设计 # 1、一对多:外键放在多的一方 # 2、多对多:外键放在常用的一方 # 3、一对一:外键放在不常用的一方 # 4、外键字段为正向查询字段,related_name是反向查询字段 # from django.contrib.auth.models import AbstractUser, User # class MyUser(AbstractUser): # pass

LANGUAGE_CODE = 'zh-hans' TIME_ZONE = 'Asia/shanghai' USE_I18N = True USE_L10N = True USE_TZ = False

path(r'publishes/', views.PublishAPIView.as_view()), re_path(r'^publishes/(?P<pk>\d+)/$', views.PublishAPIView.as_view()), path(r'books/', views.BookAPIView.as_view()), re_path(r'^books/(?P<pk>\d+)/$', views.BookAPIView.as_view()),
RBAC-基于角色的访问控制
一 什么是RBAC
RBAC 是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
应用: # RBAC - Role-Based Access Control # Django的 Auth组件 采用的认证规则就是RBAC # 1)像专门做人员权限管理的系统(CRM系统)都是公司内部使用,所以数据量都在10w一下,一般效率要求也不是很高 # 2)用户量极大的常规项目,会分两种用户:前台用户(三大认证) 和 后台用户(BRAC来管理) # 结论:没有特殊要求的Django项目可以直接采用Auth组件的权限六表,不需要自定义六个表,也不需要断开表关系,单可能需要自定义User表 前后台权限控制: # 1)后台用户对各表操作,是后台项目完成的,我们可以直接借助admin后台项目(Django自带的) # 2)后期也可以用xadmin框架来做后台用户权限管理 # 3)前台用户的权限管理如何处理 # 定义了一堆数据接口的视图类,不同的登录用户是否能访问这些视图类,能就代表有权限,不能就代表无权限 # 前台用户权限用drf框架的 三大认证
二 Django的内置RBAC(六表)
权限三表
权限六表
三 实操

from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile = models.CharField(max_length=11, unique=True) def __str__(self): return self.username class Book(models.Model): name = models.CharField(max_length=64) def __str__(self): return self.name class Car(models.Model): name = models.CharField(max_length=64) def __str__(self): return self.name

from . import models from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin # 自定义User表后,admin界面管理User类 class UserAdmin(DjangoUserAdmin): # 添加用户课操作字段 add_fieldsets = ( (None, { 'classes': ('wide',), 'fields': ('username', 'password1', 'password2', 'is_staff', 'mobile', 'groups', 'user_permissions'), }), ) # 展示用户呈现的字段 list_display = ('username', 'mobile', 'is_staff', 'is_active', 'is_superuser') admin.site.register(models.User, UserAdmin) admin.site.register(models.Book) admin.site.register(models.Car)
这样就可以登陆到admin后台进行操作了
drfdemo

from django.contrib import admin from django.urls import path from app01 import views from rest_framework.routers import DefaultRouter router = DefaultRouter() # 可以处理视图的路由器 router.register('books', views.BooksViewSet) # 向路由器中注册视图集 # 将路由器中的所以路由信息追到到django的路由列表中 from django.views.decorators.csrf import csrf_exempt urlpatterns = [ path('admin/', admin.site.urls), # path('tset/', csrf_exempt(views.test)), path('books1/', views.Books.as_view()), #在这个地方应该写个函数内存地址 path('booksapiview/', views.BooksAPIView.as_view()), #在这个地方应该写个函数内存地址 ] #这是什么意思?两个列表相加 # router.urls 列表 urlpatterns += router.urls

from django.db import models # Create your models here. class Book(models.Model): nid=models.AutoField(primary_key=True) name=models.CharField(max_length=32) price=models.DecimalField(max_digits=5,decimal_places=2) author=models.CharField(max_length=32)

from rest_framework.serializers import ModelSerializer from app01.models import Book class BookModelSerializer(ModelSerializer): class Meta: model = Book fields = "__all__"

from django.shortcuts import render,HttpResponse # Create your views here. from rest_framework.viewsets import ModelViewSet from .models import Book from .ser import BookModelSerializer from django.views import View from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request class BooksViewSet(ModelViewSet): queryset = Book.objects.all() serializer_class = BookModelSerializer class Books(View): #如果有个需求,只能接受get请求 http_method_names = ['get',] def get(self,request): print(self.request) return HttpResponse('ok') class BooksAPIView(APIView): def get(self,request): # request 已经不是原生django的request了,是drf自己定义的request对象 # print(request._request) # print(request.data) print(request.method) print(request.query_params) #get请求,地址中的参数 # 原来在 print(request.GET) return HttpResponse('ok') def post(self,request): print(request.data) # urlencoded方式有数据,json格式也有,formdata也有数据 print(type(request.POST)) # 原生的POST print(request._request.POST) from django.http.request import QueryDict return HttpResponse('ok')
drf_serializer

class MyResponse(): def __init__(self): self.status=100 self.msg='成功' @property def get_dict(self): return self.__dict__ if __name__ == '__main__': res=MyResponse() res.status=101 res.msg='查询失败' # res.data={'name':'lqz'} print(res.get_dict)

# from rest_framework.serializers import Serializer # 就是一个类 from rest_framework import serializers from rest_framework.exceptions import ValidationError # 需要继承 Serializer from app01.models import Book def check_author(data): if data.startswith('sb'): raise ValidationError('作者名字不能以sb开头') else: return data class BookSerializer(serializers.Serializer): id=serializers.CharField(read_only=True) name=serializers.CharField(max_length=16,min_length=4) # price=serializers.DecimalField() price=serializers.CharField(write_only=True,required=True) author=serializers.CharField(validators=[check_author]) # validators=[] 列表中写函数内存地址 publish=serializers.CharField() def validate_price(self, data): # validate_字段名 接收一个参数 #如果价格小于10,就校验不通过 # print(type(data)) # print(data) if float(data)>10: return data else: #校验失败,抛异常 raise ValidationError('价格太低') def validate(self, validate_data): # 全局钩子 print(validate_data) author=validate_data.get('author') publish=validate_data.get('publish') if author == publish: raise ValidationError('作者名字跟出版社一样') else: return validate_data def update(self, instance, validated_data): #instance是book这个对象 #validated_data是校验后的数据 instance.name=validated_data.get('name') instance.price=validated_data.get('price') instance.author=validated_data.get('author') instance.publish=validated_data.get('publish') instance.save() #book.save() django 的orm提供的 return instance def create(self, validated_data): instance=Book.objects.create(**validated_data) return instance # Book.objects.create(name=validated_data.get('name')) class BookModelSerializer(serializers.ModelSerializer): class Meta: model=Book # 对应上models.py中的模型 fields='__all__' # fields=('name','price','id','author') # 只序列化指定的字段 # exclude=('name',) #跟fields不能都写,写谁,就表示排除谁 # read_only_fields=('price',) # write_only_fields=('id',) #弃用了,使用extra_kwargs extra_kwargs = { # 类似于这种形式name=serializers.CharField(max_length=16,min_length=4) 'price': {'write_only': True}, } from rest_framework import serializers class BookSerializer(serializers.Serializer): # book.publish # book.price # book.xxx--->book.title # book.authors.all xxx=serializers.CharField(source='title') price=serializers.CharField() pub_date=serializers.CharField(source='test') publish=serializers.CharField(source='publish.email') # book.publish.email 相当于 # authors=serializers.CharField() authors=serializers.SerializerMethodField() #它需要有个配套方法,方法名叫get_字段名,返回值就是要显示的东西 def get_authors(self,instance): # book对象 authors=instance.authors.all() # 取出所有作者 ll=[] for author in authors: ll.append({'name':author.name,'age':author.age}) return ll

from django.shortcuts import render # Create your views here. from django.http import JsonResponse from rest_framework.views import APIView from app01.models import Book from app01.ser import BookSerializer from app01.ser import BookModelSerializer from rest_framework.response import Response #drf 提供的响应对象 # 导入自己写的response类 from app01.utils import MyResponse class BookView(APIView): def get(self,request,pk): book=Book.objects.filter(id=pk).first() #用一个类,毫无疑问,一定要实例化 #要序列化谁,就把谁传过来 book_ser=BookSerializer(book) # 调用类的__init__ # book_ser.data 序列化对象.data就是序列化后的字典 return Response(book_ser.data) # return JsonResponse(book_ser.data) def put(self,request,pk): response_msg={'status':100,'msg':'成功'} # 找到这个对象 book = Book.objects.filter(id=pk).first() # 得到一个序列化类的对象 # boo_ser=BookSerializer(book,request.data) boo_ser=BookSerializer(instance=book,data=request.data) # 要数据验证(回想form表单的验证) if boo_ser.is_valid(): # 返回True表示验证通过 boo_ser.save() # 报错 response_msg['data']=boo_ser.data else: response_msg['status']=101 response_msg['msg']='数据校验失败' response_msg['data']=boo_ser.errors return Response(response_msg) def delete(self,request,pk): response=MyResponse() ret=Book.objects.filter(pk=pk).delete() return Response(response.get_dict) class BooksView(APIView): # def get(self,request): # response_msg = {'status': 100, 'msg': '成功'} # books=Book.objects.all() # book_ser=BookSerializer(books,many=True) #序列化多条,如果序列化一条,不需要写 # response_msg['data']=book_ser.data # return Response(response_msg) def get(self,request): response=MyResponse() books=Book.objects.all() book_ser=BookSerializer(books,many=True) #序列化多条,如果序列化一条,不需要写 response.data=book_ser.data return Response(response.get_dict) # 新增 def post(self,request): response_msg = {'status': 100, 'msg': '成功'} #修改才有instance,新增没有instance,只有data book_ser = BookSerializer(data=request.data) # book_ser = BookSerializer(request.data) # 这个按位置传request.data会给instance,就报错了 # 校验字段 if book_ser.is_valid(): book_ser.save() response_msg['data']=book_ser.data else: response_msg['status']=102 response_msg['msg']='数据校验失败' response_msg['data']=book_ser.errors return Response(response_msg) class BooksView2(APIView): def get(self,request): response=MyResponse() books=Book.objects.all() book=Book.objects.all().first() book_ser=BookModelSerializer(books,many=True) book_one_ser=BookModelSerializer(book) print(type(book_ser)) print(type(book_one_ser)) response.data=book_ser.data return Response(response.get_dict) from rest_framework.views import APIView from app02.models import Book from app02.ser import BookSerializer from rest_framework.response import Response #drf 提供的响应对象 class APP02BookView(APIView): def get(self,request,pk): book=Book.objects.filter(id=pk).first() book_ser=BookSerializer(book) return Response(book_ser.data)

from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.IntegerField() pub_date=models.DateField() publish=models.ForeignKey("Publish",on_delete=models.CASCADE,null=True) authors=models.ManyToManyField("Author") def __str__(self): return self.title def test(self): return 'lqz is big' class Publish(models.Model): name=models.CharField(max_length=32) email=models.EmailField() # def __str__(self): # return self.name+'ccccc' class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() def __str__(self): return self.name
drf_views

from django.contrib import admin from django.urls import path,re_path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('test/', views.TestView.as_view()), path('test2/', views.TestView2.as_view()), path('books/', views.BookView.as_view()), re_path('books/(?P<pk>\d+)', views.BookDetailView.as_view()), # 使用GenericAPIView重写的 path('books2/', views.Book2View.as_view()), re_path('books2/(?P<pk>\d+)', views.Book2DetailView.as_view()), # 使用GenericAPIView+5 个视图扩展类 重写的 path('books3/', views.Book3View.as_view()), re_path('books3/(?P<pk>\d+)', views.Book3DetailView.as_view()), # path('books4/', views.Book4View.as_view()), re_path('books4/(?P<pk>\d+)', views.Book4DetailView.as_view()), # 使用ModelViewSet编写5个接口 path('books5/', views.Book5View.as_view(actions={'get':'list','post':'create'})), #当路径匹配,又是get请求,会执行Book5View的list方法 re_path('books5/(?P<pk>\d+)', views.Book5View.as_view(actions={'get':'retrieve','put':'update','delete':'destroy'})), #继承ViewSetMixin的视图类,路由可以改写成这样 path('books6/', views.Book6View.as_view(actions={'get': 'get_all_book'})), ]

#这个变量REST_FRAMEWORK,里面都是drf的配置信息 REST_FRAMEWORK = { 'DEFAULT_RENDERER_CLASSES': ( # 默认响应渲染类 'rest_framework.renderers.JSONRenderer', # json渲染器 'rest_framework.renderers.BrowsableAPIRenderer', # 浏览API渲染器 ), }

from django.db import models # Create your models here. class Book(models.Model): name=models.CharField(max_length=32) price=models.DecimalField(max_digits=5,decimal_places=2) publish=models.CharField(max_length=32) class Publish(models.Model): name=models.CharField(max_length=32) email=models.CharField(max_length=32)

from rest_framework import serializers from app01.models import Book,Publish class BookSerializer(serializers.ModelSerializer): class Meta: model=Book fields='__all__' class PublishSerializer(serializers.ModelSerializer): class Meta: model=Publish fields='__all__'

from django.shortcuts import render # Create your views here. from rest_framework.request import Request from rest_framework.response import Response from rest_framework.views import APIView from rest_framework import status from rest_framework.renderers import JSONRenderer class TestView(APIView): renderer_classes=[JSONRenderer,] def get(self,request): print(request) return Response({'name':'lqz'},status=status.HTTP_200_OK,headers={'token':'xxx'}) class TestView2(APIView): def get(self,request): print(request) return Response({'name':'2222'},status=status.HTTP_200_OK,headers={'token':'xxx'}) ##################################视图相关 from rest_framework.generics import GenericAPIView from app01.models import Book from app01.ser import BookSerializer # 基于APIView写的 class BookView(APIView): def get(self,request): book_list=Book.objects.all() book_ser=BookSerializer(book_list,many=True) return Response(book_ser.data) def post(self,request): book_ser = BookSerializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校验失败'}) class BookDetailView(APIView): def get(self, request,pk): book = Book.objects.all().filter(pk=pk).first() book_ser = BookSerializer(book) return Response(book_ser.data) def put(self, request,pk): book = Book.objects.all().filter(pk=pk).first() book_ser = BookSerializer(instance=book,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status': 101, 'msg': '校验失败'}) def delete(self,request,pk): ret=Book.objects.filter(pk=pk).delete() return Response({'status': 100, 'msg': '删除成功'}) # 基于GenericAPIView写的 class Book2View(GenericAPIView): #queryset要传queryset对象,查询了所有的图书 # serializer_class使用哪个序列化类来序列化这堆数据 queryset=Book.objects # queryset=Book.objects.all() serializer_class = BookSerializer def get(self,request): book_list=self.get_queryset() book_ser=self.get_serializer(book_list,many=True) return Response(book_ser.data) def post(self,request): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校验失败'}) class Book2DetailView(GenericAPIView): queryset = Book.objects serializer_class = BookSerializer def get(self, request,pk): book = self.get_object() book_ser = self.get_serializer(book) return Response(book_ser.data) def put(self, request,pk): book = self.get_object() book_ser = self.get_serializer(instance=book,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status': 101, 'msg': '校验失败'}) def delete(self,request,pk): ret=self.get_object().delete() return Response({'status': 100, 'msg': '删除成功'}) ## 基于GenericAPIView写的Publish的5个接口 from app01.models import Publish from app01.ser import PublishSerializer class Publish2View(GenericAPIView): #queryset要传queryset对象,查询了所有的图书 # serializer_class使用哪个序列化类来序列化这堆数据 queryset=Publish.objects # queryset=Book.objects.all() serializer_class = PublishSerializer def get(self,request): book_list=self.get_queryset() book_ser=self.get_serializer(book_list,many=True) return Response(book_ser.data) def post(self,request): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status':101,'msg':'校验失败'}) class Publish2DetailView(GenericAPIView): queryset = Publish.objects serializer_class = PublishSerializer def get(self, request,pk): book = self.get_object() book_ser = self.get_serializer(book) return Response(book_ser.data) def put(self, request,pk): book = self.get_object() book_ser = self.get_serializer(instance=book,data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) else: return Response({'status': 101, 'msg': '校验失败'}) def delete(self,request,pk): ret=self.get_object().delete() return Response({'status': 100, 'msg': '删除成功'}) # CURD:create update,delet,retrieve # 5 个视图扩展类 from rest_framework.mixins import ListModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin class Book3View(GenericAPIView,ListModelMixin,CreateModelMixin): queryset=Book.objects serializer_class = BookSerializer def get(self,request): return self.list(request) def post(self,request): return self.create(request) class Book3DetailView(GenericAPIView,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin): queryset = Book.objects serializer_class = BookSerializer def get(self, request,pk): return self.retrieve(request,pk) def put(self, request,pk): return self.update(request,pk) def delete(self,request,pk): return self.destroy(request,pk) #GenericAPIView的视图子类 9个 from rest_framework.generics import CreateAPIView,ListAPIView,UpdateAPIView,RetrieveAPIView,DestroyAPIView,ListCreateAPIView,RetrieveUpdateDestroyAPIView,RetrieveDestroyAPIView,RetrieveUpdateAPIView # class Book4View(ListAPIView,CreateAPIView): #获取所有,新增一个 class Book4View(ListCreateAPIView): #获取所有,新增一个 queryset = Book.objects serializer_class = BookSerializer # class Book4DetailView(UpdateAPIView,RetrieveAPIView,DestroyAPIView): class Book4DetailView(RetrieveUpdateDestroyAPIView): queryset = Book.objects serializer_class = BookSerializer # 使用ModelViewSet编写5个接口 from rest_framework.views import APIView from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet class Book5View(ModelViewSet): #5个接口都有,但是路由有点问题 queryset = Book.objects serializer_class = BookSerializer class Book5View(ReadOnlyModelViewSet): #2个接口,获取一条,和获取所有两个 queryset = Book.objects serializer_class = BookSerializer from rest_framework.viewsets import ViewSetMixin class Book6View(ViewSetMixin,APIView): #一定要放在APIVIew前 def get_all_book(self,request): print("xxxx") book_list = Book.objects.all() book_ser = BookSerializer(book_list, many=True) return Response(book_ser.data)
drf_router_auth

REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES":["app01.app_auth.MyAuthentication",] }

from django.contrib import admin from django.urls import path,re_path from app01 import views # 第一步:导入routers模块 from rest_framework import routers # 第二步:有两个类,实例化得到对象 # routers.DefaultRouter 生成的路由更多 # routers.SimpleRouter router=routers.SimpleRouter() # 第三步:注册 # router.register('前缀','继承自ModelViewSet视图类','别名') router.register('books',views.BookViewSet) # 不要加斜杠了 # 第四步 # router.urls # 自动生成的路由,加入到原路由中 # print(router.urls) # urlpatterns+=router.urls ''' [ <URLPattern '^books/$' [name='book-list']>, <URLPattern '^books/(?P<pk>[^/.]+)/$'[name='book-detail']> ] ''' urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.LoginView.as_view()), path('test/', views.TestView.as_view()), # path('books/', views.BookViewSet.as_view({'get':'list','post':'create'})), # re_path('books/(?P<pk>\d+)', views.BookViewSet.as_view({'get':'retrieve','put':'update','delete':'destroy'})), ] urlpatterns+=router.urls ''' SimpleRouter <URLPattern '^books/$' [name='book-list']>, <URLPattern '^books/(?P<pk>[^/.]+)/$'[name='book-detail']> DefaultRouter ^books/$ [name='book-list'] ^books/(?P<pk>[^/.]+)/$ [name='book-detail'] 这两条跟simple一样 ^$ [name='api-root'] 根,根路径会显示出所有可以访问的地址 ^\.(?P<format>[a-z0-9]+)/?$ [name='api-root'] ^books\.(?P<format>[a-z0-9]+)/?$ [name='book-list'] http://127.0.0.1:8000/books.json ^books/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='book-detail'] http://127.0.0.1:8000/books/1.json '''

from django.shortcuts import render # Create your views here. from rest_framework.viewsets import ModelViewSet from rest_framework.response import Response from rest_framework.decorators import action # 装饰器 from app01.models import Book from app01.ser import BookSerializer from rest_framework.request import Request from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.app_auth import MyAuthentication from rest_framework.views import APIView from rest_framework.response import Response import uuid from app01 import models class BookViewSet(ModelViewSet): # authentication_classes=[MyAuthentication] queryset =Book.objects.all() serializer_class = BookSerializer # methods第一个参数,传一个列表,列表中放请求方式, # ^books/get_1/$ [name='book-get-1'] 当向这个地址发送get请求,会执行下面的函数 # detail:布尔类型 如果是True #^books/(?P<pk>[^/.]+)/get_1/$ [name='book-get-1'] @action(methods=['GET','POST'],detail=True) def get_1(self,request,pk): print(request.user.username) print(pk) book=self.get_queryset()[:2] # 从0开始截取一条 ser=self.get_serializer(book,many=True) return Response(ser.data) from rest_framework.authentication import BasicAuthentication class TestView(APIView): def get(self,request): print(request.user.username) return Response({'msg':'我是测试'}) class LoginView(APIView): authentication_classes = [] def post(self,request): username=request.data.get('username') password=request.data.get('password') user=models.User.objects.filter(username=username,password=password).first() if user: # 登陆成功,生成一个随机字符串 token=uuid.uuid4() # 存到UserToken表中 # models.UserToken.objects.create(token=token,user=user)# 用它每次登陆都会记录一条,不好,如有有记录 # update_or_create有就更新,没有就新增 models.UserToken.objects.update_or_create(defaults={'token':token},user=user) return Response({'status':100,'msg':'登陆成功','token':token}) else: return Response({'status': 101, 'msg': '用户名或密码错误'})

from rest_framework import serializers from app01.models import Book class BookSerializer(serializers.ModelSerializer): class Meta: model=Book fields='__all__'

from django.db import models # Create your models here. class Book(models.Model): name=models.CharField(max_length=32) price=models.DecimalField(max_digits=5,decimal_places=2) publish=models.CharField(max_length=32) class User(models.Model): username=models.CharField(max_length=32) password=models.CharField(max_length=32) user_type=models.IntegerField(choices=((1,'超级用户'),(2,'普通用户'),(3,'二笔用户'))) class UserToken(models.Model): token=models.CharField(max_length=64) user=models.OneToOneField(to=User,on_delete=models.CASCADE) #一对一关联到User表

from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import UserToken class MyAuthentication(BaseAuthentication): def authenticate(self, request): # 认证逻辑,如果认证通过,返回两个值 #如果认证失败,抛出AuthenticationFailed异常 token=request.GET.get('token') if token: user_token=UserToken.objects.filter(token=token).first() # 认证通过 if user_token: return user_token.user,token else: raise AuthenticationFailed('认证失败') else: raise AuthenticationFailed('请求地址中需要携带token')
drf_others

from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.LoginView.as_view()), path('test/', views.TestView.as_view()), path('test2/', views.TestView2.as_view()), path('test3/', views.TestView3.as_view()), path('test4/', views.TestView4.as_view()), path('test5/', views.TestView5.as_view()), path('test6/', views.TestView6.as_view()), path('books/', views.BookView.as_view()), path('books2/', views.Book2View.as_view()), path('test7/', views.TestView7.as_view()), ]

REST_FRAMEWORK = { # "DEFAULT_AUTHENTICATION_CLASSES": ["app01.app_auth.MyAuthentication", ], # 'DEFAULT_PERMISSION_CLASSES': [ # 'app01.app_auth.UserPermission', # ], # 'DEFAULT_THROTTLE_CLASSES': ( # 'rest_framework.throttling.AnonRateThrottle', # ), 'DEFAULT_THROTTLE_CLASSES': ( 'rest_framework.throttling.AnonRateThrottle', 'rest_framework.throttling.UserRateThrottle' ), 'DEFAULT_THROTTLE_RATES': { 'user': '10/m', 'anon': '5/m', }, 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), 'EXCEPTION_HANDLER': 'app01.app_auth.my_exception_handler', }

from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import UserToken class MyAuthentication(BaseAuthentication): def authenticate(self, request): # 认证逻辑,如果认证通过,返回两个值 #如果认证失败,抛出AuthenticationFailed异常 token=request.GET.get('token') if token: user_token=UserToken.objects.filter(token=token).first() # 认证通过 if user_token: return user_token.user,token else: raise AuthenticationFailed('认证失败') else: raise AuthenticationFailed('请求地址中需要携带token') from rest_framework.permissions import BasePermission class UserPermission(BasePermission): def has_permission(self, request, view): # 不是超级用户,不能访问 # 由于认证已经过了,request内就有user对象了,当前登录用户 user=request.user # 当前登录用户 # 如果该字段用了choice,通过get_字段名_display()就能取出choice后面的中文 print(user.get_user_type_display()) if user.user_type==1: return True else: return False # 自定义异常处理的方法 from rest_framework.views import exception_handler from rest_framework.response import Response from rest_framework import status def my_exception_handler(exc, context): response=exception_handler(exc, context) # 两种情况,一个是None,drf没有处理 #response对象,django处理了,但是处理的不符合咱们的要求 # print(type(exc)) if not response: if isinstance(exc, ZeroDivisionError): return Response(data={'status': 777, 'msg': "除以0的错误" + str(exc)}, status=status.HTTP_400_BAD_REQUEST) return Response(data={'status':999,'msg':str(exc)},status=status.HTTP_400_BAD_REQUEST) else: # return response return Response(data={'status':888,'msg':response.data.get('detail')},status=status.HTTP_400_BAD_REQUEST) #自己封装Response对象 from rest_framework.response import Response # return APIResponse(100,'成功',data) class APIResponse(Response): def __init__(self,code=100,msg='成功',data=None,status=None,headers=None,**kwargs): dic = {'code': code, 'msg': msg} if data: dic = {'code': code, 'msg': msg,'data':data} dic.update(kwargs) super().__init__(data=dic, status=status,headers=headers)

from django.db import models # Create your models here. from django.db import models # Create your models here. class Book(models.Model): name=models.CharField(max_length=32) price=models.DecimalField(max_digits=5,decimal_places=2) publish=models.CharField(max_length=32) class User(models.Model): username=models.CharField(max_length=32) password=models.CharField(max_length=32) user_type=models.IntegerField(choices=((1,'超级用户'),(2,'普通用户'),(3,'二笔用户'))) class UserToken(models.Model): token=models.CharField(max_length=64) user=models.OneToOneField(to=User,on_delete=models.CASCADE) #一对一关联到User表

from rest_framework import serializers from app01.models import Book class BookSerializer(serializers.ModelSerializer): class Meta: model=Book fields='__all__'
drf_books_ser

from rest_framework import serializers from api import models #写一个类,继ListSerializer,重写update class BookListSerializer(serializers.ListSerializer): # def create(self, validated_data): # print(validated_data) # return super().create(validated_data) def update(self, instance, validated_data): print(instance) print(validated_data) # 保存数据 # self.child:是BookModelSerializer对象 # ll=[] # for i,si_data in enumerate(validated_data): # ret=self.child.update(instance[i],si_data) # ll.append(ret) # return ll return [ # self.child.update(对象,字典) for attrs in validated_data self.child.update(instance[i],attrs) for i,attrs in enumerate(validated_data) ] #如果序列化的是数据库的表,尽量用ModelSerializer class BookModelSerializer(serializers.ModelSerializer): # 一种方案(只序列化可以,反序列化有问题) # publish=serializers.CharField(source='publish.name') # 第二种方案,models中写方法 class Meta: list_serializer_class=BookListSerializer model=models.Book # fields='__all__' # 用的少 # depth=0 sss=serializers.CharField(source='name') fields = ('id','name','price','authors','publish','publish_name','author_list','ssss') extra_kwargs={ 'publish':{'write_only':True}, 'publish_name':{'read_only':True}, 'authors':{'write_only':True}, 'author_list':{'read_only':True} }

from django.urls import path,re_path from api import views urlpatterns = [ path('books/', views.BookAPIView.as_view()), path('books2/', views.BookView.as_view()), #继承了ListApiView re_path('books/(?P<pk>\d+)', views.BookAPIView.as_view()), ]

from django.shortcuts import render # Create your views here. from rest_framework.response import Response from api import models from rest_framework.views import APIView from rest_framework.generics import GenericAPIView from api.ser import BookModelSerializer class BookAPIView(APIView): def get(self,request,*args,**kwargs): #查询单个和查询所有,合到一起 # 查所有 book_list=models.Book.objects.all().filter(is_delete=False) book_list_ser=BookModelSerializer(book_list,many=True) return Response(data=book_list_ser.data) #查一个 def post(self,request,*args,**kwargs): # 具备增单条,和增多条的功能 if isinstance(request.data,dict): book_ser=BookModelSerializer(data=request.data) book_ser.is_valid(raise_exception=True) book_ser.save() return Response(data=book_ser.data) elif isinstance(request.data,list): #现在book_ser是ListSerializer对象 from rest_framework.serializers import ListSerializer book_ser = BookModelSerializer(data=request.data,many=True) #增多条 print('--------',type(book_ser)) book_ser.is_valid(raise_exception=True) book_ser.save() # 新增---》ListSerializer--》create方法 # def create(self, validated_data): # self.child是BookModelSerializer对象 # print(type(self.child)) # return [ # self.child.create(attrs) for attrs in validated_data # ] return Response(data=book_ser.data) def put(self,request,*args,**kwargs): # 改一个,改多个 #改一个个 if kwargs.get('pk',None): book=models.Book.objects.filter(pk=kwargs.get('pk')).first() book_ser = BookModelSerializer(instance=book,data=request.data,partial=True) # 增多条 book_ser.is_valid(raise_exception=True) book_ser.save() return Response(data=book_ser.data) else: #改多个, # 前端传递数据格式[{id:1,name:xx,price:xx},{id:1,name:xx,price:xx}] # 处理传入的数据 对象列表[book1,book2] 修改的数据列表[{name:xx,price:xx},{name:xx,price:xx}] book_list=[] modify_data=[] for item in request.data: #{id:1,name:xx,price:xx} pk=item.pop('id') book=models.Book.objects.get(pk=pk) book_list.append(book) modify_data.append(item) # 第一种方案,for循环一个一个修改 #把这个实现 # for i,si_data in enumerate(modify_data): # book_ser = BookModelSerializer(instance=book_list[i], data=si_data) # book_ser.is_valid(raise_exception=True) # book_ser.save() # return Response(data='成功') # 第二种方案,重写ListSerializer的update方法 book_ser = BookModelSerializer(instance=book_list,data=modify_data,many=True) book_ser.is_valid(raise_exception=True) book_ser.save() #ListSerializer的update方法,自己写的update方法 return Response(book_ser.data) # request.data # # book_ser=BookModelSerializer(data=request.data) def delete(self,request,*args,**kwargs): #单个删除和批量删除 pk=kwargs.get('pk') pks=[] if pk: # 单条删除 pks.append(pk) #不管单条删除还是多条删除,都用多条删除 #多条删除 # {'pks':[1,2,3]} else: pks=request.data.get('pks') #把is_delete设置成true # ret返回受影响的行数 ret=models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True) if ret: return Response(data={'msg':'删除成功'}) else: return Response(data={'msg': '没有要删除的数据'}) # 查所有,才需要分页 from rest_framework.generics import ListAPIView # 内置三种分页方式 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination ''' PageNumberPagination page_size:每页显示的条数 ''' class MyPageNumberPagination(PageNumberPagination): #http://127.0.0.1:8000/api/books2/?aaa=1&size=6 page_size=3 #每页条数 page_query_param='aaa' #查询第几页的key page_size_query_param='size' # 每一页显示的条数 max_page_size=5 # 每页最大显示条数 # class MyLimitOffsetPagination(LimitOffsetPagination): # default_limit = 3 # 每页条数 # limit_query_param = 'limit' # 往后拿几条 # offset_query_param = 'offset' # 标杆 # max_limit = 5 # 每页最大几条 class MyCursorPagination(CursorPagination): cursor_query_param = 'cursor' # 每一页查询的key page_size = 2 #每页显示的条数 ordering = '-id' #排序字段 # class BookView(ListAPIView): # # queryset = models.Book.objects.all().filter(is_delete=False) # queryset = models.Book.objects.all() # serializer_class = BookModelSerializer # #配置分页 # pagination_class = MyCursorPagination # 如果使用APIView分页 from utils.throttling import MyThrottle class BookView(APIView): # throttle_classes = [MyThrottle,] def get(self,request,*args,**kwargs): book_list=models.Book.objects.all() # 实例化得到一个分页器对象 page_cursor=MyPageNumberPagination() book_list=page_cursor.paginate_queryset(book_list,request,view=self) next_url =page_cursor.get_next_link() pr_url=page_cursor.get_previous_link() # print(next_url) # print(pr_url) book_ser=BookModelSerializer(book_list,many=True) return Response(data=book_ser.data)

from rest_framework.throttling import ScopedRateThrottle,SimpleRateThrottle #继承SimpleRateThrottle class MyThrottle(SimpleRateThrottle): scope='luffy' def get_cache_key(self, request, view): print(request.META.get('REMOTE_ADDR')) return request.META.get('REMOTE_ADDR')

REST_FRAMEWORK={ 'DEFAULT_THROTTLE_CLASSES': ( 'utils.throttling.MyThrottle', ), 'DEFAULT_THROTTLE_RATES': { 'luffy': '3/m' # key要跟类中的scop对应 }, 'PAGE_SIZE': 2, }

from django.db import models from django.contrib.auth.models import AbstractUser class BaseModel(models.Model): is_delete=models.BooleanField(default=False) # auto_now_add=True 只要记录创建,不需要手动插入时间,自动把当前时间插入 create_time=models.DateTimeField(auto_now_add=True) # auto_now=True,只要更新,就会把当前时间插入 last_update_time=models.DateTimeField(auto_now=True) # import datetime # create_time=models.DateTimeField(default=datetime.datetime.now) class Meta: # 单个字段,有索引,有唯一 # 多个字段,有联合索引,联合唯一 abstract=True # 抽象表,不再数据库建立出表 class Book(BaseModel): id=models.AutoField(primary_key=True) # verbose_name admin中显示中文 name=models.CharField(max_length=32,verbose_name='书名',help_text='这里填书名') price=models.DecimalField(max_digits=5,decimal_places=2) # 一对多的关系一旦确立,关联字段写在多的一方 #to_field 默认不写,关联到Publish主键 #db_constraint=False 逻辑上的关联,实质上没有外键练习,增删不会受外键影响,但是orm查询不影响 publish=models.ForeignKey(to='Publish',on_delete=models.DO_NOTHING,db_constraint=False) # 多对多,跟作者,关联字段写在 查询次数多的一方 # 什么时候用自动,什么时候用手动?第三张表只有关联字段,用自动 第三张表有扩展字段,需要手动写 # 不能写on_delete authors=models.ManyToManyField(to='Author',db_constraint=False) class Meta: verbose_name_plural='书表' # admin中表名的显示 def __str__(self): return self.name @property def publish_name(self): return self.publish.name # def author_list(self): def author_list(self): author_list=self.authors.all() # ll=[] # for author in author_list: # ll.append({'name':author.name,'sex':author.get_sex_display()}) # return ll return [ {'name':author.name,'sex':author.get_sex_display()}for author in author_list] class Publish(BaseModel): name = models.CharField(max_length=32) addr=models.CharField(max_length=32) def __str__(self): return self.name class Author(BaseModel): name=models.CharField(max_length=32) sex=models.IntegerField(choices=((1,'男'),(2,'女'))) # 一对一关系,写在查询频率高的一方 #OneToOneField本质就是ForeignKey+unique,自己手写也可以 authordetail=models.OneToOneField(to='AuthorDetail',db_constraint=False,on_delete=models.CASCADE) class AuthorDetail(BaseModel): mobile=models.CharField(max_length=11) # 二、表断关联 # 1、表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段) # 2、断关联后不会影响数据库查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作) # 3、断关联一定要通过逻辑保证表之间数据的安全,不要出现脏数据,代码控制 # 4、断关联 # 5、级联关系 # 作者没了,详情也没:on_delete=models.CASCADE # 出版社没了,书还是那个出版社出版:on_delete=models.DO_NOTHING # 部门没了,员工没有部门(空不能):null=True, on_delete=models.SET_NULL # 部门没了,员工进入默认部门(默认值):default=0, on_delete=models.SET_DEFAULT

from django.contrib import admin # Register your models here. from api import models admin.site.register(models.Book) admin.site.register(models.Publish) admin.site.register(models.Author) admin.site.register(models.AuthorDetail)
drf_token

# 配置头像相关 MEDIA_URL='/media/' MEDIA_ROOT=os.path.join(BASE_DIR,'media') #一定不要忘了 AUTH_USER_MODEL='api.user' REST_FRAMEWORK={ 'DEFAULT_AUTHENTICATION_CLASSES':['rest_framework_jwt.authentication.JSONWebTokenAuthentication'] } JWT_AUTH={ 'JWT_AUTH_HEADER_PREFIX': '', }

from django.contrib import admin from django.urls import path from rest_framework_jwt.views import ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken,obtain_jwt_token # 基类:JSONWebTokenAPIView继承了APIView, # ObtainJSONWebToken,VerifyJSONWebToken,RefreshJSONWebToken都继承了JSONWebTokenAPIView ''' obtain_jwt_token = ObtainJSONWebToken.as_view() refresh_jwt_token = RefreshJSONWebToken.as_view() verify_jwt_token = VerifyJSONWebToken.as_view() ''' from api import views urlpatterns = [ path('admin/', admin.site.urls), # path('login/', ObtainJSONWebToken.as_view()), path('login/', obtain_jwt_token), path('books/', views.BookView.as_view()), ]

from rest_framework_jwt.authentication import BaseAuthentication,BaseJSONWebTokenAuthentication from rest_framework.exceptions import AuthenticationFailed from rest_framework_jwt.authentication import jwt_decode_handler from rest_framework_jwt.authentication import get_authorization_header,jwt_get_username_from_payload from rest_framework import exceptions class MyToken(BaseJSONWebTokenAuthentication): def authenticate(self, request): jwt_value=str(request.META.get('HTTP_AUTHORIZATION')) # 认证 try: payload = jwt_decode_handler(jwt_value) except Exception: raise exceptions.AuthenticationFailed("认证失败") user=self.authenticate_credentials(payload) return user,None

from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): phone=models.CharField(max_length=11) icon=models.ImageField(upload_to='icon') # ImageField依赖于pillow模块

from django.shortcuts import render from rest_framework.views import APIView from rest_framework.response import Response from rest_framework_jwt.authentication import JSONWebTokenAuthentication from api.auth import MyToken class BookView(APIView): authentication_classes = [MyToken,] def get(self,request): print(request.user.email) return Response('ok')
drf_...

# base64编码和解码 #md5固定长度,不可反解 #base63 变长,可反解 #编码(字符串,json格式字符串) import base64 import json dic={'name':'lqz','age':18,'sex':'男'} dic_str=json.dumps(dic) ret=base64.b64encode(dic_str.encode('utf-8')) print(ret) # 解码 # ret是带解码的串 ret2=base64.b64decode(ret) print(ret2)

from django.contrib import admin from django.urls import path,include,re_path from django.views.static import serve # django内置给你的一个视图函数 from django.conf import settings # 以后取配置文件,都用这个 # from drf_day12 import settings urlpatterns = [ path('admin/', admin.site.urls), path('api/',include('api.urls')), # 路由分发 path('app02/',include('app02.urls')), # 开放media文件 re_path('media/(?P<path>.*)', serve,{'document_root':settings.MEDIA_ROOT}), ]

STATIC_URL = '/static/' MEDIA_URL='/media/' MEDIA_ROOT=os.path.join(BASE_DIR,'media') #真正的文件夹路径 #指定使用的auth表是自己定义的 AUTH_USER_MODEL='api.user' #app名.表名 # jwt的配置 import datetime JWT_AUTH={ 'JWT_RESPONSE_PAYLOAD_HANDLER':'app02.utils.my_jwt_response_payload_handler', 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=7), # 过期时间,手动配置 } CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', #指定缓存使用的引擎 'LOCATION': 'D:\django_cache', #指定缓存的路径 'TIMEOUT':300, #缓存超时时间(默认为300秒,None表示永不过期) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) } } }

from django.db import models # Create your models here. from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile=models.CharField(max_length=32,unique=True) #唯一 icon=models.ImageField(upload_to='icon',default='icon/default.png') #需要配media文件夹,上传的文件就会放到media文件夹下的icon class Book(models.Model): name = models.CharField(max_length=64) def __str__(self): return self.name class Car(models.Model): name = models.CharField(max_length=64) def __str__(self): return self.name

from rest_framework import serializers from api import models from rest_framework.exceptions import ValidationError class UserModelSerializer(serializers.ModelSerializer): re_password=serializers.CharField(max_length=16,min_length=4,required=True,write_only=True) # 因为re_password在表中没有,需要在这定义 class Meta: model=models.User fields=['username','password','mobile','re_password','icon'] extra_kwargs={ 'username':{'max_length':16}, 'password':{'write_only':True} } # 局部钩子 def validate_mobile(self,data): if not len(data)==11: raise ValidationError('手机号不合法') return data # 全局钩子 def validate(self, attrs): if not attrs.get('password')==attrs.get('re_password'): raise ValidationError('两次密码不一致') attrs.pop('re_password')# 剔除该字段,因为数据库没有这个字段 return attrs def create(self, validated_data): # attrs.pop('re_password') 如果上面没有剔除,在这也可以 # models.User.objects.create(**validated_data) 这个密码不会加密 user=models.User.objects.create_user(**validated_data) return user class UserReadOnlyModelSerializer(serializers.ModelSerializer): class Meta: model=models.User fields=['username','icon'] class UserImageModelSerializer(serializers.ModelSerializer): class Meta: model=models.User fields=['icon']

from django.shortcuts import render # Create your views here. from rest_framework.viewsets import GenericViewSet #ViewSetMixin:重写了as_view,路由配置变样了, generics.GenericAPIView:只需要配俩东西 from rest_framework.mixins import CreateModelMixin,RetrieveModelMixin,UpdateModelMixin from api import ser from api import models class RegisterView(GenericViewSet,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin): queryset = models.User.objects.all() serializer_class =ser.UserModelSerializer # 假设get请求和post请求,用的序列化类不一样,如何处理? # 重写getget_serializer_class,返回啥,用的序列号类就是啥 # 注册,用的序列化类是UserModelSerializer,查询一个用的序列化类是UserReadOnlyModelSerializer def get_serializer_class(self): print(self.action) # create,retrieve if self.action=='create': return ser.UserModelSerializer elif self.action=='retrieve': return ser.UserReadOnlyModelSerializer elif self.action=='update': return ser.UserImageModelSerializer

from rest_framework import serializers from api import models import re from rest_framework.exceptions import ValidationError from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler class LoginModelSerializer(serializers.ModelSerializer): username=serializers.CharField() # 重新覆盖username字段,数据中它是unique,post,认为你保存数据,自己有校验没过 class Meta: model=models.User fields=['username','password'] def validate(self, attrs): print(self.context) # 在这写逻辑 username=attrs.get('username') # 用户名有三种方式 password=attrs.get('password') # 通过判断,username数据不同,查询字段不一样 # 正则匹配,如果是手机号 if re.match('^1[3-9][0-9]{9}$',username): user=models.User.objects.filter(mobile=username).first() elif re.match('^.+@.+$',username):# 邮箱 user=models.User.objects.filter(email=username).first() else: user=models.User.objects.filter(username=username).first() if user: # 存在用户 # 校验密码,因为是密文,要用check_password if user.check_password(password): # 签发token payload = jwt_payload_handler(user) # 把user传入,得到payload token = jwt_encode_handler(payload) # 把payload传入,得到token self.context['token']=token self.context['username']=user.username return attrs else: raise ValidationError('密码错误') else: raise ValidationError('用户不存在') ''' jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) # 把user传入,得到payload token = jwt_encode_handler(payload) # 把payload传入,得到token '''

from django.contrib import admin from django.urls import path,include,re_path from django.views.static import serve # django内置给你的一个视图函数 from django.conf import settings # 以后取配置文件,都用这个 # from drf_day12 import settings from rest_framework_jwt.views import obtain_jwt_token from app02 import views urlpatterns = [ path('login/', obtain_jwt_token), path('order/', views.OrderAPIView.as_view()), path('userinfo/', views.UserInfoAPIView.as_view()), path('goods/', views.GoodsInfoAPIView.as_view()), path('login2/', views.Login2View.as_view({'post':'login'})), # 缓存 path('test/', views.test_cache), path('test2/', views.test_cache2) ]

def my_jwt_response_payload_handler(token, user=None, request=None): # 返回什么,前端就能看到什么样子 return { 'token': token, 'msg':'登录成功', 'status':100, 'username':user.username } from rest_framework.authentication import BaseAuthentication # 基于它 from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication # 基于它 from rest_framework.exceptions import AuthenticationFailed # from rest_framework_jwt.authentication import jwt_decode_handler from rest_framework_jwt.utils import jwt_decode_handler # 跟上面是一个 import jwt from api import models # class MyJwtAuthentication(BaseAuthentication): # def authenticate(self, request): # jwt_value=request.META.get('HTTP_AUTHORIZATION') # if jwt_value: # try: # #jwt提供了通过三段token,取出payload的方法,并且有校验功能 # payload=jwt_decode_handler(jwt_value) # except jwt.ExpiredSignature: # raise AuthenticationFailed('签名过期') # except jwt.InvalidTokenError: # raise AuthenticationFailed('用户非法') # except Exception as e: # # 所有异常都会走到这 # raise AuthenticationFailed(str(e)) # # 因为payload就是用户信息的字典 # print(payload) # # return payload, jwt_value # # 需要得到user对象, # # 第一种,去数据库查 # # user=models.User.objects.get(pk=payload.get('user_id')) # # 第二种不查库 # user=models.User(id=payload.get('user_id'),username=payload.get('username')) # return user,jwt_value # # 没有值,直接抛异常 # raise AuthenticationFailed('您没有携带认证信息') class MyJwtAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): jwt_value=request.META.get('HTTP_AUTHORIZATION') if jwt_value: try: #jwt提供了通过三段token,取出payload的方法,并且有校验功能 payload=jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: raise AuthenticationFailed('签名过期') except jwt.InvalidTokenError: raise AuthenticationFailed('用户非法') except Exception as e: # 所有异常都会走到这 raise AuthenticationFailed(str(e)) user=self.authenticate_credentials(payload) return user,jwt_value # 没有值,直接抛异常 raise AuthenticationFailed('您没有携带认证信息')

from django.shortcuts import render # Create your views here. from rest_framework.views import APIView from rest_framework.response import Response # 使用jwt提供的认证类,局部使用 from rest_framework_jwt.authentication import JSONWebTokenAuthentication # 内置权限类 # 可以通过认证类:JSONWebTokenAuthentication和权限类IsAuthenticated,来控制用户登录以后才能访问某些接口 # 如果用户不登录就可以访问,只需要把权限类IsAuthenticated去掉就可以了 from rest_framework.permissions import IsAuthenticated class OrderAPIView(APIView): authentication_classes = [JSONWebTokenAuthentication,] # 权限控制 permission_classes = [IsAuthenticated,] def get(self,request,*args,**kwargs): return Response('这是订单信息') class UserInfoAPIView(APIView): authentication_classes = [JSONWebTokenAuthentication,] # 权限控制 # permission_classes = [IsAuthenticated,] def get(self,request,*args,**kwargs): return Response('UserInfoAPIView') # from rest_framework_jwt.utils import jwt_response_payload_handler from app02.utils import MyJwtAuthentication class GoodsInfoAPIView(APIView): authentication_classes = [MyJwtAuthentication,] def get(self,request,*args,**kwargs): print(request.user) return Response('商品信息') # 手动签发token,完成多方式登录 from rest_framework.views import APIView from rest_framework.viewsets import ViewSetMixin, ViewSet from app02 import ser # class Login2View(ViewSetMixin,APIView): class Login2View(ViewSet): # 跟上面完全一样 # 这是登录接口 # def post(self): # 不写post了,直接写login? # pass def login(self, request, *args, **kwargs): # 1 需要 有个序列化的类 login_ser = ser.LoginModelSerializer(data=request.data,context={'request':request}) # 2 生成序列化类对象 # 3 调用序列号对象的is_validad login_ser.is_valid(raise_exception=True) token=login_ser.context.get('token') # 4 return return Response({'status':100,'msg':'登录成功','token':token,'username':login_ser.context.get('username')}) # 逻辑在视图类中写 # def login(self, request, *args, **kwargs): # username=request.data.get('username') # 用户名有三种方式 # password=request.data.get('password') # import re # from api import models # from rest_framework_jwt.utils import jwt_encode_handler, jwt_payload_handler # # 通过判断,username数据不同,查询字段不一样 # # 正则匹配,如果是手机号 # if re.match('^1[3-9][0-9]{9}$',username): # user=models.User.objects.filter(mobile=username).first() # elif re.match('^.+@.+$',username):# 邮箱 # user=models.User.objects.filter(email=username).first() # else: # user=models.User.objects.filter(username=username).first() # if user: # 存在用户 # # 校验密码,因为是密文,要用check_password # if user.check_password(password): # # 签发token # payload = jwt_payload_handler(user) # 把user传入,得到payload # token = jwt_encode_handler(payload) # 把payload传入,得到token # return Response() # 单页面缓存 from django.views.decorators.cache import cache_page class Person: def __init__(self,name,age): self.name=name self.age=age from django.core.cache import cache # @cache_page(5) # 缓存5s钟 def test_cache(request): p=Person('lqz',18) cache.set('name',p) import time ctime=time.time() return render(request,'index.html',context={'ctime':ctime}) def test_cache2(request): p=cache.get('name') print(type(p)) print(p.name) import time ctime = time.time() return render(request, 'index.html', context={'ctime': ctime})
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构