You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过domain属性获取Django的Jornal模型对象?

解决Django中通过@property属性获取模型对象的问题

你的问题出在domain是用@property定义的计算属性,它并不是数据库中实际存在的字段——Django的ORM查询是直接转换成SQL操作数据库的,而数据库里没有domain这个列,所以你尝试的get_domain和objects(domain=domain)自然无法生效。

下面给你三种可行的解决方案,根据你的实际场景选择:

方案一:临时通过URL字段匹配(适合偶尔查询、数据量小的情况)

既然domain是从url解析而来,我们可以反过来通过匹配url字段定位对象。这里提供两种实现方式:

方式A:遍历筛选后触发异常

from urllib.parse import urlparse

domain = "www.example.com"
# 筛选出domain匹配的对象
matched_objs = [obj for obj in Jornal.objects.all() if obj.domain == domain]

# 手动触发DoesNotExist异常,和get方法行为一致
if not matched_objs:
    raise Jornal.DoesNotExist(f"No Jornal found with domain {domain}")
obj = matched_objs[0]

方式B:用ORM查询条件匹配URL格式

通过Q表达式覆盖常见的URL格式(带http/https、有无末尾斜杠等),避免遗漏:

from django.db.models import Q

domain = "www.example.com"
obj = Jornal.objects.get(
    Q(url__startswith=f"http://{domain}/") |
    Q(url__startswith=f"https://{domain}/") |
    Q(url__startswith=f"http://{domain}") |
    Q(url__startswith=f"https://{domain}") |
    Q(url__exact=domain)  # 处理不带协议的URL情况
)

方案二:添加domain数据库字段(推荐,适合频繁查询、数据量大的场景)

把domain作为数据库字段存储,既能提升查询效率,又能直接使用ORM的get方法。我们可以在save方法中自动同步domain的值:

from django.db import models
from urllib.parse import urlparse

class Jornal(models.Model):
    url = models.URLField(unique=True, blank=True)
    name = models.CharField(max_length=100)
    # 添加domain字段,加上db_index提升查询速度
    domain = models.CharField(max_length=255, blank=True, db_index=True)

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        # 保存时自动从url解析domain
        if self.url:
            self.domain = urlparse(self.url).netloc
        super().save(*args, **kwargs)

    # 保留原有的property方便旧代码使用(可选)
    @property
    def domain_from_url(self):
        return urlparse(self.url).netloc

修改后,你就能直接用get方法查询,不存在时自动触发DoesNotExist异常:

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

方案三:自定义模型管理器(不修改模型结构,优雅封装查询)

如果你不想改动现有模型,可以自定义模型管理器,封装get_by_domain方法:

from django.db import models
from urllib.parse import urlparse

class JornalManager(models.Manager):
    def get_by_domain(self, domain):
        for obj in self.all():
            if obj.domain == domain:
                return obj
        # 找不到对象时抛出和get一致的异常
        raise self.model.DoesNotExist(f"No {self.model.__name__} found with domain {domain}")

class Jornal(models.Model):
    url = models.URLField(unique=True, blank=True)
    name = models.CharField(max_length=100)
    # 替换默认的模型管理器
    objects = JornalManager()

    def __str__(self):
        return self.name

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

之后你就能像最开始设想的那样调用:

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

注意:这个方案需要遍历所有对象,数据量大时查询效率会很低,仅适合小规模数据集。

内容的提问来源于stack exchange,提问作者Miguel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:45:19