Friday, December 27, 2019

Re: Overriding Prefetched objects in Serialization

Hi Barddes,

Bc of you alter model, so let try to command migration, makemigration.




On Fri, Dec 27, 2019, 00:46 Cesar Bueno <barddes@gmail.com> wrote:
Hi!

I'm having trouble overriding some prefetched data, I hope someone can help me here. I'll try to explain my issue with the examples provided from the Docs (https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related). The base models from the examples below were taken from there.

So... Let's suppose I'm running a Pizzeria, and I have the following models:

class Topping(models.Model):
   
name = models.CharField(max_length=30)

class Pizza(models.Model):
   
name = models.CharField(max_length=50)
   
toppings = models.ManyToManyField(Topping)

My goal is to fetch my Pizzas, serialize them, and store it into an ElasticSearch cluster.

If I want to fetch all my Pizzas from DB, I run the following:

pizzas = Pizza.objects.all()

But also with the Pizza object, I want to (pre)fetch all toppings. In that case, I should run:

Pizza.objects.all().prefetch_related('toppings')

This works great, but I might want to add some filters to the toppings fetched for any reason (They are out of stock, for example). I can do this by adding the field in_stock to my model Topping:

class Topping(models.Model):
   
name = models.CharField(max_length=30)
    in_stock
= models.BooleanField()

With this Topping model, I can use the Prefetch object:

pizzas = Pizza.objects.all().prefetch_related(
                       
Prefetch('toppings', queryset=Topping.objects.filter(in_stock=True)
                   
)

Until now everything works as expected (even the serialization). But my problem begins when I try to do the same stock control with the Pizza object. Just like I did with Topping, I will also add the in_stock field to the Pizza Model. The new Pizza Model then is:

class Pizza(models.Model):
   
name = models.CharField(max_length=50)
   
toppings = models.ManyToManyField(Topping)
    in_stock
= models.BooleanField()

If my Pizza is out of stock, I don't need to know which toppings are available and which are not. After the query execution I expected a list of all Pizzas and, if the pizza is available, the list of Toppings available for each pizza. I wasn't able to make this behavior using the Prefetch object. As a workaround, I tried the following:

pizzas = Pizza.objects.all().prefetch_related(
                       
Prefetch('toppings', queryset=Topping.objects.filter(in_stock=True)
                   
)

for pizza in pizzas:
   
if not pizza.in_stock:
      pizza
.toppings = []    

Running the following, Python/Django raised an error saying that I should use this instead:

pizza.toppings.set([])

But even when I the code above (that runs without raising an error), every time I serialize my pizza object, the full toppings list gets serialized instead of the empty array previously setted.
I am using an HyperlinkedModelSerializer to serialize my data.

Can anyone help me? How can I serialize the empty array instead of the list retrieved from the db?

Thanks in advance

Cesar



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/ec53999f-2a9f-469f-8c1e-36db8916d541%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/CAP5HUWo1v6uj5Fze05ULiig6MHcLMju2KC-4NZ%2Ba9tF%2BCkJdSg%40mail.gmail.com.

No comments:

Post a Comment