class Tag(models.Model):
  name = models.CharField(maxlength=100)

class Blog(models.Model):
  name = models.CharField(maxlength=100)
  tags =  models.ManyToManyField(Tag)

简单的模型只是为了问我问题.

我想知道如何以两种不同的方式使用标签查询博客.

  • 带有"tag1"或"tag2"标签的博客条目: Blog.objects.filter(tags_in=[1,2]).distinct()
  • 标记为"tag1"和"tag2"的博客对象:?
  • 只标记了"tag1"和"tag2"的博客对象:??

Tag和Blog只是一个例子.

推荐答案

您可以对#1使用Q对象:

# Blogs who have either hockey or django tags.
from django.db.models import Q
Blog.objects.filter(
    Q(tags__name__iexact='hockey') | Q(tags__name__iexact='django')
)

联合和交叉点,我相信,有点超出了Django ORM的范围,但也有可能添加到这些.以下示例来自一个名为django-tagging的Django应用程序,它提供该功能.Line 346 of models.py:

在第二部分中,基本上是两个查询的并集

def get_union_by_model(self, queryset_or_model, tags):
    """
    Create a ``QuerySet`` containing instances of the specified
    model associated with *any* of the given list of tags.
    """
    tags = get_tag_list(tags)
    tag_count = len(tags)
    queryset, model = get_queryset_and_model(queryset_or_model)

    if not tag_count:
        return model._default_manager.none()

    model_table = qn(model._meta.db_table)
    # This query selects the ids of all objects which have any of
    # the given tags.
    query = """
    SELECT %(model_pk)s
    FROM %(model)s, %(tagged_item)s
    WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
      AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s)
      AND %(model_pk)s = %(tagged_item)s.object_id
    GROUP BY %(model_pk)s""" % {
        'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)),
        'model': model_table,
        'tagged_item': qn(self.model._meta.db_table),
        'content_type_id': ContentType.objects.get_for_model(model).pk,
        'tag_id_placeholders': ','.join(['%s'] * tag_count),
    }

    cursor = connection.cursor()
    cursor.execute(query, [tag.pk for tag in tags])
    object_ids = [row[0] for row in cursor.fetchall()]
    if len(object_ids) > 0:
        return queryset.filter(pk__in=object_ids)
    else:
        return model._default_manager.none()

第三部分,我相信你在寻找一个十字路口.见line 307 of models.py

def get_intersection_by_model(self, queryset_or_model, tags):
    """
    Create a ``QuerySet`` containing instances of the specified
    model associated with *all* of the given list of tags.
    """
    tags = get_tag_list(tags)
    tag_count = len(tags)
    queryset, model = get_queryset_and_model(queryset_or_model)

    if not tag_count:
        return model._default_manager.none()

    model_table = qn(model._meta.db_table)
    # This query selects the ids of all objects which have all the
    # given tags.
    query = """
    SELECT %(model_pk)s
    FROM %(model)s, %(tagged_item)s
    WHERE %(tagged_item)s.content_type_id = %(content_type_id)s
      AND %(tagged_item)s.tag_id IN (%(tag_id_placeholders)s)
      AND %(model_pk)s = %(tagged_item)s.object_id
    GROUP BY %(model_pk)s
    HAVING COUNT(%(model_pk)s) = %(tag_count)s""" % {
        'model_pk': '%s.%s' % (model_table, qn(model._meta.pk.column)),
        'model': model_table,
        'tagged_item': qn(self.model._meta.db_table),
        'content_type_id': ContentType.objects.get_for_model(model).pk,
        'tag_id_placeholders': ','.join(['%s'] * tag_count),
        'tag_count': tag_count,
    }

    cursor = connection.cursor()
    cursor.execute(query, [tag.pk for tag in tags])
    object_ids = [row[0] for row in cursor.fetchall()]
    if len(object_ids) > 0:
        return queryset.filter(pk__in=object_ids)
    else:
        return model._default_manager.none()

Django相关问答推荐

如何在管理页面创建实例时只在ManyToManyField字段中显示超级用户

如何删除Docker上的django应用程序?

Django中用于外键的嵌套循环

Django 按月分组并按月显示在模板中

在 Django 模板中分页时如何正确显示与其父模型字段关联的所有内联字段?

Django ORM,按天分组

JSP模板继承

Django 自定义管理器 - 如何仅返回登录用户创建的对象?

relation "django_site" does not exist

Django SMTPAuthenticationError

如何在 django-rest-framework 中为 API 使用 TokenAuthentication

如何按名称设置 django 模型字段?

使用 lambda 作为属性的默认值时,Django 1.7.1 Makemigrations 失败

django 有条件地过滤对象

django post_save 更新信号

Django Rest Framework - 缺少静态目录

Django - 每 x 秒运行一个函数

在 Celery 任务中运行 Scrapy 蜘蛛

基于 User-Agent 更改 Django 模板

Django 测试 - 在所有测试中修补对象