Search code examples
pythonmysqldjangoormmodels

Django filtering by multiple tags in many to many ORM object


I have three models. Query, QueryStringTag, and Tag. These models are apart of a tag cloud that I have built. A Query can have many Tags and a Tag can have many Querys. The Tag and Query models have foreign keys to the connecting QueryStringTag model that holds all of the information about how a query is associated with a tag and vice versa.

Here are my models...

class Tag(models.Model):
    name = models.CharField(max_length=101)
    use_count = models.IntegerField(default=1)

class QueryStringTag(models.Model):
    tag = models.ForeignKey(Tag, related_name='qstag')
    querystring = models.ForeignKey(QueryString, related_name='qsquerystring')

class QueryString(BaseObject): 
    """
    Query string holds an SQL statement and query properties for execution
    """

    server_id = models.IntegerField()
    schema = models.CharField(max_length=255, blank=True)
    archived = models.BooleanField(default=False)
    query = models.CharField(max_length=60000) 
    variables = models.TextField(blank=True)
    created_by = models.ForeignKey(User, related_name='queries_created')
    updated_by = models.ForeignKey(User, related_name='queries_last_edited')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField()
    touched_by = models.CharField(max_length=1000)
    config = models.TextField(blank=True)
    runs_started = models.IntegerField(default=0)
    runs_completed = models.IntegerField(default=0)
    runs_completed_duration = models.IntegerField(default=0) # total number of seconds spent running this query to completion
    formats = "pretty_html html json prettyjson csv excel tableau".split()

I currently have it set up so a user clicks any given amount of tags in the tag cloud and an array of tag primary keys are sent down to my django view looking something like this: ['12', '14', '15']

I need to use Django ORM to retrieve all queries that are associated with all of the tags the user clicked on. So if a user clicks on the tags, 'user', 'game', and 'truck' it should bring me back only the queries that are associated with all of the tags that the user clicked on. This is an AND relationship, not an OR relationship. Meaning "Query1" would be associated with '12' and '14' and '15'.

What would the correct syntax be for this?


Solution

  • qsts_pks = QueryStringTag.objects.filter(tag__pk__in=['12', '14', '15']).values_list('id', flat=True)
    queries = QueryString.objects.filter(qsquerystring__pk__in=qsts_pks)
    

    Relevant docs here and here