2015-05-31 214 views
13

如果我有一個嵌套的串行:方面Django的REST框架

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

,我想訪問上下文嵌套串,我怎麼能做到這一點?據我所知,上下文不會傳遞給孩子。

我希望能夠實現每個用戶權限模型的領域,我覆蓋了get_fields()的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 

這對於經常串行工作,但背景下,並且因此當嵌套子代傳遞給get_fields()時請求和用戶不可用。序列化程序嵌套時,如何訪問上下文?

回答

8

好吧,我發現了一個工作解決方案。我用一個添加了上下文的SerializerMethodField替換了Parent類中的ChildSerializer賦值。這隨後被傳遞到get_fields方法在我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 

,並在我的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 

這似乎做工精細,孩子的字段在序列化時,我被丟棄撤銷對Child.c_nameParent.child閱讀權限

2

可以使用serialziers.ListField代替。 ListField自動將上下文傳遞給它的孩子。所以,這是你的代碼

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