2015-05-31 23 views
13

Nếu tôi có một serializer lồng nhau:bối cảnh trong serializers lồng nhau django còn lại khung

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

Và tôi muốn truy cập vào ngữ cảnh trong serializer lồng nhau, làm thế nào tôi có thể làm điều đó? Theo như tôi có thể nói, ngữ cảnh không được truyền cho đứa trẻ.

Tôi muốn để có thể thực hiện một mô hình cho phép mỗi người dùng trên các lĩnh vực, cho rằng tôi ghi đè các get_fields() phương pháp của 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 

nào làm việc cho serializers thường xuyên, nhưng bối cảnh, và do đó yêu cầu và người dùng không có sẵn khi con lồng nhau được chuyển tới get_fields(). Làm thế nào để tôi truy cập vào bối cảnh khi serializer được lồng nhau?

Trả lời

8

Ok tôi đã tìm được giải pháp làm việc. Tôi đã thay thế nhiệm vụ ChildSerializer trong lớp Parent bằng một SerializerMethodField để thêm ngữ cảnh. Điều này sau đó được truyền cho phương thức get_fields trong CustomModelSerializer tôi:

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 

và trong CustomModelSerializer tôi:

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 

Điều này dường như làm việc tốt, và các lĩnh vực của đứa trẻ sẽ bị loại bỏ trong serializer khi tôi hoặc thu hồi read-quyền trên Child.c_name hoặc trên Parent.child

2

Bạn có thể sử dụng serialziers.ListField để thay thế. ListField tự động chuyển ngữ cảnh cho con của nó. Vì vậy, đây là mã của bạn

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') 
Các vấn đề liên quan