drf图书管理数据的增删查改
模型类
from django.db import models # Create your models here. class BaseModel(models.Model): create_time = models.DateTimeField(auto_now_add=True) is_delete = models.BooleanField(default=False) last_update_time = models.DateTimeField(auto_now=True) class Meta: # abstract=True说明是一个抽象类,不会生成表 abstract = True class Book(BaseModel): name = models.CharField(max_length=32) price = models.DecimalField(max_digits=5,decimal_places=2) # db_constraint表示实质上没有外键联系,只是逻辑上的关联,增删不会有影响,同时不影响我们orm查询 publish = models.ForeignKey(to='Publish',db_constraint=False,on_delete=models.DO_NOTHING) # 自动:中间表只有两个表的关联字段,用自动创第三张表的方式 # 手动:中间表有扩展字段,需要用手动的方式,through,through_fields, authors = models.ManyToManyField(to='Author') class Meta: verbose_name_plural = '图书表' # common_serializer.py中的方案二 @property def publish_name(self): return self.publish.name # # 也可以用common_serializers.py中的方案三 # def author_list(self): # author_list = self.authors.all() # # 可以用列表生成式代替下面代码块 # # l = [] # # for author in author_list: # # l.append({'name':author.name,'gender':author.get_gender_display()}) # # return l # return [{'name':author.name,'gender':author.get_gender_display()} for author in author_list] def __str__(self): return '%s'% self.name class Publish(BaseModel): name = models.CharField(max_length=32) addr = models.CharField(max_length=255) class Meta: verbose_name_plural = '出版社表' def __str__(self): return '%s'% self.name class Author(BaseModel): name = models.CharField(max_length=32) gender = models.IntegerField(choices=((1,'男'), (2,'女')), ) # OneToOneField本质就是ForeignKey+unique,自己手动写也可以 author_detail = models.OneToOneField(to='AuthorDetail',db_constraint=False,on_delete=models.CASCADE) class Meta: verbose_name_plural = '作者表' def __str__(self): return '%s'% self.name class AuthorDetail(BaseModel): phone = models.CharField(max_length=32) class Meta: verbose_name_plural = '作者详情表'
序列化器
# common_serializer.py 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) # 重写update方法 def update(self, instance, validated_data): print(instance) print(validated_data) # 保存数据 # self.child:是BookModelSerializer对象 # 下面的代码块可以用列表生成式表示 # l = [] # for i,attrs in enumerate(validated_data): # res = self.child.update(instance[i],attrs) # l.append(res) # return l return [ # self.child.update(对象,字典) for attrs in validated_data self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data) ] class BookModelSerializer(serializers.ModelSerializer): # 方案一(序列化可以,反序列化容易出错,传publish的id还是name) # publish = serializers.CharField(source='publish.name') # 方案三(跟方案二差不多,方案二在模型类中定义方法,方案三直接在序列化器内定义方法) # authors = serializers.SerializerMethodField() # # 方案三配套方法,方法名:get_字段名 # def get_authors(self, instance): # authors = instance.authors.all() # 这里的instance就是模型类中的book对象 # l = [] # for author in authors: # l.append({'name':author.name,'gender':author.get_gender_display()}) # return l class Meta: # 通过list_serializer_class与BookListSerializer类进行关联 list_serializer_class = BookListSerializer model = models.Book # 方案二(在模型类中定义一个publish_name方法),推荐 # fields = ('name','price','publish','publish_name','authors','author_list') fields = ('name','price','publish','publish_name','authors',) # depth = 1 # 可以设置深度,查询联表下一级的数据 extra_kwargs = { 'publish':{"write_only":True}, 'publishj_name':{'read_only':True}, # 'authors': {"write_only": True}, # 'author_list': {'read_only': True}, } # publish = serializers.SerializerMethodField() # def get_publish(self, instance): # publish_name = instance.publish.name # return publish_name
视图函数
from django.shortcuts import render from rest_framework.views import APIView from rest_framework.generics import GenericAPIView from rest_framework.response import Response from api import models from api.common_serializers import BookModelSerializer # Create your views here. class BookGenericAPIView(GenericAPIView): queryset = models.Book.objects.all().filter(is_delete=False) serializer_class = BookModelSerializer def get(self,request,*args,**kwargs): books = self.get_queryset() # 查询多条 需要加many=True book_ser = self.get_serializer(instance=books,many=True) return Response(book_ser.data) def post(self,request,*args,**kwargs): # 如果传的数据是字典 说明是增1条 if isinstance(request.data,dict): book_ser = self.get_serializer(data=request.data) if book_ser.is_valid(): book_ser.save() return Response(book_ser.data) # 如果传的数据是列表 说明是增多条 elif isinstance(request.data,list): # 新增多条 需要加many=True book_ser = self.get_serializer(data=request.data,many=True) if book_ser.is_valid(): 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(book_ser.data) def put(self,request,*args,**kwargs): # 改单个 判断是否有pk 如果有则修改单个 没有则修改多个 if kwargs.get('pk',None): book = self.get_object() # partial=True表示可以修改部分内容 book_ser = self.get_serializer(instance=book,data=request.data,partial=True) if book_ser.is_valid(): book_ser.save() return Response(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_list = [] # # 方式一:直接通过for循环前端传过来的数据,对数据进行不同的处理 # for book_dic in request.data: # pk = book_dic.pop('id',None) # 获取id 通过id获取book对象 # book = models.Book.objects.filter(pk=pk).first() # book_list.append(book) # 得到[book1,book2] # modify_data_list.append(book_dic) # 删除id后的book_dic [{name:xx,price:xx},{name:xx,price:xx}] # 通过for循环一条条修改 # for i,modify_data in enumerate(modify_data_list): # book_ser = self.get_serializer(instance=book_list[i],data=modify_data) # if book_ser.is_valid(): # book_ser.save() # return Response({'msg':'修改成功%s条数据'%(i+1)}) # 方式二:在序列化器的py文件内 重写ListSerializer类中的update方法 本质也是通过for循环 book_list = [] modify_data_list = [] for book_dic in request.data: pk = book_dic.pop('id',None) book = models.Book.objects.filter(pk=pk).first() book_list.append(book) modify_data_list.append(book_dic) # 删除id后的book_dic # 直接传入对象列表[book1,book2] 以及修改的数据列表[{name:xx,price:xx},{name:xx,price:xx}] # 修改多条必须加many=True 会直接走ListSerializer book_ser = self.get_serializer(instance=book_list,data=modify_data_list,many=True) if book_ser.is_valid(): book_ser.save() # 会走ListSerializer的update方法,自己写的update方法 return Response(book_ser.data) def delete(self,request,*args,**kwargs): # 单个删除/批量删除 pk = kwargs.get('pk') pks = [] if pk: # 不管是单个删除还是批量删除,都从pks里面删 pks.append(pk) else: # 多条删除 {'pks':[1,2,3]} pks = request.data.get('pks') # 把is_delete设置成True res返回的是受影响的行数 res = models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True) if res: return Response({'msg':'删除成功!删除了%s行'%res}) else: return Response({'msg':'没有你要删除的数据'})
路由
from django.contrib import admin from django.urls import path,re_path from api import views urlpatterns = [ path('admin/', admin.site.urls), path('books/',views.BookGenericAPIView.as_view()), re_path(r'^books/(?P<pk>\d+)/',views.BookGenericAPIView.as_view()), # 匹配带pk的视图 ]