drf - ModelSerializers 직렬 화

원본 링크:http://www.cnblogs.com/Hades123/p/11487864.html
목차
  • drf - ModelSerializers 직렬 화
  • 프로젝트 준비
  • settings. py 설정
  • 경로
  • 다 중 시계 디자인
  • 표 관계 분석
  • 모델 생 성
  • 모델 직렬 화
  • 사용자 정의 모델 직렬 화 api / serializers. py
  • 보기에 서 api / views. py
  • 를 사용 합 니 다.
  • 모델 의 반 직렬 화
  • 사용자 정의 모델 반 직렬 화 api / serializers. py
  • 보기에 서 api / views. py
  • 를 사용 합 니 다.
  • 모델 서열 화기 (서열 화 와 반 서열 화 통합 *****
  • 하위 경로 api / urls. py
  • 사용자 정의 직렬 화기 api / serializers. py
  • 보기에 서 api / views. py
  • 를 사용 합 니 다.
  • 군 증 군 개
  • ListSerializer api/serializers.py
  • 보기 층 api / views. py


  • drf - ModelSerializers 직렬 화
    프로젝트 준비
    settings. py 설정
    #   rest_framework app
    INSTALLED_APPS = [
        # ...
        'rest_framework',
    ]
    
    #   mysql   
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'dg_proj',
            'USER': 'root',
            'PASSWORD': '123',
            'HOST': '127.0.0.1',
            'PORT': 3306
        }
    }
    
    #   pymysql  
    """
      __init__  
    import pymysql
    pymysql.install_as_MySQLdb()
    """
    
    #   
    LANGUAGE_CODE = 'zh-hans'
    TIME_ZONE = 'Asia/Shanghai'
    USE_I18N = True
    USE_L10N = True
    USE_TZ = False
    
    #                 
    STATIC_URL = '/static/'
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR, 'static'),
    )
    
    MEDIA_URL = '/media/'
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

    경로
    주 경로 urls. py
    from django.conf.urls import url, include
    from django.contib import admin
    from django.views import serve
    from django.conf import settings
    
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^api/', include('api.urls')),
        url(r'^media/(?P.*)', serve, {'document_root': settings.MEDIA_ROOT}),
    ]

    하위 경로 api / urls. py
    from django.conf.urls import url
    from . import views
    urlpatterns = [
        url(r'^books/$', views.BookAPIView.as_view()),
        url(r'^books/(?P\d+)/$', views.BookAPIView.as_view()),
    ]

    멀 티 탭 디자인
    표 관계 분석
    """
    Book :
        name, price, img, publish(  Publish ), authors(  Author ), is_delete, create_time
    
    Publish :
        name, address, is_delete, create_time
        
    Author :
        name, age, is_delete, create_time
        
    AuthorDetail :
        mobile, author(  Author ), is_delete, create_time
        
            is_delete, create_time     ,            ,        
    BaseModel :
        is_delete, create_time
    """

    표 관계 도:
    모델 생 성
    기본 표 utils / models. py
    from django.db import models
    
    class BaseModel(models.Model):
        is_delete = models.BooleanField(default=False)
        create_time = models.DateTimeField(auto_now_add=True, null=True)
        
        class Meta:
            #    ,          
            abstract = True

    모형 층 api / models. py
    from django.db import models
    from utils.models import BaseModel
    """
    relate_name:        ,    relate_name    ,         (    _set)
    db_constraint:   False       
    on_delete:    CASCSADE,                  
               DO_NOTHING,          ,        
               SET_NULL,          ,      null,   null   True
               SET_DEFAULT,          ,         ,   default     
               
                 : on_delete  ,      ,         
    db_table:         ,        
    verbose_name:  admin      ,              
    """
    
    # Create your models here.
    class Book(BaseModel):
        name = models.CharField(max_length=64)
        price = models.DecimalField(max_digits=6, decimal_places=2)
        img = models.ImageField(upload_to='icon', default='icon/default.png')
        publish = models.ForeignKey(to='Publish',
                                    null=True,
                                    related_name='books',
                                    db_constraint=False,
                                    on_delete=models.DO_NOTHING
                                    # on_delete=models.SET_NULL, null=True
                                    # on_delete=models.SET_DEFAULT, default=1
                                    )
        authors = models.ManyToManyField(to='Author',
                                         related_name='authors',
                                         db_constraint=False
                                         )
        #    model    ,         ,       read_only
        @property
        def publish_info(self):
            return {'name': self.publish.name, 'address': self.publish.address}
        
        @property
        def author_info(self):
            author_list = []
            
            for author in self.authors.all():
                detail = AuthorDetail.objects.filter(author_id=self.author.id)
                author_list.append({
                    'name': author.name,
                    'age': author.age,
                    #    : author.detail   ,         
                    # 'mobile': author.detail.mobile
                    'mobile': '  ' if not detail else author.detail.mobile
                })
                
            return author_list
            
    
        class Meta:
            db_table = "books"
            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()
    
        @property
        def mobile(self):
            return self.detail.mobile
        
        class Meta:
            db_table = 'author'
            verbose_name = '  '
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name
    
    
    class AuthorDetail(BaseModel):
        mobile = models.CharField(max_length=11)
        author = models.OneToOneField(to='Author',
                                      null=True,
                                      related_name='detail',
                                      db_constraint=False,
                                      on_delete=models.CASCADE
                                      )
        class Meta:
            db_table = 'detail'
            verbose_name = '    '
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return f"{self.author.name}   "
    
    
    class Publish(BaseModel):
        name = models.CharField(max_length=64)
        address = models.CharField(max_length=128)
    
        class Meta:
            db_table = 'publish'
            verbose_name = '   '
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.name

    모델 직렬 화
    계승 rest_framework.serializersModelSerializer
  • 사용자 정의 ModelSerializer 클래스 에 class Meta model 바 인 딩 직렬 화 된 모델 클래스 fields 를 플러그 인 방식 으로 직렬 화 필드
  • 를 지정 합 니 다.
  • 모델 류 에서 모델 표 의 방법 속성 을 통 해 연결 표 조회 필드 를 사용자 정의 한 다음 fields 에 삽입
  • 외부 키 필드 를 사용 하여 링크 조 회 를 완성 하면 직렬 화 깊이 eg:publish = PublishModelSerializer()
  • 사용자 정의 모델 직렬 화 api / serializers. py
    from rest_framework import serializers
    from . import models
    
    #      
    class PublishModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Publish
            fields = ('name', 'address')
            
    #      
    class AuthorModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Author
            fields = ('name', 'age', 'mobile')
            
    class BookModelSerializer(serializers.ModelSerializer):
        #        
        publish = PublishModelSerializer()
        authors = AuthorModelSerializer(many=True)
        
        """  :
         ModelSerializer      ,        fields     
            p_n = serializers.SerializerMethodField()
            def get_p_n(self, obj: models.Book):
                return obj.publish.name
        """
        class Meta:
            #          
            model = models.Book
            #     
            fields = ('name', 'price', 'img', 'publish', 'authors', 'publish_info', 'author_info')
            
            """  :
            fields = "__all__" :      
            exclude = ('id', 'is_delete'):      ,         
            depth = 1 :       (         )
            """

    보기에 서 api / views. py 사용 하기
    from rest_framework.views import APIView
    from utils.response import APIResponse
    from . import models, serializers
    
    class BookAPIView(APIView):
        def get(self, request, *args, **kwargs):
            #   
            pk = kwargs.get('pk')
            if pk:
                book_obj = models.Book.objects.filter(pk=pk, is_delete=False).first()
                if not book_obj:
                    return APIResponse(1, 'pk  ')
                
                book_ser = serializers.BookModelSerializer(book_obj)
                return APIResponse(0, 'ok', results=book_ser.data)
            book_obj_list = models.Book.objects.filter(is_delete=False).all()
            if not book_obj_list:
                return APIResponse(1,'    ')
            book_ser = serializers.BookModelSerializer(book_obj_list, many=True)
            return APIResponse(0,'ok',results=book_ser.data)

    모델 역 직렬 화
    계승 rest_framework.serializersModelSerializer
  • 사용자 정의 ModelSerializer 클래스 에 class Meta models 를 설정 합 니 다. 반 직렬 화 와 관련 된 모델 클래스 fields: 삽입 방식 으로 반 직렬 화 필드 extra 를 지정 합 니 다.kwargs: 시스템 검사 필드 의 규칙 을 정의 합 니 다
  • 부분 갈고리 와 전체 갈고리 완성 필드 의 복잡 한 검사 규칙
  • 을 사용자 정의 할 수 있 습 니 다.
  • create 와 update 를 다시 쓸 필요 가 없습니다. 추가 수정 을 완 료 했 습 니 다. ModelSerializer 류 는 이미 실현 되 었 습 니 다
  • 사용자 정의 모델 역 직렬 화 api / serializers. py
    from rest_framework import serializers
    from . import models
    
    class BookModelDeserializer(serializers.ModelSerializer):
        #         ,      fields 
        re_name = serializers.CharField(
            min_length=3, 
            required=True, 
            error_messages={
                'min_length': '   ',
                'required': '    '
            }
        )
        class Meta:
            model = models.Book
            fields = ('name', 're_name', 'price', 'publish', 'authors')
            extra_kwargs = {
                'name':{
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '   ',
                        'required': '    '
                    }
                },
                #           required False,             
                'publish':{
                    'required': True,
                    'error_messages':{
                        'required': '    '
                    }
                },
                'authors':{
                    'required': True,
                    'error_messages':{
                        'required': '    '
                    }
                }
            }
            
            #        
            #     
            def validate_name(self, value):
                if 'sb' in value:
                    raise serializers.ValidationError('        ')
                return value
            
            def validate(self, attr):
                name = attr.get('name')
                re_name = attr.get('re_name')
                publish = attr.get('publish')
                if name != re_name:
                    raise serializers.ValidationError(
                        {'re_name': '       '}
                    )
                if models.Book.objects.filter(name=name, publish=publish):
                    raise serializers.ValidationError(
                        {'book': '     '}
                    )
                    
                return attr 

    보기에 서 api / views. py 사용 하기
    from rest_framework.views import APIView
    from utils.response import APIResponse
    from . import models, serializers
    
    class BookAPIView(APIView):
        def post(self, request, *args, **kwargs):
            book_ser = serializers.BookModelDeserializer(data=request.data)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                results = serializers.BookModelDeserializer(book_obj).data
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', resultes=book_ser.errors)

    모델 직렬 화 기 (직렬 화 와 반 직렬 화 통합 *****하위 경로 api / urls. py
    from django.conf.urls import url
    from . import views
    urlpatterns = [
        url(r'^v2/books/$', views.BookV2APIView.as_view()),
        url(r'^v2/books/(?P.*)/$', views.BookV2APIView.as_view()),
    ]

    사용자 정의 직렬 화 기 api / serializers. py
    from rest_framework import serializers
    from . import models
    
    class BookV2ModelSerializer(serializers.ModelSerializer):
        re_name = serializers.CharField(
            min_length=3, 
            required=True, 
            write_only=True,  #        
            error_messages={
                'min_length': '   ',
                'required': '    '
            }
        )
        
        class Meta:
            model = models.Book
            fields = ('name', 're_name', 'price', 'img', 'publish', 'publish_info', 'authors', 'authors_info')
             extra_kwargs = {
                'name':{
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '   ',
                        'required': '    '
                    }
                },
                #           required False,                 ,            
                'publish':{
                    'required': True,
                    'write_only': True,
                    'error_messages':{
                        'required': '    '
                    }
                },
                'authors':{
                    'required': True,
                    'write_only': True,
                    'error_messages':{
                        'required': '    '
                    }
                },
            }
                
            #        
            #     
            def validate_name(self, value):
                if 'sb' in value:
                    raise serializers.ValidationError('        ')
                return value
            
            def validate(self, attr):
                name = attr.get('name')
                re_name = attr.get('re_name')
                publish = attr.get('publish')
                if name != re_name:
                    raise serializers.ValidationError(
                        {'re_name': '       '}
                    )
                if models.Book.objects.filter(name=name, publish=publish):
                    raise serializers.ValidationError(
                        {'book': '     '}
                    )
                    
                return attr
    

    보기에 서 api / views. py 사용 하기
    class BookV2APIView(APIView):
        def get(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            #   
            if pk:
                book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
                if not pk:
                    return APIResponse(1, 'pk  ')
                book_ser = serializers.BookV2ModelSerializer(book_obj)
                return APIResponse(0, 'ok', results=book_ser.data)
    
            #   
            book_obj_list = models.Book.objects.filter(is_delete=False).all()
            if not book_obj_list:
                return APIResponse(1, '    ')
            book_ser = serializers.BookV2ModelSerializer(book_obj_list, many=True)
            return APIResponse(0, 'ok', results=book_ser.data)
    
        #     
        def post(self, request, *args, **kwargs):
            book_ser = serializers.BookV2ModelSerializer(data=request.data)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj).data
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', results=book_ser.errors)
    
        #       
        def patch(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
    
            if not pk:
                return APIResponse(1, 'pk  ')
    
            try:
                book_obj = models.Book.objects.get(is_delete=False, pk=pk)
            except:
                return APIResponse(1, 'pk   ')
    
            book_ser = serializers.BookV2ModelSerializer(instance=book_obj, data=request.data, partial=True)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj)
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', results=book_ser.errors)
    
            #       
    
        def put(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            if not pk:
                return APIResponse(1, 'pk  ')
    
            try:
                book_obj = models.Book.objects.get(is_delete=False, pk=pk)
            except:
                return APIResponse(1, 'pk   ')
    
            book_ser = serializers.BookV2ModelSerializer(instance=book_obj, data=request.data)
            if book_ser.is_valid():
                book_obj = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj).data
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', results=book_ser.errors)
    
        #   
        def delete(self, request, *args, **kwargs):
            #    /books/(pk)/
            #    /books/        pks => request.data
            pk = kwargs.get('pk')
            if pk:
                pks = [pk, ]
            else:
                pks = request.data.get('pk')
    
            if not pks:
                return APIResponse(1, 'pk  ')
            book_obj_list = models.Book.objects.filter(is_delete=False, pk__in=pks)
            if not book_obj_list.update(is_delete=True):
                return APIResponse(1, '    ')
            return APIResponse(0, '    ')
        

    군 증 군 개
    ModelSerializer 에 서 는 기본적으로 여러 대상 을 한꺼번에 반 직렬 화 할 수 없고 한 대상 만 반 직렬 화 할 수 있 기 때문에 그룹 변경 과 군 증 기능 을 실현 할 수 없 기 때문에 Meta 에 list 를 설정 해 야 합 니 다.serializer_class:
  • 먼저 ListSerializer 글꼴 을 사용자 정의 해 야 합 니 다. 여러 대상 을 역 직렬 화 할 수 있 습 니 다. update 방법 을 다시 써 서 이 종 류 를 list 에 연결 할 수 있 습 니 다.serializer_class
  • 재 업데이트 방법 에서 인 스 턴 스 를 통 해 업데이트 할 대상 을 받 고 vaidateddata 바 인 딩 업데이트 할 데 이 터 를 업데이트 한 후 인 스 턴 스 를 되 돌려 줍 니 다
  • 메모: 업데이트 대상 과 업데이트 할 데 이 터 는 일일이 대응 해 야 합 니 다.
    ListSerializer api/serializers.py
    from rest_framework import serializers
    from . import models
    
    class BookListSerializer(serializers.ListSerializer):
        def update(self, instance, validated_data):
            for ind, obj in enumerate(instance):
                for attr, value in validated_data[ind].items():
                    if hasattr(obj, attr):
                        set(obj, attr, value)   
                obj.save()
            return instance
        
    class BookV2ModelSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = ('name', 're_name', 'price', 'img', 'publish', 'publish_info', 'authors', 'authors_info')
            list_serializer_class = BookListSerializer
             extra_kwargs = {
                'name':{
                    'min_length': 3,
                    'error_messages': {
                        'min_length': '   ',
                        'required': '    '
                    }
                },
                'publish':{
                    'required': True,
                    'write_only': True,
                    'error_messages':{
                        'required': '    '
                    }
                },
                'authors':{
                    'required': True,
                    'write_only': True,
                    'error_messages':{
                        'required': '    '
                    }
                },
            }
                
            def validate_name(self, value):
                if 'sb' in value:
                    raise serializers.ValidationError('        ')
                return value
            
            def validate(self, attr):
                name = attr.get('name')
                publish = attr.get('publish')
                if models.Book.objects.filter(name=name, publish=publish):
                    raise serializers.ValidationError(
                        {'book': '     '}
                    )    
                return attr 

    보기 층 api / views. py
    class BookV2APIView(APIView):
        #   
        def post(self, request, *args, **kwargs):
            #          
            request_data = request.data
            if isinstance(request_data, dict):
                data = [request_data, ]
            elif isinstance(request, list):
                data = request_data
            else:
                return APIView(1, '      ')
            
            book_ser = serializers.BookV2ModelSerializer(data=data, many=True)
            if book_ser.is_valid():
                book_obj_list = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj_list, many=True).data
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', results=book_ser.errors)
           
        #     
        def put(self, request, *args, **kwargs):
            pk = kwargs.get('pk')
            request_data = request.data
            #       
            if pk:
                if not isinstance(request_data, dict):
                    return APIResponse(1, '      ')
                pks = [pk, ]
                data = [request_data, ]
            elif isinstance(request_data, list):
                try:
                    pks = []
                    for dic in request_data:
                        pks.append(dic.pop('pk'))
                        data = request_data
                 except:
                     return APIResponse(1, '      ')
            else:
                return APIResponse(1, '      ')
    
            #                      (             )
            book_obj_list = []
            filter_data = []
            for ind, pk in enumerate(pks):
                book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
                if book_obj:
                    book_obj_list.append(book_obj)
                    filter_data.append(data[ind])
    
            #            
            book_ser = serializers.BookV2ModelSerializer(instance=book_obj_list, data=filter_data, many=True)
            if book_ser.is_valid():
                book_obj_list = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj_list, ).data
                return APIResponse(0, 'ok', results=results)
            else:
                return APIResponse(1, '    ', results=book_ser.errors)
            
        #     
        def patch(self, request, *args, **kwargs):
            """
               /books/(pk)/  data  {"name": "new_name", ...}
               /books/  data  [{"pk": 1, "name": "new_name", ...}, ...,{"pk": n, "name": "new_name", ...}]
              :
            pks = [1, ..., n] => book_query => instance
            data = [{"name": "new_name", ...}, ..., {"name": "new_name", ...}] => data
            """
            pk = kwargs.get('pk')
            request_data = request.data
            #       
            if pk:
                if not isinstance(request_data, dict):
                    return APIResponse(1, '      ')
                pks = [pk, ]
                data = [request_data, ]
            elif isinstance(request_data, list):
                try:
                    pks = []
                    for dic in request_data:
                        pks.append(dic.pop('pk'))
                        data = request_data
                 except:
                     return APIResponse(1, '      ')
            else:
                return APIResponse(1, '      ')
    
            #                      (             )
            book_obj_list = []
            filter_data = []
            for ind, pk in enumerate(pks):
                book_obj = models.Book.objects.filter(is_delete=False, pk=pk).first()
                if book_obj:
                    book_obj_list.append(book_obj)
                    filter_data.append(data[ind])
    
            #            
            book_ser = serializers.BookV2ModelSerializer(instance=book_obj_list, data=filter_data, many=True)
            #       
            if book_ser.is_valid():
                book_obj_list = book_ser.save()
                results = serializers.BookV2ModelSerializer(book_obj_list, ).data
                return APIResponse(0, 'ok', results=results)
            #       
            else:
                return APIResponse(1, '    ', results=book_ser.errors)

    다음으로 전송:https://www.cnblogs.com/Hades123/p/11487864.html

    좋은 웹페이지 즐겨찾기