2015-05-31 33 views
13

Se ho un serializzatore nidificato:contesto in serializzatori nidificate Django resto quadro

class ChildSerializer(ModelSerializer): 
    class Meta: 
     fields = ('c_name',) 
     model = Child 


class ParentSerializer(ModelSerializer): 

    child = ChildSerializer(many=True, read_only=True) 

    class Meta: 
     model = Parent 
     fields = ('p_name', 'child') 

e voglio accedere al contesto nel serializzatore nidificato, come posso farlo? Per quanto posso dire, il contesto non è passato al bambino.

Voglio essere in grado di implementare un modello di autorizzazione per utente sui campi, per questo ho sovrascritto le get_fields() il metodo del ModelSerializer:

def get_fields(self): 
    fields = super().get_fields() 
    .... 
    for f in fields: 
     if has_rights(self.context['request'].user, f, "read"): 
      ret_val[f] = fields[f] 
    .... 
    return ret_val 

che lavora per serializzatori regolari, ma il contesto, e quindi la richiesta e l'utente non sono disponibili quando il figlio nidificato viene passato a get_fields(). Come accedo al contesto quando il serializzatore è annidato?

risposta

8

Ok ho trovato una soluzione funzionante. Ho sostituito l'assegnazione ChildSerializer nella classe Parent con un SerializerMethodField che aggiunge il contesto. Questo viene poi passato al metodo get_fields nel mio CustomModelSerializer:

class ChildSerializer(CustomModelSerializer): 
    class Meta: 
     fields = ('c_name',) 
     model = Child 


class ParentSerializer(CustomModelSerializer): 

    child = serializers.SerializerMethodField('get_child_serializer') 

    class Meta: 
     model = Parent 
     fields = ('p_name', 'child') 

    def get_child_serializer(self, obj): 
     serializer_context = {'request': self.context.get('request') } 
     children = Child.objects.all().filter(parent=obj) 
     serializer = ChildSerializer(children, many=True, context=serializer_context) 
     return serializer.data 

e nel mio CustomModelSerializer:

class CustomModelSerializer(rest_serializer_classes.HyperlinkedModelSerializer): 

    def __init__(self, *args, **kwargs): 
     """ 
      Make sure a user is coupled to the serializer (needed for permissions) 
     """ 
     super().__init__(*args, **kwargs) 
     if not self.context: 
      self._context = getattr(self.Meta, 'context', {}) 
     try: 
      self.user = self.context['request'].user 
     except KeyError: 
      self.user = None 


    def get_fields(self): 
     ret = OrderedDict() 

     if not self.user: 
      print("No user associated with object") 
      return ret 

     fields = super().get_fields() 

     # Bypass permission if superuser 
     if self.user.is_superuser: 
      return fields 

     for f in fields: 
      if has_right(self.user, self.Meta.model.__name__.lower(), f, "read"): 
       ret[f] = fields[f] 

     return ret 

Questo sembra funzionare bene, e campi del bambino vengono scartati nel serializzatore quando ho neanche revocare read-diritti sul Child.c_name o Parent.child

2

È possibile utilizzare serialziers.ListField invece. ListField passa automaticamente il contesto al suo figlio. Quindi, ecco il tuo codice

class ChildSerializer(ModelSerializer): 
    class Meta: 
     fields = ('c_name',) 
     model = Child 


class ParentSerializer(ModelSerializer): 
    child = serializers.ListField(read_only=True, child=ChildSerializer()) 

    class Meta: 
     model = Parent 
     fields = ('p_name', 'child') 
Problemi correlati