Django: checking for an object in a query set (IF ELSE)

PROBLEM: The problem I am facing is getting the option price in the Choice model. This is due to the fact that depending on which other Parameters are also in the same basket, different prices will be used to generate the total quantity. I need help with a set of queries that gives me the Option price, if the option has effector_option , which itself is in the same basket, is used, otherwise use Variation only with the specified option fields.

The TempName App model consists of:

class Section(models.Model): title = models.CharField(max_length=20) description = models.CharField(max_length=100) temp = models.ForeignKey(TempName, null=False) def __str__(self): return self.title def get_options(self): return self.option_set.all() class Option(models.Model): name = models.CharField(max_length=120) section = models.ForeignKey(Section, null=False) def __str__(self): return self.name def get_variations(self): return self.variation_set.all() class Variation(models.Model): name = models.CharField(max_length=60, blank=True, unique=True) price = models.DecimalField(max_digits=5, decimal_places=2) option = models.ForeignKey(Option, null=False) effector_option = models.ForeignKey(Option, null=True, blank=True, related_name='option_effected') def __str__(self): return self.name 

One page can have many sections . Each Section can contain many Parameters , which will be later selected by the user. The selected option will be sent to the basket, which will be used to create the total price.

In the Variation model, the field parameter simply tells me which parameter the Variation belongs to. The effector_option field inside the Variation model will be used by the cart.

The user will be allowed to select any number of Parameters , however, depending on the Parameters parameter selected by the user, other parameters may display Variation price, where the effector_option parameter was previously selected.

The application model for mobile devices consists of:

 class Cart(models.Model): owner = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True) creation_date = models.DateTimeField(verbose_name='creation date') checked_out = models.BooleanField(default=False, verbose_name='checked out') class Meta: verbose_name = 'cart' verbose_name_plural = 'carts' ordering = ('-creation_date',) def __str__(self): return unicode(self.creation_date) def get_selections(self): return self.selection_set.all() class Selection(models.Model): cart = models.ForeignKey(Cart) option = models.ForeignKey(Option) @property def price(self): return 10 

The cart may contain several options that the user has selected. Each Selection will have a price property that can be used to show the user the price of this individual choice, depending on which other option is also in the same basket.

WHAT I EXCLUDE:

Get all options options. Then swipe through each variation and see if Variation.effector_option is contained within the same Basket . If this displays this price, otherwise display the price within the variation where Variation.effector_option is null / not set.

I found that more than 26 queries are called in the basket for each selection . Does this db schema require more normalization or is it good enough for this simple project?

+6
source share
1 answer

I found that for each selection in the basket, more than 26 queries are called. Does this db schema require more normalization or is it good enough for this simple project?

I will bite because I believe the solution to this is software development. The problem here is not normalization, and it is not Django. How did you decide to organize the problem. I assume that you have fallen into several traps, which I will tell about when we go. First, give some definitions right here, starting with your own ...

  • Section - option group
  • Option - price
  • Variation - an attempt to simulate parameters that affect other parameters.

Now do we have this problem? Some of my Option options can be used with other Option options and influence the price! Chaos! We need Variation provide meta rules for their interaction. More inquiries! More logic! May be,...

Trap 1

Providing a way to display information on the screen of your data model

I guess here, but using the words Section and Option makes me feel like you're organizing a screen, not a database. Most often, companies have models that look like this:

  • Product - We are selling something ( name , base_price , options , option_sets )
  • OptionSet - Groups of options that come together as a package! Think about saving! ( name , group , options , price , optionset_exclusions , option_exclusions )
  • Option - parameters a la carte ( name , group , price )
  • Purchase - Who wants to buy ( Product , options , optionsets )

Now you can say: "How about my sections!" Sections can be as easy as hanging up a piece of metadata with OptionSet and Option called group with type CharField . When rendering in a template, you can group parameters / options together group . You can use exclusions so that people cannot select conflicting Option and optionsets for Product . Now all this shebang can be folded on the page with just three requests (if used correctly, prefetch_related ), and the selected options / optionsets can simply be added together to get a deterministic price.

Trap 2

Denying how you want it to work prevents it from working at all

Now, before you launch the volley, "This can't work for me, I'm a snowflake!" (here it was a long time ago). Often we find that the way we want to work something prevents it from working.

Older unix chapters used to discuss the virtues of Consistency, Simplicity, and Completeness. The consensus is that Simplicity is best, even if it is not complete or consistent. To achieve completeness, your original solution uses complexity. It is a trap! (Thanks Admiral Akbar)

eg. this is how my / my client business works, so it should work that way.

Software is cheaper / easier to write when we look for ways to achieve simplicity. Sometimes this means changing the organization to meet software limitations.

I can present the retort to the foregoing, which says

Option 1 will give you a 10% discount on option 2. You only have static prices!

This can be modeled in the diagram above, where the total price is equal to Option 1 Price +.9 (Option 2 prices). In this case, we just took the concept of Variation and made it data instead of behavior. Much easier. It is more flexible. I mean, you can make a complex 3D volume calculation at prices and just bring the result into your product schema. There are more problems to consider ...

I do not want to do this configuration manually!

Write yourself a Django management command that imports from a spreadsheet.

What if prices or the relationship between options change?

In the product / price scheme itself, there is the concept of _spec as Option_spec , which allows you to fix the Point In Time purchase conditions. _spec entries _spec connected to the Purchase at the time of purchase. This allows you to change Option and OptionSet without changing all connected past purchases.

and the list goes on ...

The fact is that all the problems you can dream of have simple solutions if you are smart and open-minded.

+3
source

Source: https://habr.com/ru/post/1013314/


All Articles