设为首页 收藏本站
查看: 567|回复: 0

Django中drf图书增删改查(单条和批量操作)

[复制链接]
累计签到:504 天
连续签到:1 天
发表于 2022-12-30 00:25:55 | 显示全部楼层 |阅读模式
from django.shortcuts import render
from api.ser import BookModelSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from api import models
# Create your views here.

路由部分总路由urlpatterns = [
    # 路由分发
    path('api/', include('api.urls')),
]api路由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()),
]
View视图部分(核心逻辑部分)
class BookAPIView(APIView):
   
def get(self,request,*args,**kwargs):
        
# 查询单个和查询所有,合在一起
        book_list = models.Book.objects.all().first(is_delete=False)
        book_list_ser= BookModelSerializer(book_list
,many=True)
        
return Response(data=book_list_ser.data)
        
# 查询单个
        # book_list = models.Book.objects.filter(pk=kwargs.get('pk')).first() 下面一样的

    def post(self,request,*args,**kwargs):
        
# 具备增多条还是增加一条,一条时前端传过来的只有一个字典,多条时列表套字典
        if isinstance(request.data,dict):
            book_ser=BookModelSerializer(
data=request.data)
            book_ser.is_valid(
raise_exception=True)
            
# 如果不清洗数据是没有数据,也就没法用save()方法
            book_ser.save()
            
return Response(data=book_ser.data)
        
# 批量增加
        elif isinstance(request.data,list):
            
# 因为many源码可以得到book_ser已经变成了listSerializer对象
            book_ser = BookModelSerializer(data=request.data,many=True)
            book_ser.is_valid(
raise_exception=True)
            
# 如果不清洗数据是没有数据,也就没法用save()方法
            book_ser.save() # 调用的是ListSerializercreate方法,源码写过了就不用自己写create方法了
            # 新增--ListSerializer--create方法走的是列表for循环,源码如下
            # def create(self, validated_data):
            #   self.childBookModelSerializer对象
            #   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)#部分修改partial=True内部处理成required=True
            book_ser.is_valid()
            book_ser.save()
            
return Response(book_ser.data)
        
else:
            
# 改多个 重点的在many=True 会调用ListSerializer的方法,我们自己写了一个类的方法,里面没有update方法,需要自己重写,我们在class Meta中重写的了代码list_serializer_class自定义的方法
            # 前端传递的数格式[{id:1,name:xx,price:xx}{id:1,name:xx,price:xx}]
            # 处理传入的数据 对象列表[book1book2] 修改的数据列表[{name:xx,price:xx}{name:xx,price:xx}]
            book_list=[]
            modify_data=[]
            
for item in request.data:
               
# item {id:1,name:xx,price:xx} pop方法后就是我们正常的存入的数据
                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,data=si_data)
            #     book_ser.is_valid(raise_exception=True)
            #     book_ser.save()  # ListSerializerupdate方法,自己写的update方法
            # return Response(data='成功')
            # # 第二种方案,重写ListSerializerupdate方法
            book_ser = BookModelSerializer(instance=book_list,data=modify_data,many=True)
            book_ser.is_valid(
raise_exception=True)
            book_ser.save()
#ListSerializerupdate方法,自己写的update方法
            return Response(book_ser.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).update(is_delete=True)
        
if ret:
            
return Response(data={'msg':'删除成功'})
        
else:
            
return Response(data={'msg':'没有可删除的数据'})序列化ser.pyfrom 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,si_data)
        #     ll.append(ret)
        # return ll
        # 源码高级写法
        return [
            # self.child.update(被修改的对象,传入的字典) for attrs in validated,调的Bookupdate方法
            self.child.update(instance,attrs) for i,attrs in enumerate(validated_data)
        ]

# 如果序列化是数据库的表,尽量用ModelSerializer
class BookModelSerializer(serializers.ModelSerializer):
    # 一种方案(只序列化可以,反序列化有问题)
    publish=serializers.CharField(source='publish.name')
    # 第二种方案,models中写方法
    class Meta:
        list_serilizer_class=BookListSerializer
        model=models.Book
        # fields='__all__'
        # depth=1
        fields=('name','price','authors','publish','publish_name','author_list')
        extra_kwargs={
            'publish':{'write_only':True},# post写字段的时候必须要写,但是不会展示
            'publish_name':{'read_only':True},# get时只展示,不用传进去
            'authors':{'write_only':True},
            'author_lst':{'read_only':True},
        }表设计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): 不能叫authors否则会把之前的替换掉
    def author_list(self):
        author_list=self.authors.all()# 多对多,author中可能有多个对象所以用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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-1003518-1-1.html 上篇帖子: Django中drf三大组件:认证组件、权限组件、频率组件、Response 下篇帖子: Django之drf分页器使用
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表