天天看點

「Django」rest_framework學習系列-序列化

序列化

方式一 :在業務類裡序列化資料庫資料

class RolesView(APIView):
    def get(self,request,*args,**kwargs):
        roles = models.Role.objects.all().values('id','title')[1:3]
        ret = list(roles)
        r = json.dumps(ret,ensure_ascii=False)
        return HttpResponse(r)      

View Code

方式二:寫個序列化的類,在業務類中引用,序列化類中可以定制字段

class UserinfoSerializer(serializers.ModelSerializer):
    #字段名與資料庫相同則替換,不同則添加
    type = serializers.CharField(source='get_usertype_display')
    gb = serializers.CharField(source='group.title')
    class Meta:
        model = models.UserInfo
        #全部顯示
        fields = '__all__'
        #定制顯示
        # fields = ['id','username','type','gb']      

定制類

class UserInfo(models.Model):
    usertype_choices = (
        (1,'普通使用者'),
        (2,'VIP使用者'),
        (3,'SVIP使用者')
    )
    usertype = models.IntegerField(choices=usertype_choices,verbose_name='使用者類型')
    username = models.CharField(max_length=32,unique=True,verbose_name='使用者名')
    password = models.CharField(max_length=64,verbose_name='密碼')
    group = models.ForeignKey('UserGroup',on_delete=models.DO_NOTHING,verbose_name='分組')
    roles = models.ManyToManyField('Role',verbose_name='職業')
    class Meta:
        verbose_name = '使用者管理'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username      

對應資料庫結構

class UserInfoView(APIView):
    authentication_classes = []
    permission_classes = []
    def get(self,request,*args,**kwargs):
        m = models.UserInfo.objects.all()
        ser = UserinfoSerializer(instance=m,many=True)
        #單表的話這裡many = false
        return Response(ser.data)          

業務類

方式二補充:source不适合many to many,many to many需要自定義顯示

role = serializers.SerializerMethodField() #自定義顯示
def get_role(self,row):
     role_list = row.roles.all()
     ret = []
     for item in role_list:
         ret.append({'id':item.id,'title':item.title})
     return ret      

many to many

方式三:depth根本連表結構往深層取值

class UserinfoSerializer(serializers.ModelSerializer):
    usertype = serializers.CharField(source='get_usertype_display')
    class Meta:
        model = models.UserInfo
        #全部顯示
        fields = '__all__'
        depth = 1  #0~10之間
        #定制顯示
        # fields = ['id','username','type','gb']      

定制類

[{"id": 1, "usertype": 1, "username": "wrx", "password": "123", "group": {"id": 1, "title": "A組"}, "roles": [{"id": 2, "title": "老師"}, {"id": 3, "title": "醫生"}]}, 
{"id": 2, "usertype": 2, "username": "ylp", "password": "123", "group": {"id": 2, "title": "B組"}, "roles": [{"id": 3, "title": "醫生"}]}]      

取值結果

方式四:生成連結,即把上述類的group生成連結

class UserinfoSerializer(serializers.ModelSerializer):
    usertype = serializers.CharField(source='get_usertype_display')
    group = serializers.HyperlinkedIdentityField(view_name='grp',lookup_field='group_id',lookup_url_kwarg='pk')
    #name,pk值對應urls中的re-path
    class Meta:
        model = models.UserInfo
        #全部顯示
        fields = '__all__'
        depth = 1  #0~10之間
        #定制顯示
        # fields = ['id','username','type','gb']      

定制類

re_path(r'^(?P<version>[v1|v2]+)/group/(?P<pk>\d+)$',GroupView.as_view(),name='grp')
PS:這裡經曆了一個錯誤,如果配置了全局的版本控制(詳見版本控制配置),這裡要也要配置,否則會一直報錯
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "grp". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.      
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        m = models.UserInfo.objects.all()
        ser = UserinfoSerializer(instance=m,many=True,context={'request':request})
        return Response(ser.data)      

Views業務類

PS:執行個體這個定制類的時候要加要加context={'request':request}

實際調用的是另一個views類的url

class GroupSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserGroup
        fields = '__all__'

