Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

255
Visualizações
Acceso a instancias particulares en un DRF ListSerializer

Actualmente tengo estos modelos de Django que quiero serializar:

 class Result(models.Model): ... routes = models.ManyToManyField(Route) ... class Route(models.Model): ... class Feature(models.Model): result = models.ForeignKey(Result) route = models.ForeignKey(Route) description = models.TextField()

Y los serializadores DRF se ven así:

 class ResultSerializer(serializers.ModelSerializer): ... route = RouteSerializer(many=True, required=False) ... class Meta: model = Result fields = '__all__' class FeatureField(serializers.CharField): """ Accepts text in the writes and looks up the correct feature for the reads. """ def get_attribute(self, obj): # We pass the object instance onto `to_representation`, not just the field attribute. return obj def to_representation(self, obj): try: search_result = self.root.child.instance # FIXME: this is the problem. feature = Feature.objects.get(route=obj.id, search_result=search_result) feature = feature.description except Feature.DoesNotExist: feature = None return feature class RouteSerializer(serializers.ModelSerializer): description = FeatureField(required=False) class Meta: model = Route fields = '__all__'

El problema al que me refiero en el código es que esto funciona cuando estoy usando un ResultSerializer con solo una instancia, pero si quiero serializar varias instancias en una vista de lista, por ejemplo, y paso un conjunto de consultas al serializador, DRF aplica un ListSerializer encima y ahora self.root.instance es una lista de los registros, y no puedo acceder a los resultados individuales que llaman al RouteSerializer anidado, por lo que no puedo recuperar la característica correcta.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Salté al código DRF y finalmente entendí lo que estaba pasando:

Si serializa solo una instancia con serializer = ResultSerializer(result) , serializer.instance contiene solo esta única instancia de result particular, y los serializadores y campos anidados pueden acceder a ella sin problemas usando self.root.instance .

Ahora, si serializa varias instancias, como lo hace la acción de list predeterminada, lo que realmente sucede es lo siguiente:

  1. se realiza una llamada como serializer = ResultSerializer(queryset, many=True)
  2. tener many=True en los argumentos activa el método many_init() de BaseSerializer , y esto crea un solo ResultSerializer con el conjunto de consultas como instancia, por lo que serializer.instance es el conjunto de consultas.
  3. a continuación, crea un solo ListSerializer que extiende ResultSerializer y su instancia nuevamente es el conjunto de consultas.

Lo que me equivoqué es pensar que ListSerializer crearía ResultSerializer separados para cada elemento en el conjunto de consultas.

La forma en que finalmente resolví esto es anular el método ResultSerializer.to_representation() :

 class ResultSerializer(serializers.ModelSerializer): def to_representation(self, instance): # When we call Results with many=True, the serializer.instance is a list with several records, # we can't know which particular instance is spawning the nested serializers so we add it here. self._instance = instance return super(ResultSerializer, self).to_representation(instance)

y finalmente consumirlo en FeatureField así:

 class FeatureField(serializers.CharField): """ Accepts text in the writes and looks up the correct feature for the reads. """ def get_attribute(self, obj): # We pass the object instance onto `to_representation`, not just the field attribute. return obj def to_representation(self, obj): # If the root is a ListSerializer, retrieve the right Result instance using the `_instance` attribute. try: if isinstance(self.root, serializers.ListSerializer): search_result = self.root.child._instance else: search_result = self.root.instance feature = Feature.objects.get(route=obj.id, search_result=search_result) feature = feature.pickup_instructions except Feature.DoesNotExist: feature = None return feature
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Assistente virtual