1

Je le modèle suivant:sérialisation relations génériques avec Django Rest-cadre, avec le soutien d'écriture

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') 

Je suis en train de sérialisation ce modèle d'une manière que je peux affecter l'objet de contenu via un point de terminaison API

jusqu'à présent, je l'ai fait ceci:

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

    class Meta: 
     model = TaggedItem 

Toutefois, c'est en lecture seule. Si je supprime le paramètre read_only, je dois spécifier le jeu de requête pour le champ. Cependant, j'ai beaucoup de types de modèles différents pour cette relation générique. Il semble que je duplique du code si je spécifie tous les types de modèles possibles à la fois dans le sérialiseur et ailleurs dans le modèle.

Je pourrais également définir l'objet de contenu à travers les champs object_id et content_type, mais quand je fais cela, je reçois une erreur.

Par exemple:

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

renvoie une réponse 400 avec "detail": "JSON parse error - Expected object or value"

Comment puis-je faire ce content_object inscriptible via le api DRF?

Répondre

3

Remplacer les méthodes comme .to_internal_value, .validate et .create: ce

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)