多方式登录 book,publish,author表关系及抽象表的建立 book表的群(增删改查)
一:多方式登录
serializer.py文件中 from rest_framework import serializers from app01.models import UserInfo,MyUser import re from rest_framework.exceptions import ValidationError from rest_framework_jwt.views import obtain_jwt_token from rest_framework_jwt.utils import jwt_encode_handler,jwt_payload_handler #继承了Absract表的多方式登录 class LoginSerializer(serializers.ModelSerializer): username = serializers.CharField() class Meta: model = UserInfo fields = ['username','password'] def validate(self, attrs): username = attrs.get('username') password = attrs.get('password') #如果是手机号(^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$)中国合法是手机号码正则表达式 if re.match('^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$',username): user = UserInfo.objects.filter(phone=username).first() #如果是邮箱(^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$) elif re.match('^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$',username): user = UserInfo.objects.filter(email=username).first() else: user = UserInfo.objects.filter(username=username).first() if user and user.check_password(password): #登录成功,生成token #drf-jwt中有通过uer对象生成token的方法 payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) #token是要在视图类中使用,现在我们在序列化类在中 #self.context.get('request') #视图类和序列化类之间通过context这个字典来传递数据 self.context['token'] = token self.context['username'] = user.username return attrs else: raise ValidationError('用户名或者密码错误') #没有继承的多方式登录 class LoginMyuser(serializers.ModelSerializer): class Meta: model = MyUser fields = ['username', 'password'] def validate(self, attrs): username = attrs.get('username') password = attrs.get('password') # 如果是手机号(^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$)中国合法是手机号码正则表达式 if re.match('^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$', username): user = MyUser.objects.filter(phone=username).first() print(user) # 如果是邮箱(^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$) elif re.match('^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$', username): user = MyUser.objects.filter(email=username).first() print(user) else: user = MyUser.objects.filter(username=username).first() if user and password == user.password: # 登录成功,生成token # drf-jwt中有通过uer对象生成token的方法 payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) print(token) # token是要在视图类中使用,现在我们在序列化类在中 # self.context.get('request') # 视图类和序列化类之间通过context这个字典来传递数据 self.context['token'] = token self.context['username'] = user.username return attrs else: raise ValidationError('用户名或者密码错误')
View.py
from rest_framework.viewsets import ViewSet from app01.serizlizer import LoginSerializer,LoginMyuser from app01.utils import APIResponse from rest_framework.views import APIView class LoginViewSet(ViewSet): def create(self,request,*args,**kwargs): #实例化得到一个序列化的对象 #ser=LoginSerializer(data=request.data,context={'request':request}) ser = LoginSerializer(data=request.data) #序列化类的对象的校验方法 ser.is_valid(raise_exception=True) #字段自己的校验 局部校验,全局校验 #如果通过,表示登录成功,返回手动签发的token token = ser.context.get('token') username = ser.context.get('username') return APIResponse(token=token,username=username) #如果失败则不用管,因为设置了全局异常 class LoginMyuserViewset(ViewSet): def create(self,request,*args,**kwargs): ser = LoginMyuser(data=request.data) ser.is_valid(raise_exception=True) token = ser.context.get('token') username = ser.context.get('username') return APIResponse(token=token,username=username)
路由
path('login2/', views.MyLoginView.as_view()),
二、book、publish、author表关系以及抽象表的建立
# 注意:以后所有的数据删除,尽量用软删除,使用一个字段标志是否删除,而不是真正的从数据库中删除 -好处:1 这样删除数据不会影响索引,不会导致索引失效 2 之前存的用户数据还在,以备以后使用 # 表模型如下 # 抽象出一个基表(不再数据库生成,abstract=True),只用来继承 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', 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): # ll=[] # for author in self.authors.all(): # ll.append({'name':author.name,'sex':author.get_sex_display()}) return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()] 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)
三、book表单增群增
from app01 import serizlizer from app01 import models class BookView(APIView): def post(self,request,*args,**kwargs): if isinstance(request.data,dict): #看request.data是不是字典 #增一条 ser = serizlizer.BookSerializer(data=request.data) ser.is_valid(raise_exception=True) ser.save() #对象直接保存 return APIResponse(data=ser.data) elif isinstance(request.data,list): #增多条 ser = serizlizer.BookSerializer(data=request.data,many=True) #内部如何实现的? #many=True,ser不是BookSerizlizer对象,而是listSerializer对象,套了一个个的BookSerializer对象 print(type(ser)) ser.is_valid(raise_exception=True) # ser.save() return APIResponse(msg='增加%s条成功'%len(request.data)) def get(self,request,*args,**kwargs): pk = kwargs.get('pk',None) if pk: #单查 #方式一: # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first() #if not book: # raise Exception('要查询的不存在') book= models.Book.objects.get(id=pk,is_delete=False) ser = serizlizer.BookSerializer(instance=book) else: #查所有 book_list = models.Book.objects.all().filter(is_delete=False) ser = serizlizer.BookSerializer(instance=book_list,many=True) return APIResponse(data=ser.data)
book表的单删群删
def delete(self,request,*args,**kwargs): pk = kwargs.get('pk',None) pks = [] if pk: #单条删除 # res=models.Book.objects.filter(id=pk).update(is_delete=True) # print(res) # return APIResponse(msg='删除成功') pks.append(pk) else: pks = request.data print(request.data) # for i in request.data: # book=models.Book.objects.filter(title=request.data.get('title'),price=request.data.get('price')).first() # pks.append(book.pk) res = models.Book.objects.filter(id__in=pks).update(is_delete=True) # res = models.Book.objects.filter(id__in=pks).update(is_delete=True) print(res,type(res)) if res >=1: return APIResponse(msg='删除%s条成功'%res) else: #raise Exception('没有要删除的数据') return APIResponse(code=99,msg='没有要删除的数据')
book表的单增群增
def put(self,request,*args,**kwargs): pk = kwargs.get('pk',None) if pk: #单条修改 book = models.Book.objects.get(id=pk,is_delete=False) ser = serizlizer.BookSerializer(instance=book,data=request.data) ser.is_valid(raise_exception=True) ser.save() return APIResponse(msg='修改成功') else: #分析:ListSerializer的update方法没有写,需要我们自己去写 from rest_framework.serializers import ListSerializer #pks=[item['id'] for item in request.data] #如果我们不重写ListSerializer的update方法,这是存不进去的 pks = [] for item in request.data: pks.append(item['id']) item.pop('id') print(request.data) book_list = models.Book.objects.filter(id__in=pks,is_delete=False) ser = serizlizer.BookSerializer(instance=book_list,data=request.data,many=True) print(type(ser)) ser.is_valid(raise_exception=True) ser.save() print(ser,222222222222222222222) return APIResponse(msg='修改成功%s条成功'%len(pks)) # 你们能想到的方法 # pks = [] # for item in request.data: # pks.append(item['id']) # item.pop('id') # book_list = models.Book.objects.filter(id__in=pks, is_delete=False) # # for i,book in enumerate(book_list): # ser = serializer.BookSerializer(instance=book, data=request.data[i]) # ser.is_valid(raise_exception=True) # ser.save() # return APIResponse(msg='修改%s条成功'%len(book_list))
serizlizer.py
图书表序列化 from app01 import models class ListBookSerializer(serializers.ListSerializer): def update(self, instance, validated_data): print(instance) #book_list:是一堆图书对象 print(validated_data,9999999999) #列表套字典,是要修改的数据 print(self.child,1212121) return [self.child.update(book,validated_data[i]) for i,book in enumerate(instance) ] # child是所有图书的对象打印出来是这样的 ''' BookSerializer(data=[{'name': '金梅5up', 'price': '22.22', 'publish': 1, 'authors': [1]}, {'name': '金梅6up', 'price': '22.22', 'publish': 1, 'authors': [1]}], instance=<QuerySet [<Book: Book object (5)>, <Book: Book object (6)>]>): name = CharField(max_length=16) price = DecimalField(decimal_places=2, max_digits=5) publish = PrimaryKeyRelatedField(queryset=Publish.objects.all(), write_only=True) authors = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Author.objects.all(), write_only=True) publish_name = ReadOnlyField(read_only=True) author_list = ReadOnlyField(read_only=True) 1212121 ''' #视图view中的ser打印出来也是这样的,两者 """ BookSerializer(data=[{'name': '金梅5up', 'price': '22.22', 'publish': 1, 'authors': [1]}, {'name': '金梅6up', 'price': '22.22', 'publish': 1, 'authors': [1]}], instance=<QuerySet [<Book: Book object (5)>, <Book: Book object (6)>]>, many=True): name = CharField(max_length=16) price = DecimalField(decimal_places=2, max_digits=5) publish = PrimaryKeyRelatedField(queryset=Publish.objects.all(), write_only=True) authors = PrimaryKeyRelatedField(allow_empty=False, many=True, queryset=Author.objects.all(), write_only=True) publish_name = ReadOnlyField(read_only=True) author_list = ReadOnlyField(read_only=True) 222222222222222222222 """ class BookSerializer(serializers.ModelSerializer): class Meta: model = models.Book list_serializer_class = ListBookSerializer #指定many=True的时候,生成的ListBookSerializer的对象 fields = ['name','price','publish','authors','publish_name','author_list'] extra_kwargs = { 'publish':{'write_only':True}, 'authors':{'write_only':True}, 'publish_name':{'read_only':True}, 'author_list':{'read_only':True}, }
book表的单查群查
def get(self,request,*args,**kwargs): pk = kwargs.get('pk',None) if pk: #单查 #方式一: # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first() #if not book: # raise Exception('要查询的不存在') book= models.Book.objects.get(id=pk,is_delete=False) ser = serizlizer.BookSerializer(instance=book) else: #查所有 book_list = models.Book.objects.all().filter(is_delete=False) ser = serizlizer.BookSerializer(instance=book_list,many=True) return APIResponse(data=ser.data)