• 多表与基表等概念


    搭建前奏

    打开pycharm,建立day71的程序,如图

    项目建好以后在settings里面进行简单配置,如图所示

    然后简单地进行数据库的配置:

    接下来再在settings里面注册,如图:

    配置文件完成后再做一个路由分发,如图:

    接下来在总路由中进行路由分发与查找照片的相应配置,如图:

    再下来就是在__init__中进行连接数据库的相应配置,如图

    接着在settings进行全局配置,看图

    基础的结构配置已完成,接下来在models里面进行表的创建,如图:创建表所需的字段

    先创建一个基表,基表 : 基表的class Mate一定要加上abstract = True,因为该表是提供共有字段的,不是用来创表的如果创建表就要继承我,如果不想增加新的字段就继承我就行,若果想加新的字段,就在我的基础上增加新的字段。

    还有提一个就是模型类的封装就是共有类的封装,依据是abstract的Meta里面规定的

    # 所有的东西都来自于models.Model
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=0)
        create_time = models.DateTimeField(auto_now_add=True)
      # 作为基表的Model不能在数据库中形成对应的表    class Meta:
          abstract = True
         class Book(BaseModel): name = models.CharField(max_length=64) price = models.DecimalField(max_digits=5, decimal_places=2) image = models.ImageField(upload_to='img', default='image/default.jpg') publish = models.ForeignKey(to='Publish') authors = models.ManyToManyField(to='Author') class Meta: db_table = 'book' verbose_name = '书籍' verbose_name_plural = verbose_name def __str__(self): return self.name
       # 序列化插拔式属性===》完成自定义字段名完成连表查询
       @propery
       def publish_name(self)
          return self.publish.name
    class Publish(BaseModel): name = models.CharField(max_length=64) address = models.CharField(max_length=64) class Meta: db_table = 'publish' verbose_name = '出版社' verbose_name_plural = verbose_name def __str__(self): return self.name class Author(BaseModel): name = models.CharField(max_length=64) age = models.IntegerField() class Meta: db_table = 'author' verbose_name = '作者' verbose_name_plural = verbose_name def __str__(self): return self.name
       def get_sex(self, obj):
         # choice类型的解释性值, get_字段_display() 来访问
         return obj.get_sex_display
    class AuthorDetail(BaseModel): mobile = models.CharField(max_length=11) author = models.OneToOneField(to='Author') class Meta: db_table = 'author_detail' verbose_name = '作者详情' verbose_name_plural = verbose_name def __str__(self): return '%s的详情' % self.author.name

      表建好以后进行数据库的创建,然后连接数据库,将数据迁移在数据库里面,如图

    表成功迁移至是数据库

    2. 多表断关联

      1,创建超级用户,在app01下的admin进行注册,如图

     现在就开始断关系,来到models模块里面,作者被删,那么作者详情也就会被删,如图,related_name = detail叫做反向查询 , db_constraint=False  断关联

     在根目录下建立script/model.py的测试脚本,如图

     django脚本化启动

    运行django脚本化并不是运行manage.py,运行结果:

    在这边拓展下级联关系,比如,书籍是作者写的,写这本书的人西去了,那么这本书的作者还是有的,并且还是他,最鲜明的例子就是《西游记》,这就叫do_nothing,还有一个叫set_default,另外一个叫做SET_NULL,

    当unll=true, on_delete = models.SET_NULL时,会出现作者被删除,外键被删除,

    作者被删除

    外键被置空

    当设置为on_delete = models.SET_DEFAULT, default = true时,如图, 详情重置

    当设置为do_nothing时,如图:在现实生活中只是改了下字段,如图

    作者会被删掉

    外键什么的都没变

    总体来说,四种关系是这样的

    manytomany不能直接设置on_delete,要在第三张表中设置才可以

    三 . 多表序列化组件

      序列化层: app01/serializers.py

    from rest_framework.serializers import ModelSerializer
    from . import models
    
    class BookModelSerializer(ModelSerializer):
        class Meta:
            # 序列化类关联的model类
            model = models.Book
            # 参与序列化的字段
            fields = ('name',)  # 往前台返回的字段
         # 所有字段
         fields = ‘__all__’
         # 刨除。。不展示, 不能与fields同用
         exclude = ('id', 'is_delete')

      

    视图层: app01/views.py

    from rest_framework.views import APIView  # 负责请求过来的
    from rest_framework.response import Response  # 负责响应的
    
    from . import models, serializers  # 负责模型与序列化
    
    class Book(APIView):  
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if pk:
                try:
                   book_obj = models.Book.objects.get(pk=pk)
             # 序列化对象 book_data = serializers.BookModelSerializer(book_obj).data print(book_data) except: return Response({ 'status': 1, 'msg': '书籍不存在' }) else: book_query = models.Book.objects.all() book_data = serializers.BookModelSerializer(book_query,many=True).data # return Response({ 'status': 0, 'msg': 'ok', 'results': book_data })

      路由层: app01/urls.py

    urlpatterns = [
        url(r'^books/$', views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),
    ]
    

      

    四. 自定义子序列化深度连表查询

      自定义深度查询

    from rest_framework.serializers import ModelSerializer
    from . import models
    
    class PublishModelSerializer(ModelSerializer):
        class Meta:
            model = models.Publish
            fields = ('name', 'address')
    
    class BookModelSerializer(ModelSerializer):
    
    
        # 自定义连表深度 - 子序列化方法
    
        publish = PublishModelSerializer()  # 相当于调用了class PublishModelSerializer这个类,对其外键完成深度序列化
    
    
    
        class Meta:
            # 序列化类关联的model类
            model = models.Book
            # 参与序列化的字段
            fields = ('name', 'price','publish')  # 往前台返回的字段
            # fields = '__all__'
    

      效果如图:

      

    五. 多表反序列化组件

      序列化层: api/serializers.py

    视图层: app01/views.py

    效果如下:

    局部钩子与全局钩子的校验

    class BookModelDeserializer(ModelSerializer):
        class Meta:
            # 序列化类关联的model类
            model = models.Book
            # 参与序列化的字段
            fields = ('name', 'price','publish','authors', 'image')  # 往前台返回的字段
            # 加系统的约束条件,用来完成反序列化字段的系统校验规则
            extra_kwargs = {
                'name': {
                    'required': True,  # required是否是必须的
                    'min_length': 1,
                    'error_messages': {
                        'required': '必填项',  # 将原来没有传照片的提示改变为'必填项',其实也就是自定义的
                        'min_length': '太短'
                    }
                }
            }
    
    
        # 局部钩子的校验
        def validate_name(self, value):
            # 重复的书名校验
            # 检验书名不能包含‘g’
            if 'g' in value.lower():
                raise ValidationError('改书已经不能出版')
            return value
    
        # 全局钩子校验
        def validate(self, attrs):
            publish = attrs.get('publish')  # 序列化类已经将外键转化为对象
            name = attrs.get('name')
            if models.Book.objects.filter(name=name, publish=publish):
    
                raise ValidationError({'book': '改书已存在'})
            return attrs
    
            # ModelSerializer类已经帮我们实现了create与updata方法
    

      视图层:

    def post(self,request,*args,**kwargs):
            request_data = request.data  #获取post提交的数据包
            book_ser = serializers.BookModelDeserializer(data=request_data)
            # raise_exception=True:当校验失败,马上终止当前视图方法,抛异常返回给前台
            book_ser.is_valid(raise_exception=True) #检验是否合格 raise_exception=True必填的
            book_obj = book_ser.save()  #保存
            return Response({
                'status':0,
                'msg':'ok',
                'results':serializers.BookModelSerializers(book_obj).data
            })
    

      

    六 .序列化与反序列化的整合(************)

      序列化层:

      

    class V2BookModelSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 'price', 'img', 'author_list', 'publish_name', 'publish', 'authors')
            extra_kwargs = {
                'name': {
                    'required': True,  # requirred是否是必须的
                    'min_length': 1,
                    'error_messages': {
                        'required': '必填项', # 将原来没有传照片的提示改变为‘必须填’
                        'min_length': '太短',
                    }
                },
                'publish': {
                    'write_only': True
                },
                'authors': {
                    'write_only': True
                },
                'img': {
                    'read_only': True,
                },
                'author_list': {
                    'read_only': True,
                },
                'publish_name': {
                    'read_only': True,
                }
            }
    
        def validate_name(self, value):
            # 书名不能包含 g 字符
            if 'g' in value.lower():
                raise ValidationError('该g书不能出版')
            return value
    
        def validate(self, attrs):
            publish = attrs.get('publish')
            name = attrs.get('name')
            if models.Book.objects.filter(name=name, publish=publish):
                raise ValidationError({'book': '该书已存在'})
            return attrs
    

      序列化注意点:

    1) fields中设置所有序列化与反序列化字段
    2) extra_kwargs划分只序列化或只反序列化字段(一般我们把需要存入到数据库中的使用write_only(反序列化),只需要需要展示的就read_only(序列化),看需求设计)
        write_only:只反序列化
        read_only:只序列化
        自定义字段默认只序列化(read_only)
        如果字段没设置write_only或者read_only,那么该字段可以序列化和反序列化
    3) 设置反序列化所需的 系统、局部钩子、全局钩子 等校验规则
    

      视图层. views.py

    class V2Book(APIView):
        def get(self,request,*args,**kwargs):
            pk = kwargs.get('pk')
            #单查
            if pk:
                try:
                    book_obj = models.Book.objects.get(pk=pk,is_delete=False)
                    book_data = serializers.V2BookModelSerializer(book_obj).data  #序列化
                except:
                    return Response({
                        'status':1,
                        'msg':'参数有误'
                    })
            #群查
            else:
                book_query=models.Book.objects.filter(is_delete=False).all()
           # many = true 多条数据 book_data = serializers.V2BookModelSerializer(book_query,many=True).data #序列化 return Response({ 'status':0, 'msg':'ok', 'results':book_data }) def post(self,request,*args,**kwargs): #单增:传的数据是与model对应的一个字典 # 群增:设计传递的是多个model对应的字典列表 request_data = request.data if isinstance(request_data,dict): many = False elif isinstance(request_data,list): #在postman中设计一个列表存入每条数据 many = True else: return Response({ 'status':1, 'msg':'数据错误' }) book_ser = serializers.V2BookModelSerializer(data=request_data,many=many) #反序列化 book_ser.is_valid(raise_exception=True) book_result = book_ser.save() #book_result是对象<class 'app01.models.Book'>,如果增加多个就是列表套一个个对象
         return Response({ 'status':0, 'msg':'ok', 'results':serializers.V2BookModelSerializer(book_result,many=many).data }) #单删: 有pk #在postman中通过路径传参 #群删:有pks {"pks": [1, 2, 3]} #通过json传参 两者都不需要序列化,只是将数据库中的0变为1 def delete(self,request,*args,**kwargs): pk = kwargs.get('pk') if pk: # 单删 pks = [pk] else: # 群删 pks = request.data.get('pks') if models.Book.objects.filter(pk__in=pks,is_delete=False).update(is_delete=True): return Response({ 'status':0, 'msg':'删除成功' }) return Response({ 'status':1, 'msg':'删除失败' })

      视图层注意点:(*****)

    1.序列化数据最后必须要.data
    2.反序列化通过data传参
    3.反序列化与序列化都能使用many=True
    

      路由层: urls.py

    urlpatterns = [
        url(r'^v2/books/$', views.V2Book.as_view()),
        url(r'^v2/books/(?P<pk>.*)/$', views.V2Book.as_view()),
    ]
    

      

    生前无需久睡,死后自会长眠,努力解决生活中遇到的各种问题,不畏将来,勇敢面对,加油,你是最胖的,哈哈哈
  • 相关阅读:
    《基于B_S模式的教务管理系统设计与实现》论文笔记(三)
    《重修补考报名考务管理信息系统中的网络技术》论文笔记(二)
    《基于WEB的独立学院补考重修管理系统研究》论文笔记(一)
    重修安排管理系统的设计与实现 文献收集
    重修安排管理系统的设计与实现 文献收集
    《暗时间》读书笔记
    R、Python、Scala 和 Java,到底该使用哪一种大数据编程语言?
    编程和音乐真的很像吗?
    关于虚拟现实叙事方式的终极入门指南
    如何避免脆弱的代码
  • 原文地址:https://www.cnblogs.com/panshao51km-cn/p/11695242.html
Copyright © 2020-2023  润新知