1

У меня есть следующие модели:Serialize Родовые отношения с Джанго Rest Framework, с поддержкой записью

class TaggedItem(models.Model): 
    tag = models.SlugField() 
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) 
    object_id = models.PositiveIntegerField() 
    content_object = GenericForeignKey('content_type', 'object_id') 

Я пытаюсь сериализации этой модели таким образом, что я могу назначить объект контента через API конечной

до сих пор я сделал это:

class TaggedItemSerializer(serializers.ModelSerializer): 
    content_object = serializers.RelatedField(read_only=True) 

    class Meta: 
     model = TaggedItem 

Однако это неизменяемые. Если я удалю параметр read_only, я должен указать набор запросов для этого поля. Тем не менее, у меня есть много разных типов моделей для этих общих отношений. Кажется, я дублирую код, если я укажу все возможные типы моделей как в сериализаторе, так и в другом месте модели.

Я также мог установить объект контента через поля object_id и content_type, но когда я это сделаю, я получаю сообщение об ошибке.

Например:

{ 
    ... 
    object_id: 1, 
    content_type: 'auth.User' 
} 

возвращает 400 ответ с "detail": "JSON parse error - Expected object or value"

Как я могу сделать это content_object записываемой через апи ФПИ?

ответ

3

Переопределение .to_internal_value, .validate и .create методы, как это:

from django.apps import apps 

class TaggedItemSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = TaggedItem 
     read_only_fields = ('content_type', 'object_id', 'content_object') 

    def to_internal_value(self, data): 
     object_id = data.pop('object_id') 
     content_type = data.pop('content_type') 

     ret = super(ConfigCalcSerializer, self).to_internal_value(data) 

     ret['object_id'] = object_id 
     ret['content_type'] = content_type 

     return ret 

    def validate(self, data): 
     object_id = data.pop('object_id') 
     content_type = data.pop('content_type') 

     Model = apps.get_model(content_type) 

     try: 
      content_object = Model.objects.get(id=object_id) 
     except Model.DoesNotExist: 
      raise serializers.ValidationError('Not found') 
     else: 
      data['content_object'] = content_object 

     return data 

    def create(self, validate_data): 
     return TaggedItem.objects.create(**validate_data)