question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Passing ordering parameter to the TaggableManager

See original GitHub issue

So far I am doing it like this:

class _SortedTaggableManager(_TaggableManager):
    def get_queryset(self, *args, **kwargs):
        qs = super(_SortedTaggableManager, self).get_queryset(*args, **kwargs)
        return qs.order_by("name")

Then later in the code I am defining the following:

tags = TaggableManager(manager=_SortedTaggableManager)

But I feel it would be much easier to simply write:

tags = TaggableManager(ordering=["name"])

What do you think?

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:2
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
kavdevcommented, Jun 16, 2021

Just throwing this out there for anyone who comes across this looking to solve prefetch_related query issues.

The taggable manager has a workaround in the get_queryset that helps avoid spawning a ton of queries. Removing that causes a specified prefetch_related to both send the prefetch query and then still fetch tags on each instance.

Here’s a version of @Natim’s manager that supports prefetch_related. I’ve submitted a version of this as a PR.

class _SortedTaggableManager(_TaggableManager):
    ordering = ["name"]

    def get_queryset(self, extra_filters=None):
        try:
            return self.instance._prefetched_objects_cache[self.prefetch_cache_name]
        except (AttributeError, KeyError):
            kwargs = extra_filters if extra_filters else {}
            return self.through.tags_for(self.model, self.instance, **kwargs).order_by(*self.ordering)
0reactions
nicorelliuscommented, May 10, 2021

@rtpg Thanks for the reply. Apologies for the delay in getting back with you. To be fair, I implemented this a while back so the code is not fresh, but this is what I’ve got (I could totally be doing this wrong):

class TagColor(models.TextChoices):
    RED = 'RD', _('danger')
    BLUE = 'BU', _('primary')
    GREEN = 'GN', _('success')
    YELLOW = 'JR', _('warning')

class RNTag(TagBase):
    color = models.CharField(max_length=2, choices=TagColor.choices)

    class Meta:
        verbose_name = _('Tag')
        verbose_name_plural = _('Tags')
        ordering = ['color']

class RNsTaggedItem(GenericTaggedItemBase):
    tag = models.ForeignKey(
        RNTag,
        on_delete=models.CASCADE,
        related_name="%(app_label)s_%(class)s_items",
    )

I then do something like this in the template (it’s a ListView for RN objects):

{% for pr in pr_list %}
    . . .
    {% for rn in pr.rns.all %}
        . . .
        {% for tag in rn.tags.all %}
          <span class="badge bg-{{ tag.get_color_display }}">
            {{ tag.name }}
          </span>
        {% endfor %}
    {% endfor %}
{% endfor %}

This spits out the list of RNs and associated tags but the order is mixed.

Here is the RN model (some bits omitted):

class RN(abstract_base_model_factory()):
    . . .
    pr = models.ForeignKey(PR, on_delete=models.CASCADE, related_name='rns')
    tags = TaggableManager(through=ReleaseNotesTaggedItem)

    class Meta:
        verbose_name_plural = 'RNs'
        # ordering = ['order']

I should note that I’ve tried setting the ordering on all the models included in this relationship to try and coax out the tag order, but nothing seemed to work. If you have any ideas on a workaround, that would be awesome. As a total hack, I have an order field on the base class from which all my models inherit (not the custom tag, but my own models) so I’m using this to set the order of RN objects.

Also, perhaps what is making this trickier than expected is that RN has a ForeignKey relationship to another model, PR. So my ListView above is actually for PR. I’m doing this because I need to loop through PRs first, then for each PR, I need to loop through all the associated RNs (and thus tags, cause each RN has a single tag).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Passing ordering parameter to the TaggableManager #370
I'm currently struggling with custom tags and related models not honoring the ordering option the Meta class. In my case, I'm tagging things ......
Read more >
django-taggit - Read the Docs
your content model named content_object. Pass this intermediary model as the through argument to. TaggableManager:.
Read more >
The API — django-taggit 1.3.0 documentation - Read the Docs
Returns a list (not a lazy QuerySet ) of other objects tagged similarly to this one, ordered with most similar first. Each object...
Read more >
django-taggit get number of posts that use a particular tag
I tried to look into the source code of django-taggit, specifically the TaggableManager, to see if I can override something there and get...
Read more >
Recipes — Wagtail Documentation 4.1.1 documentation
Wagtail defaults to serving Page -derived models by passing a reference to the page object to a Django HTML template matching the model's...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found