class GroupView(APIView):
    def get(self,request,*args,**kwargs):
        pk = kwargs.get('pk')
        obj = models.UserGroup.objects.filter(pk=pk).first()
        ser = GroupSerializer(instance=obj, many=False)
        t = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(t)      

上面re_path對應的定制類和業務類

方式五:三張表互相關聯的反向查找

class Course(models.Model):
    title = models.CharField(max_length=32,verbose_name='課程名稱')
    course_img = models.ImageField(verbose_name='課程圖檔',upload_to = "static/img/")
    course_choice = (
        (0, '入門級'),
        (1, '普通難度'),
        (2, '中等難度'),
        (3, '進階難度'),
    )
    level = models.IntegerField(verbose_name='課程難度',choices=course_choice,default=0)

    class Meta:
        verbose_name = '課程管理'
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.title

class CourseInfo(models.Model):
    why = models.CharField(verbose_name='課程描述',max_length=255)
    course = models.OneToOneField(to='Course',on_delete=models.DO_NOTHING,verbose_name='關聯課程')
    recommend_course = models.ManyToManyField(to='Course',verbose_name='推薦課程',related_name='rc')

    class Meta:
        verbose_name = '課程詳細'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '課程詳細:'+self.course.title

class Section(models.Model):
    num = models.IntegerField(verbose_name='章節')
    name = models.CharField(max_length=64,verbose_name='課程章節')
    course = models.ForeignKey(to='Course', on_delete=models.DO_NOTHING, verbose_name='關聯課程')

    class Meta:
        verbose_name = '課程章節'
        verbose_name_plural = verbose_name

    def __str__(self):
        return '課程章節'+self.course.title      

表結構

PS:第二張表與第一張表多對多并且單對單(這裡有個小知識點,同時多對多和單對單的時候有一張表要加related_name='rc'),第三張表與第一張表一對多,需求:通過序列化第二張表得到第一張表和第三張表的相關内容

class CourseinfoSerializer(serializers.ModelSerializer):
    #單對單,單對多,choice可以用這種方式,多對多不能使用
    title = serializers.CharField(source='course.title')
    level = serializers.CharField(source='course.get_level_display')
    #多對多需要自定義
    recommends = serializers.SerializerMethodField()
    def get_recommends(self, row):
        role_list = row.recommend_course.all()
        ret = []
        for item in role_list:
            ret.append({'id': item.id, 'title': item.title})
        return ret
    #3張表互相關聯的反向查找
    sections = serializers.SerializerMethodField()
    def get_sections(self, row):
        role_list = row.course.section_set.all()
        ret = []
        for item in role_list:
            ret.append({'num': item.num, 'name': item.name})
        return ret
    class Meta:
        model = models.CourseInfo
        # fields = '__all__'
        fields = ['id','title','level','why','recommends','sections']
        # depth = 2      

定制類

def retrieve(self,request, *args, **kwargs):
        ret = {'code': 1000, 'data': None}
        pk = kwargs.get('pk')
        try:
            obj = models.CourseInfo.objects.filter(course_id=pk)
            ser = sl.CourseinfoSerializer(instance=obj, many=True)
            ret['data'] = ser.data
        except Exception as e:
            ret['code'] = 1001
            ret['error'] = '擷取課程失敗'
        return Response(ret)      

業務類

PS:這實際是個類的get請求,re_path(r'^course/(?P<pk>\d+)$',views.CourseView.as_view({'get':'retrieve'})),

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

序列化-資料驗證,驗證title資料不能為空且必須以wrx開頭

class UserGroupSerializer(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'标題不能為空'},)
    def validate_title(self,value):
        if not value.startswith('wrx'):
            message = '标題必須以%s開頭'%'wrx'
            raise exceptions.ValidationError(message)
        else:
            return value      

定制類

class UserGroupView(APIView):
    def post(self,request,*args,**kwargs):
        src = ''
        res = UserGroupSerializer(data=request.data)
        if res.is_valid():
            print(res.validated_data)
            src = str(res.validated_data['title'])
        else:
            print(res.errors)
            src = str(res.errors)
        return HttpResponse(src)      

業務類

轉載于:https://www.cnblogs.com/wrxblog/p/10402580.html