在非主键关系上加入和查询Django模型?

Dav*_*ver 4 django django-models

我有两个通过非主键字段在逻辑上相关的模型。是否可以在select_related(…)不引入ForeignKey列的情况下查询它们(例如,)?

例如,考虑人为模型:

class LogEntry(Model):
    source_name = CharField(…)
    log_message = CharField(…)

class LogSource(Model):
    name = CharField(…)
    domain = CharField(…)
Run Code Online (Sandbox Code Playgroud)

我希望能够查询LogEntry,加入和过滤相关内容LogSource(例如,因此我可以访问log_entry.source而无需其他查询):

LogEntry.objects
    .select_related(
        source=Join(LogSource, on="logsource.name = logentry.source_name")),
    )
    .filter(source__domain="example.com")
Run Code Online (Sandbox Code Playgroud)

不引入ForeignKey可以做到吗?

Ala*_*air 6

通过使用extra()tables选项,您应该能够做到这一点。

LogEntry.objects.extra(
    tables=['logsource'],
    where=['logsource.name=logentry.source_name',
           'logsource_domain="example.com"',
           ]
)
Run Code Online (Sandbox Code Playgroud)

另一个选择是更改source_name为外键,但指定db_columnto_field参数以使用现有列。我知道您说过您不想添加外键,但这是可以接受的,因为它仅更改模型,而不更改数据库表中的列。但是,请注意,Django可能要创建外键约束。一种破解方法是伪造该迁移,以便不在数据库中创建约束。

class LogEntry(Model):
    source_name = models.ForeignKey(db_column=source_name', to_field='name')
Run Code Online (Sandbox Code Playgroud)

log_entry.source_name然后将是LogSource实例,并且log_entry.source_name_id将是存储在source_name列中的值。它可能是有意义的领域,从命名source_namesource转换为外键之后,但是这是没有必要的。