模型类
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):
# pk = if kwargs.get('pk') else None
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的视图
]