• Jobs
  • About Us
  • Jobs
    • Home
    • Jobs
    • Courses and challenges
  • Businesses
    • Home
    • Post vacancy
    • Our process
    • Pricing
    • Assessments
    • Payroll
    • Blog
    • Sales
    • Salary Calculator

0

170
Views
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 3 years ago · Santiago Trujillo
1 answers
Answer question

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 3 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Our process Sales
Legal
Terms and conditions Privacy policy
© 2025 PeakU Inc. All Rights Reserved.

Andres GPT

Show me some job opportunities
There's an error!