class Jornal(models.Model):
    url = models.URLField(unique = True,blank=True)
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name
    @property
    def domain(self):
        return urlparse(self.url).netloc


我如何通过其域获取Jornal对象?我正在外壳中尝试此操作:

domain = "www.example.com"
obj = Jornal.objects.get_domain(domain)


然后这个:

domain = "www.example.com"
obj = Jornal.objects(domain = domain)


但是没有办法。

编辑我正在尝试使用get方法,因为在没有找到它的情况下,我需要DidNotExist。

最佳答案

由于该属性是在运行时存储的,因此,如果我们将该属性视为黑匣子,则只能通过在Python级别进行过滤来做到这一点。因此,例如列表理解:

domain = "www.example.com"
all_example_domain = [j for j in Journal.objects.all() if j.domain == domain]


通常,我们不能反转函数,因此我们不能为此在数据库级别使用过滤。

然而,在这里,我们现在有了一些额外的东西:domain是URL的子字符串。因此,我们可以通过在数据库级别进行一些过滤来增强过滤过程:

domain = "www.example.com"
all_example_domain = [j for j in Journal.objects.filter(url__icontains=domain)
                        if j.domain == domain]


因此,这里我们已经过滤掉了Journal对象,其中url不包含请求的domain。从技术上讲,其中仍然可能存在错误(例如,带有www.example.com.com的url)。因此,我们最好使用j.domain == domain进行第二次过滤。

如果没有这样的对象,则列表将为空;如果有多个,则列表将包含两个或多个项目。

我们可以使用它编写一个函数,该函数将进行适当的过滤,并在找不到这样的对象或多个对象的情况下引发错误。例如:

从itertools导入islice

def property_get(query_set, **kwargs):
    results = list(islice((j for j in qs
                          if all(getattr(j, k) == v for k, v in kwargs.items())),
                         2))
    if results:
        if len(results) > 1:
            raise MultipleObjectsReturned
        return results[0]
    else:
        raise ObjectDoesNotExist


因此,我们可以使用property_get(Journal.objects.all(), domain=domain)进行查询,它将引发ObjectDoesNotExistMultiObjectsReturned异常。但这效率很低。

通常,如果您经常查询属性,将属性存储在数据库以及字段中而不使用属性,则更好。

10-02 10:59
查看更多