drf单、群增删查改
一、单群增
① models.py
from django.db import models
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)
# 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
# create_time = models.DateTimeField(default=Datetime.datetime.now)
class Meta:
# 单个字段,有索引,有唯一
# 多个字段,又联合索引,联合唯一
abstract = True # 抽象表,不在数据库中创建实际表
class Book(BaseModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name="书名")
price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 一对多关系一旦确立,关联字段写在多的一边
# to_field 默认不写,关联到Publish主键
# db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
# 多对多关系,跟作者 关联字段写在查询次数多的一方
# 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动; 第三张表有扩展字段,需要手动写
# 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
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):
# 拿到所有作者
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,verbose_name="出版社")
addr = models.CharField(max_length=32,verbose_name="地址")
class Meta:
verbose_name_plural = "出版社"
def __str__(self):
return self.name
class Author(BaseModel):
name = models.CharField(max_length=32,verbose_name="作者")
sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
# 一对一关系,关联字段写在查询频率高的那一方
# 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 self.name
class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=11,verbose_name="手机号")
class Meta:
verbose_name_plural = "作者详情表"
def __str__(self):
return self.mobile
# 表断关联
# 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
# 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
# 3.断关系一定要通过逻辑保证表支架数据安全
# 4.断关联
# 5.级联关系
# <1> 作者没了,详情也没了:on_delete = models.CASCADE
# <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
# <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
# <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
② ser.py
from api import models
from rest_framework import serializers
# 写一个类,继承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):
# 这是重写修改数据时需要执行的方法
# instance = book_list,数据格式是:[book1,book2,book3]
# validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
# 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
# list_serializer_class = BookListSerializer
print("----》",instance)
print("---->",validated_data)
# ll = []
# for i,si_data in enumerate(validated_data):
# result = self.child.update(instance[i],si_data)
# ll.append(result)
# return ll
"""上面的方法和下面的方法一致"""
return [
self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# def update(self, instance = instance[i], validated_data = attrs):
# pass
]
# 如何序列化的是数据库的表,尽量用ModelSerializer
class BookSerializer(serializers.ModelSerializer):
# depth:控制的是在前端展示的外键数据
# 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
# 方式一:只序列化可以,反序列化会出现问题
# publish = serializers.CharField(source="publish.name")
# 方式二:在models中写方法
# ...
class Meta:
list_serializer_class = BookListSerializer
model = models.Book
# fields = "__all__"
# 控制前端展示的数据信息,用得少
# depth = 0
fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {"read_only": True},
'authors': {'write_only': True},
'author_list': {"read_only": True},
}
③ urls.py
# 使用了路由分发
from django.conf.urls import url
from api import views
urlpatterns = [
# 此处一定要记得,特殊的路由放在上面,避免匹配到
url(r'books/(?P<pk>\d+)', views.BookAPIView.as_view()),
url(r'books/', views.BookAPIView.as_view()),
]
④ views.py
"""单查群查、单增群增、单改群改、单删群删"""
class BookAPIView(APIView):
# 增加一条和多条数据
def post(self, request, *args, **kwargs):
# 具备增单条和增多条的功能
if isinstance(request.data, dict): # 如果request.data 是一个套字段信息的字典,就是增一条数据 {}
book_ser = ser.BookSerializer(data=request.data)
book_ser.is_valid(raise_exception=True)
book_ser.save()
return Response(data=book_ser.data)
elif isinstance(request.data, list): # 如果request.data 是一个套字段信息的多个字典的列表,就是增多条数据 [{},{},{}]
# 此时的book_ser是ListSerializer对象
book_ser = ser.BookSerializer(data=request.data, many=True)
print(type(book_ser))
book_ser.is_valid(raise_exception=True)
book_ser.save()
# 此时的book_ser.save()是谁的方法?
'''
此时的book_ser是ListSerializer对象,所以save()方法是ListSerializer的save()的方法
批量新增-----》ListSerializer------》create()方法
# 源码中的方法
def create(self,validated_data):
# self.create是bookSerializer对象
return [
self.child.create(attr) for attr in validated_data
]
'''
return Response(data=book_ser.data)
二、单群删
① models.py
from django.db import models
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)
# 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
# create_time = models.DateTimeField(default=Datetime.datetime.now)
class Meta:
# 单个字段,有索引,有唯一
# 多个字段,又联合索引,联合唯一
abstract = True # 抽象表,不在数据库中创建实际表
class Book(BaseModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name="书名")
price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 一对多关系一旦确立,关联字段写在多的一边
# to_field 默认不写,关联到Publish主键
# db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
# 多对多关系,跟作者 关联字段写在查询次数多的一方
# 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动; 第三张表有扩展字段,需要手动写
# 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
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):
# 拿到所有作者
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,verbose_name="出版社")
addr = models.CharField(max_length=32,verbose_name="地址")
class Meta:
verbose_name_plural = "出版社"
def __str__(self):
return self.name
class Author(BaseModel):
name = models.CharField(max_length=32,verbose_name="作者")
sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
# 一对一关系,关联字段写在查询频率高的那一方
# 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 self.name
class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=11,verbose_name="手机号")
class Meta:
verbose_name_plural = "作者详情表"
def __str__(self):
return self.mobile
# 表断关联
# 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
# 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
# 3.断关系一定要通过逻辑保证表支架数据安全
# 4.断关联
# 5.级联关系
# <1> 作者没了,详情也没了:on_delete = models.CASCADE
# <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
# <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
# <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
② ser.py
from api import models
from rest_framework import serializers
# 写一个类,继承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):
# 这是重写修改数据时需要执行的方法
# instance = book_list,数据格式是:[book1,book2,book3]
# validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
# 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
# list_serializer_class = BookListSerializer
print("----》",instance)
print("---->",validated_data)
# ll = []
# for i,si_data in enumerate(validated_data):
# result = self.child.update(instance[i],si_data)
# ll.append(result)
# return ll
"""上面的方法和下面的方法一致"""
return [
self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# def update(self, instance = instance[i], validated_data = attrs):
# pass
]
# 如何序列化的是数据库的表,尽量用ModelSerializer
class BookSerializer(serializers.ModelSerializer):
# depth:控制的是在前端展示的外键数据
# 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
# 方式一:只序列化可以,反序列化会出现问题
# publish = serializers.CharField(source="publish.name")
# 方式二:在models中写方法
# ...
class Meta:
list_serializer_class = BookListSerializer
model = models.Book
# fields = "__all__"
# 控制前端展示的数据信息,用得少
# depth = 0
fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {"read_only": True},
'authors': {'write_only': True},
'author_list': {"read_only": True},
}
③ urls.py
# 使用了路由分发
from django.conf.urls import url
from api import views
urlpatterns = [
# 此处一定要记得,特殊的路由放在上面,避免匹配到
url(r'books/(?P<pk>\d+)', views.BookAPIView.as_view()),
url(r'books/', views.BookAPIView.as_view()),
]
④ views.py
"""单查群查、单增群增、单改群改、单删群删"""
class BookAPIView(APIView):
# 删除一条和多条数据
def delete(self,request,*args,**kwargs):
# 多条单条一起删除
pk = kwargs.get('pk')
pks = []
if pk:
"""删除一条数据"""
# 此处的pk是前端在url路径后面拼接的数据pk
# append进pks是为了后面一起删除数据
print(pk)
pks.append(pk)
else:
"""删除多条数据"""
# 此处的pks是前端在body中传入的需要删除的数据的pk
# 前端传回来的数据格式是{'pks':[1,2,3]}
# 直接赋值给pks是为了后面一起删除数据
pks = request.data.get('pks')
# 数据并不是真正的删除,只是将is_delete字段改成False而已
# result 是返回受影响的字段数,是一个int类型
result = models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True)
if result > 0:
return Response(data='删除成功')
else:
return Response(data="删除失败")
三、单群查
① models.py
from django.db import models
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)
# 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
# create_time = models.DateTimeField(default=Datetime.datetime.now)
class Meta:
# 单个字段,有索引,有唯一
# 多个字段,又联合索引,联合唯一
abstract = True # 抽象表,不在数据库中创建实际表
class Book(BaseModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name="书名")
price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 一对多关系一旦确立,关联字段写在多的一边
# to_field 默认不写,关联到Publish主键
# db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
# 多对多关系,跟作者 关联字段写在查询次数多的一方
# 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动; 第三张表有扩展字段,需要手动写
# 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
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):
# 拿到所有作者
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,verbose_name="出版社")
addr = models.CharField(max_length=32,verbose_name="地址")
class Meta:
verbose_name_plural = "出版社"
def __str__(self):
return self.name
class Author(BaseModel):
name = models.CharField(max_length=32,verbose_name="作者")
sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
# 一对一关系,关联字段写在查询频率高的那一方
# 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 self.name
class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=11,verbose_name="手机号")
class Meta:
verbose_name_plural = "作者详情表"
def __str__(self):
return self.mobile
# 表断关联
# 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
# 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
# 3.断关系一定要通过逻辑保证表支架数据安全
# 4.断关联
# 5.级联关系
# <1> 作者没了,详情也没了:on_delete = models.CASCADE
# <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
# <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
# <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
② ser.py
from api import models
from rest_framework import serializers
# 写一个类,继承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):
# 这是重写修改数据时需要执行的方法
# instance = book_list,数据格式是:[book1,book2,book3]
# validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
# 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
# list_serializer_class = BookListSerializer
print("----》",instance)
print("---->",validated_data)
# ll = []
# for i,si_data in enumerate(validated_data):
# result = self.child.update(instance[i],si_data)
# ll.append(result)
# return ll
"""上面的方法和下面的方法一致"""
return [
self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# def update(self, instance = instance[i], validated_data = attrs):
# pass
]
# 如何序列化的是数据库的表,尽量用ModelSerializer
class BookSerializer(serializers.ModelSerializer):
# depth:控制的是在前端展示的外键数据
# 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
# 方式一:只序列化可以,反序列化会出现问题
# publish = serializers.CharField(source="publish.name")
# 方式二:在models中写方法
# ...
class Meta:
list_serializer_class = BookListSerializer
model = models.Book
# fields = "__all__"
# 控制前端展示的数据信息,用得少
# depth = 0
fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {"read_only": True},
'authors': {'write_only': True},
'author_list': {"read_only": True},
}
③ urls.py
# 使用了路由分发
from django.conf.urls import url
from api import views
urlpatterns = [
# 此处一定要记得,特殊的路由放在上面,避免匹配到
url(r'books/(?P<pk>\d+)', views.BookAPIView.as_view()),
url(r'books/', views.BookAPIView.as_view()),
]
④ views.py
"""单查群查、单增群增、单改群改、单删群删"""
class BookAPIView(APIView):
# 查询一条和多条数据
def get(self, request, *args, **kwargs):
# 查询单个和查询所有,合到一起
if kwargs.get('pk', None): # 查询一条数据
book_obj = models.Book.objects.filter(pk=kwargs.get('pk'), is_delete=False).first()
book_ser = ser.BookSerializer(instance=book_obj)
return Response(data=book_ser.data)
else: # 此处是查询所有
book_list_obj = models.Book.objects.all().filter(is_delete=False)
book_list_ser = ser.BookSerializer(instance=book_list_obj, many=True)
return Response(data=book_list_ser.data)
四、单群改
① models.py
from django.db import models
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)
# 此处的Datetime.datetime.now不需要加括号,加括号和不加括号有很大的区别
# create_time = models.DateTimeField(default=Datetime.datetime.now)
class Meta:
# 单个字段,有索引,有唯一
# 多个字段,又联合索引,联合唯一
abstract = True # 抽象表,不在数据库中创建实际表
class Book(BaseModel):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=32,verbose_name="书名")
price = models.DecimalField(max_digits=5,decimal_places=2,verbose_name="价格")
# 一对多关系一旦确立,关联字段写在多的一边
# to_field 默认不写,关联到Publish主键
# db_constraint = False 逻辑上的关联,实质上没有外键联系,增删不会受外键影响,但是orm查询不影响
publish = models.ForeignKey(to="Publish",on_delete=models.DO_NOTHING,db_constraint=False)
# 多对多关系,跟作者 关联字段写在查询次数多的一方
# 什么时候使用自动,什么时候使用手动? 第三张表只有关联字段,用自动; 第三张表有扩展字段,需要手动写
# 不能写on_delete 因为使用自动的话,这是orm帮我们建的关系表,不会真正作用到数据库中
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):
# 拿到所有作者
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,verbose_name="出版社")
addr = models.CharField(max_length=32,verbose_name="地址")
class Meta:
verbose_name_plural = "出版社"
def __str__(self):
return self.name
class Author(BaseModel):
name = models.CharField(max_length=32,verbose_name="作者")
sex = models.IntegerField(choices=((1,"男"),(2,'女'),),verbose_name="性别")
# 一对一关系,关联字段写在查询频率高的那一方
# 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 self.name
class AuthorDetail(BaseModel):
mobile = models.CharField(max_length=11,verbose_name="手机号")
class Meta:
verbose_name_plural = "作者详情表"
def __str__(self):
return self.mobile
# 表断关联
# 1.表之间没有外键关联,但是有外键逻辑关联(有充当外键的字段)
# 2.断关系后不会影响数据查询效率,但是会极大提高数据库增删改效率(不影响增删改查操作)
# 3.断关系一定要通过逻辑保证表支架数据安全
# 4.断关联
# 5.级联关系
# <1> 作者没了,详情也没了:on_delete = models.CASCADE
# <2> 出版社没了,书还是那个出版社出版:on_delete = models.DO_NOTHING
# <3> 部门没了,员工没有部门(空不能):null = True ,on_delete = models.SET_NULL
# <4> 部门没了,员工进入默认部门(默认值):default = 0,on_delete = models.SET_DEFAULT
② ser.py
from api import models
from rest_framework import serializers
# 写一个类,继承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):
# 这是重写修改数据时需要执行的方法
# instance = book_list,数据格式是:[book1,book2,book3]
# validated_data = modify_data,数据格式是:[{name:jason,price:12},{name:jason,price:12}]
# 此处的self.child是BookSerializer对象,但是需要在BookSerializer中的Meta中配置一句话
# list_serializer_class = BookListSerializer
print("----》",instance)
print("---->",validated_data)
# ll = []
# for i,si_data in enumerate(validated_data):
# result = self.child.update(instance[i],si_data)
# ll.append(result)
# return ll
"""上面的方法和下面的方法一致"""
return [
self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# self.child.update(instance[i], attrs) for i, attrs in enumerate(validated_data)
# def update(self, instance = instance[i], validated_data = attrs):
# pass
]
# 如何序列化的是数据库的表,尽量用ModelSerializer
class BookSerializer(serializers.ModelSerializer):
# depth:控制的是在前端展示的外键数据
# 因为数据库中的有些数据不需要在前端展示,所以需要在后端处理展示的信息
# 方式一:只序列化可以,反序列化会出现问题
# publish = serializers.CharField(source="publish.name")
# 方式二:在models中写方法
# ...
class Meta:
list_serializer_class = BookListSerializer
model = models.Book
# fields = "__all__"
# 控制前端展示的数据信息,用得少
# depth = 0
fields = ('id','name', 'price', 'authors', 'publish', 'publish_name', 'author_list')
extra_kwargs = {
'publish': {'write_only': True},
'publish_name': {"read_only": True},
'authors': {'write_only': True},
'author_list': {"read_only": True},
}
③ urls.py
# 使用了路由分发
from django.conf.urls import url
from api import views
urlpatterns = [
# 此处一定要记得,特殊的路由放在上面,避免匹配到
url(r'books/(?P<pk>\d+)', views.BookAPIView.as_view()),
url(r'books/', views.BookAPIView.as_view()),
]
④ views.py
"""单查群查、单增群增、单改群改、单删群删"""
class BookAPIView(APIView):
# 修改一条和多条数据
def put(self, request, *args, **kwargs):
if kwargs.get('pk', None): # 修改一条数据
# kwargs中如果没有pk这个键,就返回None,也就是不会走if中的代码
book_obj = models.Book.objects.filter(pk=kwargs.get("pk")).first()
book_ser = ser.BookSerializer(instance=book_obj, data=request.data)
book_ser.save()
return Response(request.data)
else: # 改多条数据
"""第一种方式,序列化器的代码不需要修改"""
# book_list = [] # 此时book_list类似于[book1,book2,book3]格式的数据
# modify_data = [] # 此时的modify_data类似于[{name:jason,price:12},{name:jason,price:12}]格式的数据
# for item in request.data: # 此时request.data是一个列表套字典格式的数据
# pk = item.pop('id')
# book = models.Book.objects.filter(pk=pk).first()
# book_list.append(book)
# modify_data.append(item)
#
# for i,si_data in modify_data:
# book_ser = ser.BookSerializer(instance=book_list[i],data=si_data)
# book_ser.is_valid(raise_exception=True)
# book_ser.save()
# return Response(data="成功")
"""第二种方式:复杂点,并且需要配合序列化器,实现的代码全都写在序列化器中"""
# print(request.data)
# return Response(request.data)
# 前端传过来的数据格式:[{id:1,name:jason,price:12},{id:1,name:jason,price:12},{id:1,name:jason,price:12}]
# 处理后的数据 对象列表instance = [book1,book2,book3] 修改的数据列表data = [{name:jason,price:12},{name:jason,price:12}]
book_list = [] # 此时book_list类似于[book1,book2,book3]格式的数据
modify_data = [] # 此时的modify_data类似于[{name:jason,price:12},{name:jason,price:12}]格式的数据
for item in request.data: # 此时request.data是一个列表套字典格式的数据
pk = item.pop('id')
book = models.Book.objects.filter(pk=pk).first()
book_list.append(book)
modify_data.append(item)
# 序列化
book_list_ser = ser.BookSerializer(instance=book_list, data=modify_data, many=True)
# 校验数据
book_list_ser.is_valid(raise_exception=True)
# 保存数据
book_list_ser.save() # 此时的save()方法是ListSerializer的update方法,但是我们现在自己写一个update方法,使用哪自己的方法
return Response(book_list_ser.data)