with rest_framework pip3 instalar framework espaƱol django python-3.x serialization django-rest-framework

django - instalar - pip3 install rest_framework



contexto en serializadores anidados Django resto framework (2)

Si tengo un serializador anidado:

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

Y quiero acceder al contexto en el serializador anidado, ¿cómo puedo hacer eso? Por lo que puedo decir, el contexto no se pasa al Niño.

Quiero poder implementar un modelo de permiso por usuario en los campos, para eso he anulado el método get_fields () 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

Lo que funciona para los serializadores normales, pero el contexto, y por lo tanto la solicitud y el usuario no están disponibles cuando el hijo anidado se pasa a get_fields (). ¿Cómo accedo al contexto cuando el serializador está anidado?


Ok he encontrado una solución de trabajo. Reemplacé la asignación de ChildSerializer en la clase Parent con un SerializerMethodField que agrega el contexto. Esto se pasa luego al método get_fields en mi 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

y en mi 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

Esto parece funcionar bien, y los campos del niño se descartan en el serializador cuando revoco los derechos de lectura en Child.c_name o en Parent.child


Puedes usar serialziers.ListField en serialziers.ListField lugar. ListField pasa el contexto automáticamente a su hijo. Entonces, aquí está tu código

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