#32423: Support for extra related lookup definitions of a field.
-------------------------------------+-------------------------------------
               Reporter:  CloudCode  |          Owner:  nobody
  Hungary                            |
                   Type:  New        |         Status:  new
  feature                            |
              Component:  Database   |        Version:  3.1
  layer (models, ORM)                |       Keywords:  ForeignKey,
               Severity:  Normal     |  ManyToOneRel
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 When adding ForeignKeys to models one have the option to specify related
 name. It would be useful, to be able to specify multiple related names,
 and assign different queries for each of those. See the example below:

 There are products, with some master data, like SKU and some variations of
 that product in different contexts (profiles) like name and description.

 {{{
 class Product:
     sku = models.CharField()

 class ProductProfileGroup:
     is_default = models.BooleanField()

 class ProductProfile:
     group = models.ForeignKey(to='ProductProfileGroup',
 related_name='profiles')
     product = models.ForeignKey(to='Product', related_name='profiles')
     name = models.CharField()
     description = models.CharField()
 }}}


 If I were to retrieve all information of a product, with a specific
 profile group, I have to write the below code:
 {{{
 Product.objects.annotate(
     name=F('profiles__name'),
     description=F('profiles__description'),
 ).filter(profiles__group_id=1)

 """
 select product.sku, product_profile.name, product_profile.description
 from product
 join product_profile on product_profile.product_id = product.id
 where product_profile.group_id = 1
 """
 }}}

 This is a bit cumbersome, hard to read because of those plurals. My
 suggested approach would be something like:

 {{{
 def get_selected_profile():
     # maybe use settings, or some request context like
 https://pypi.org/project/django-currentuser/
     return
 
Q(product_profile_group_id=get_current_user().preferred_product_profile_group_id)

 class ProductProfile:
     product = models.ForeignKey(to='Product', related_name='profiles',
 related_queries={
         'default_profile': Q(is_default=True),
         'selected_profile': get_selected_profile,
     })

 # the same annotation, much more readable:
 Product.objects.annotate(
     name=F('default_profile__name'),
 )

 """
 select product.sku, product_profile.name, product_profile.description
 from product
 join product_profile on product_profile.product_id = product.id and
 product_profile.is_default is true
 """

 Product.objects.annotate(
     name=F('selected_profile__name'),
 )

 """
 select product.sku, product_profile.name, product_profile.description
 from product
 join product_profile on product_profile.product_id = product.id and
 product_profile.product_profile_group_id = 1
 """
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/32423>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/060.8ba3ec7189064e46a626bdaee8b359b6%40djangoproject.com.

Reply via email to