Django ORM annotation with tree traversal












0














I'm using the django-mptt library to make categories for my project. The model is pretty simple:



from django.db import models
from mptt.models import MPTTModel, TreeForeignKey

class Category(MPTTModel):
name = models.CharField('Name', max_length=100, unique=True)
color = models.CharField(
'Color',
max_length=100,
blank=True,
null=True
)
parent = TreeForeignKey(
'self',
on_delete=models.CASCADE,
null=True,
blank=True,
related_name='children'
)

class MPTTMeta:
order_insertion_by = ['name']


Category color is optional and should be inherited from parent, if undefined. So just to illustrate:



Main Category 1 (red) -> Subcategory 1
-> Subcategory 2 (blue)
-> Subcategory 3 (yellow) -> Subcategory 4


Subcategory 4 has no color defined and it inherits subcategory 3 color (yellow).
Subcategory 1 inherits color from Main Category 1 (blue), etc.



In my view i have the root category and then build a tree using get_descendants(include_self=True).
How can i annotate color for each category of <TreeQuerySet>?



For one model i have the following method:



@property
def inherited_color(self):
if self.color:
return self.color
return (self
.get_ancestors(ascending=True, include_self=True)
.filter(color__isnull=False)
.values_list('color', flat=True)
.first())


But when this method is called for a list of categories it results in a lot of database queries!



This is an example from django shell:



>>> category
<Category: 3>
>>> category.color is None
True
>>> category.get_family().values_list('name', 'color')
<TreeQuerySet [('1', '#51DCFF'), ('2', None), ('3', None)]>
>>> category.inherited_color
'#51DCFF'









share|improve this question





























    0














    I'm using the django-mptt library to make categories for my project. The model is pretty simple:



    from django.db import models
    from mptt.models import MPTTModel, TreeForeignKey

    class Category(MPTTModel):
    name = models.CharField('Name', max_length=100, unique=True)
    color = models.CharField(
    'Color',
    max_length=100,
    blank=True,
    null=True
    )
    parent = TreeForeignKey(
    'self',
    on_delete=models.CASCADE,
    null=True,
    blank=True,
    related_name='children'
    )

    class MPTTMeta:
    order_insertion_by = ['name']


    Category color is optional and should be inherited from parent, if undefined. So just to illustrate:



    Main Category 1 (red) -> Subcategory 1
    -> Subcategory 2 (blue)
    -> Subcategory 3 (yellow) -> Subcategory 4


    Subcategory 4 has no color defined and it inherits subcategory 3 color (yellow).
    Subcategory 1 inherits color from Main Category 1 (blue), etc.



    In my view i have the root category and then build a tree using get_descendants(include_self=True).
    How can i annotate color for each category of <TreeQuerySet>?



    For one model i have the following method:



    @property
    def inherited_color(self):
    if self.color:
    return self.color
    return (self
    .get_ancestors(ascending=True, include_self=True)
    .filter(color__isnull=False)
    .values_list('color', flat=True)
    .first())


    But when this method is called for a list of categories it results in a lot of database queries!



    This is an example from django shell:



    >>> category
    <Category: 3>
    >>> category.color is None
    True
    >>> category.get_family().values_list('name', 'color')
    <TreeQuerySet [('1', '#51DCFF'), ('2', None), ('3', None)]>
    >>> category.inherited_color
    '#51DCFF'









    share|improve this question



























      0












      0








      0







      I'm using the django-mptt library to make categories for my project. The model is pretty simple:



      from django.db import models
      from mptt.models import MPTTModel, TreeForeignKey

      class Category(MPTTModel):
      name = models.CharField('Name', max_length=100, unique=True)
      color = models.CharField(
      'Color',
      max_length=100,
      blank=True,
      null=True
      )
      parent = TreeForeignKey(
      'self',
      on_delete=models.CASCADE,
      null=True,
      blank=True,
      related_name='children'
      )

      class MPTTMeta:
      order_insertion_by = ['name']


      Category color is optional and should be inherited from parent, if undefined. So just to illustrate:



      Main Category 1 (red) -> Subcategory 1
      -> Subcategory 2 (blue)
      -> Subcategory 3 (yellow) -> Subcategory 4


      Subcategory 4 has no color defined and it inherits subcategory 3 color (yellow).
      Subcategory 1 inherits color from Main Category 1 (blue), etc.



      In my view i have the root category and then build a tree using get_descendants(include_self=True).
      How can i annotate color for each category of <TreeQuerySet>?



      For one model i have the following method:



      @property
      def inherited_color(self):
      if self.color:
      return self.color
      return (self
      .get_ancestors(ascending=True, include_self=True)
      .filter(color__isnull=False)
      .values_list('color', flat=True)
      .first())


      But when this method is called for a list of categories it results in a lot of database queries!



      This is an example from django shell:



      >>> category
      <Category: 3>
      >>> category.color is None
      True
      >>> category.get_family().values_list('name', 'color')
      <TreeQuerySet [('1', '#51DCFF'), ('2', None), ('3', None)]>
      >>> category.inherited_color
      '#51DCFF'









      share|improve this question















      I'm using the django-mptt library to make categories for my project. The model is pretty simple:



      from django.db import models
      from mptt.models import MPTTModel, TreeForeignKey

      class Category(MPTTModel):
      name = models.CharField('Name', max_length=100, unique=True)
      color = models.CharField(
      'Color',
      max_length=100,
      blank=True,
      null=True
      )
      parent = TreeForeignKey(
      'self',
      on_delete=models.CASCADE,
      null=True,
      blank=True,
      related_name='children'
      )

      class MPTTMeta:
      order_insertion_by = ['name']


      Category color is optional and should be inherited from parent, if undefined. So just to illustrate:



      Main Category 1 (red) -> Subcategory 1
      -> Subcategory 2 (blue)
      -> Subcategory 3 (yellow) -> Subcategory 4


      Subcategory 4 has no color defined and it inherits subcategory 3 color (yellow).
      Subcategory 1 inherits color from Main Category 1 (blue), etc.



      In my view i have the root category and then build a tree using get_descendants(include_self=True).
      How can i annotate color for each category of <TreeQuerySet>?



      For one model i have the following method:



      @property
      def inherited_color(self):
      if self.color:
      return self.color
      return (self
      .get_ancestors(ascending=True, include_self=True)
      .filter(color__isnull=False)
      .values_list('color', flat=True)
      .first())


      But when this method is called for a list of categories it results in a lot of database queries!



      This is an example from django shell:



      >>> category
      <Category: 3>
      >>> category.color is None
      True
      >>> category.get_family().values_list('name', 'color')
      <TreeQuerySet [('1', '#51DCFF'), ('2', None), ('3', None)]>
      >>> category.inherited_color
      '#51DCFF'






      django django-mptt






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 17 hours ago

























      asked 21 hours ago









      v01d

      4117




      4117





























          active

          oldest

          votes











          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53942918%2fdjango-orm-annotation-with-tree-traversal%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53942918%2fdjango-orm-annotation-with-tree-traversal%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Monofisismo

          Angular Downloading a file using contenturl with Basic Authentication

          Olmecas