Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django:可查询的计算字段_Python_Django_Django Models_Computed Properties_Computed Field - Fatal编程技术网

Python Django:可查询的计算字段

Python Django:可查询的计算字段,python,django,django-models,computed-properties,computed-field,Python,Django,Django Models,Computed Properties,Computed Field,是否有一种“最佳”方式来处理可查询的计算字段 例如: from django.db import models class Person(models.Model): given_name = models.CharField(max_length=30) family_name = models.CharField(max_length=30) NAME_ORDER_CONVENTION_CHOICES = ( # "Eastern" name or

是否有一种“最佳”方式来处理可查询的计算字段

例如:

from django.db import models

class Person(models.Model):
    given_name = models.CharField(max_length=30)
    family_name = models.CharField(max_length=30)

    NAME_ORDER_CONVENTION_CHOICES = (
        # "Eastern" name order: family name followed by given name
        ('E', 'Eastern'),
        # "Western" name order: given name followed by family name
        ('W', 'Western')
    )

    name_order_convention = models.CharField(
        length=1, 
        choices=NAME_ORDER_CONVENTION_CHOICES,
    )

    @property
    def full_name(self):
        """
        Return full name, calculated on the basis of given name,
        family name and name order convention.
        """
        template = "{} {}"
        if self.name_order_convention == "W":
            return template.format(self.given_name, self.family_name)
        return template.format(self.family_name, self.given_name)
这使您能够为任何
人员
获取
全名
,但如果您希望基于全名执行数据库查询,则需要编写一个包含如何计算此属性的隐式知识的查询。这似乎违反了DRY,因为不再有任何中心位置可以更改计算字段的计算方式-您必须更改
full_name
属性,以及基于
full_name
工作方式的隐式知识进行查询的任何位置

我能想到的主要替代方法是重写
save()
方法,以便在每次更新时更新这些字段

from django.db import models

class Person(models.Model):
    given_name = models.CharField(max_length=30)
    family_name = models.CharField(max_length=30)

    NAME_ORDER_CONVENTION_CHOICES = (
        ('E', 'Eastern'),
        ('W', 'Western')
    )

    name_order_convention = models.CharField(
        length=1, 
        choices=NAME_ORDER_CONVENTION_CHOICES,
    )

    # Computed fields
    full_name = models.CharField(max_length=60)

    def _calculate_full_name(self):
        template = "{} {}"
        if self.name_order_convention == "W":
            self.full_name = template.format(self.given_name, self.family_name)
        else:
            self.full_name = template.format(self.family_name, self.given_name)

    def save(self, *args, **kwargs):
        self._calculate_full_name()
        super(Model, self).save(*args, **kwargs)

对于我可能缺少的可查询计算字段,是否有一个通用的“最佳实践”解决方案?

我可以看到的一种方法是:在数据库中创建视图,在django中使用连接的全名和非托管模型,该模型将用于查询(
Person
模型也应存在于crud操作中):

视图(postgresql)

非托管模型:

class ViewPerson(models.Model):
    given_name = models.CharField(max_length=30)
    family_name = models.CharField(max_length=30)
    full_name = models.CharField(max_length=60)

    class Meta:
        managed = False

我可以看到的一种方法是:在数据库中创建视图,并使用连接的全名和django中的非托管模型,该模型将用于查询(
Person
model也应存在于crud操作中):

视图(postgresql)

非托管模型:

class ViewPerson(models.Model):
    given_name = models.CharField(max_length=30)
    family_name = models.CharField(max_length=30)
    full_name = models.CharField(max_length=60)

    class Meta:
        managed = False

答案可能在于django相当新的查询注释:


答案可能在于django相当新的查询注释:

company = Company.objects.annotate(
    chairs_needed=F('num_employees') - F('num_chairs'))