Django的ReverseUnique字段实现
项目描述
Django的ReverseUnique模型字段实现
ReverseUnique字段可以用于从ForeignKey的反向访问单个模型实例。本质上,ReverseUnique可以用于在正常ForeignKey的反向方向上生成OneToOneField的行为。想法是在遍历外键的反向方向时添加一个唯一的过滤条件。
要使用反向唯一,您需要一个反向边的唯一约束,或者知道反向边只有一个实例可以匹配。
示例
看到实际的用例总是很好的。在这个例子中,我们将用具有时间依赖性的薪水来模拟员工。这个用例可以建模为
class Employee(models.Model): name = models.TextField() class EmployeeSalary(models.Model): employee = models.ForeignKey(Employee, related_name='employee_salaries') salary = models.IntegerField() valid_from = models.DateField() valid_until = models.DateField(null=True)
可以保存像“Anssi从2000-1-1到2009-12-31有10€的薪水,从2010-1-1到无穷大(在模型中建模为None)的薪水11€”这样的数据。
不幸的是,当使用这些模型时,直接获取员工及其薪水以显示给用户并不简单。可以通过遍历员工的全部薪水并检查哪个EmployeeSalaries当前有效来实现这一点。然而,这种方法有几个缺点
在列表视图中表现不佳
最重要的是,执行涉及员工当前工资的查询是不可能的。例如,获取前10位最高薪员工或员工的平均工资,在单次查询中是无法实现的。
Django-reverse-unique拯救了我们!让我们将Employee模型改为
from datetime import datetime class Employee(models.Model): name = models.TextField() current_salary = models.ReverseUnique( "EmployeeSalary", filter=Q(valid_from__gte=datetime.now) & (Q(valid_until__isnull=True) | Q(valid_until__lte=datetime.now)) )
现在我们可以简单地发出如下查询
Employee.objects.order_by('current_salary__salary')[0:10]
或者
Employee.objects.aggregate(avg_salary=Avg('current_salary__salary'))
那里发生了什么?我们添加了一个ReverseUnique字段。该字段是EmployeeSalary.employee外键的反向,并附加了一个限制,即关系必须在执行查询的当前时刻有效。第一个“EmployeeSalary”参数指的是EmployeeSalary模型(我们必须使用字符串,因为EmployeeSalary模型是在Employee模型定义之后定义的)。filter参数是一个Q对象,可以引用远程模型的字段。
Django应用程序的另一个常见问题是如何存储模型翻译。存储问题可以使用django-reverse-unique来解决。以下是一个针对该用例的完整示例。
from django.db import models from reverse_unique import ReverseUnique from django.utils.translation import get_language, activate class Article(models.Model): active_translation = ReverseUnique("ArticleTranslation", filters=Q(lang=get_language)) class ArticleTranslation(models.Model): article = models.ForeignKey(Article) lang = models.CharField(max_length=2) title = models.CharField(max_length=100) body = models.TextField() class Meta: unique_together = ('article', 'lang') activate("fi") objs = Article.objects.filter( active_translation__title__icontains="foo" ).select_related('active_translation') # Generated query is # select article.*, article_translation.* # from article # join article_translation on article_translation.article_id = article.id # and article_translation.lang = 'fi' # If you activate "en" instead, the lang is changed. # Now you can access objs[0].active_translation without generating more # queries.
同样,可以获取酒店房间等的当前有效预订等。
安装
ReverseUnique的要求是Django 1.6+。您需要将reverse_unique目录放置在Python路径中,然后就像在上面的示例中那样使用它。测试(reverse_unique/tests.py)包含一些额外的示例。安装的最简单方法是
pip install -e git://github.com/akaariai/django-reverse-unique.git#egg=reverse_unique
测试
您需要安装支持的Django版本。转到testproject目录并运行
python manage.py test reverse_unique
项目详情
哈希值 for django_reverse_unique_charettes-1.1-py2.py3-none-any.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 3409edce3b119b9bddcb69593d02b7022d5fde73f6b7f3a31530c4ca20bc6a71 |
|
MD5 | 279ea9414b31a3b29e647f0b7b2d118a |
|
BLAKE2b-256 | c0c108d2dc31d0f84709e8278715034253b0cddec1c95a943d396396a0a022db |