2

다음과 같이 중첩 모델 Product을 정의했습니다. Product은 각각 Productlist에 속할 수 있습니다.Django Rest 프레임 워크 : validated_data에서 기본 키를 비순환 및 가져 오기

class Product(models.Model): 
    product_id = models.AutoField(primary_key=True) 
    product_name = models.CharField(max_length=50) 

class Productlist(models.Model): 
    productlist_id = models.AutoField(primary_key=True) 
    productlist_name = models.CharField(max_length=50) 
    product = models.ManyToManyField(Product, related_name='productlists') 

대응하는 시리얼은 다음과 같습니다

class ProductlistSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Productlist 
     fields = ('productlist_id', 'productlist_name',) 

class ProductSerializer(serializers.ModelSerializer): 
    productlists = ProductlistSerializer(many=True, required=False) 

    class Meta: 
     model = Product 
     fields = ('product_id', 'product_name', 'product lists') 

    def create(self, validated_data): 
     #some codes 

I POST 새로운 Product (url(r'^api/products/$', views.ProductEnum.as_view()가), I는 해당 제품 목록에 새로운 제품을 추가하기위한 제품 목록을 업데이 트하려는

. 내가 사용하는 것을 선호 JSON 파일은 다음과 같습니다

{ 
    "product_name": "product1" 
    "productlist": [ 
     { 
      "productlist_id": 1, 
      "productlist_name": "list1", 
     }, 
     { 
      "productlist_id": 2, 
      "productlist_name": list2" 
     } 
    ] 
} 

문제는 내가 validated_data에서 productlist_id을 얻을 수 있다는 것입니다. Django Rest Framework에서는 데이터를 비 직렬화하고 validated_data을 생성하기 위해 항상 to_internal_value()을 호출해야합니다. 일부 degugging 후, 나는 DRF의 코드를 확인하고 to_internal_value()에서 다음 조각을 찾을 수 :

def to_internal_value(self, data): 
    """ 
    Dict of native values <- Dict of primitive datatypes. 
    """ 
    if not isinstance(data, dict): 
     message = self.error_messages['invalid'].format(
      datatype=type(data).__name__ 
     ) 
     raise ValidationError({ 
      api_settings.NON_FIELD_ERRORS_KEY: [message] 
     }) 

    ret = OrderedDict() 
    errors = OrderedDict() 
    fields = [ 
     field for field in self.fields.values() 
     if (not field.read_only) or (field.default is not empty) 
    ] 

    for field in fields: 
     validate_method = getattr(self, 'validate_' + field.field_name, None) 
     primitive_value = field.get_value(data) 
     try: 
      validated_value = field.run_validation(primitive_value) 
      if validate_method is not None: 
       validated_value = validate_method(validated_value) 
     except ValidationError as exc: 
      errors[field.field_name] = exc.detail 
     except DjangoValidationError as exc: 
      errors[field.field_name] = list(exc.messages) 
     except SkipField: 
      pass 
     else: 
      set_value(ret, field.source_attrs, validated_value) 

    if errors: 
     raise ValidationError(errors) 

    return ret 

to_internal_value의 필드를주의하시기 바랍니다는 다음과 같은 조건을 만족시킬 수 없다에 대한 IntegerField(read_only=True) 무시했습니다

 fields = [ 
      field for field in self.fields.values() 
      if (not field.read_only) or (field.default is not empty) 
     ] 

{ 
    "product_name": "product1" 
    "productlist": [ 
     { 
      "productlist_name": "list1", 
     }, 
     { 
      "productlist_name": list2" 
     } 
    ] 
} 

어떻게 COU를 :

은 그래서 validated_data는 다음과 같은 데이터를해야합니다 제품 목록의 기본 키를 얻었습니까? 미리 감사드립니다!

답변

5

일부 파기 후에는 read_only 필드가 출력 프리젠 테이션 전용임을 알게되었습니다. 비슷한 질문은 linkDjango REST Framework입니다.

class ProductlistSerializer(serializers.ModelSerializer): 
    productlist_id = serializers.IntegerField(read_only=False) 

    class Meta: 
     model = Productlist 
     fields = ('productlist_id', 'productlist_name',) 
:

그래서 해결책은 다음과 시리얼에 read_only 필드를 무시한다