How can I select entries in one table based on criteria in another table in Django's ORM if the foreign key is not referencing a primary key but another column with unique constraint?
The corresponding SQL command would be:

SELECT TableMoon.name
FROM TableMoon JOIN TablePlanet
ON TableMoon.planet = TablePlanet.name
WHERE classification = 'inner_planet';

预期的答案是:月球、火卫二、土卫二

我试图在Django ORM中从上面改写SQL命令,但每次都会得到一个空的QuerySet:

Tablemoon.objects.filter(planet__classification='inner_planet').values('name')
#Out: <QuerySet []>

Tablemoon.objects.filter(planet_id__classification='inner_planet').values('name')
#Out: <QuerySet []>

Background
I have a Django app that is connected to a legacy sqlite database. I am not allowed to modify the database scheme. The database looks like this:

TablePlanet  
------------------------------------  
planet_id |  name   | classification  
------------------------------------  
1         | Mercury | inner_planet  
2         | Venus   | inner_planet  
3         | Earth   | inner_planet  
4         | Mars    | inner_planet  
5         | Jupiter | outer_planet  
6         | Saturn  | outer_planet  
7         | Uranus  | outer_planet  
8         | Neptune | outer_planet  

TableMoon  
------------------------  
moon_id | planet  | name
------------------------  
1       | Earth   | Moon  
2       | Mars    | Phobos  
3       | Mars    | Deimos  
4       | Jupiter | Io  
5       | Jupiter | Europa  
6       | Jupiter | Ganymede  

TablePlanet.name具有唯一约束.列TableMoon.planet具有引用TablePlanet.name的外键约束.

以下是这些表的SQL代码:

CREATE TABLE tablePlanet (
  planet_id INTEGER PRIMARY KEY,
  name TEXT UNIQUE NOT NULL,
  classification TEXT
);

CREATE TABLE tableMoon (
  moon_id INTEGER PRIMARY KEY,
  planet TEXT,
  name TEXT,
  FOREIGN KEY (planet) REFERENCES tablePlanet(name)
);

我的Models.py文件如下所示

from django.db import models


class Tableplanet(models.Model):
    planet_id = models.AutoField(primary_key=True, null=False)
    name = models.TextField(unique=True)
    classification = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'tablePlanet'


class Tablemoon(models.Model):
    moon_id = models.AutoField(primary_key=True, null=False)
    planet = models.ForeignKey('Tableplanet', models.DO_NOTHING,
                               db_column='planet', blank=True, null=True)
    name = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'tableMoon'

首先让我感到困惑的是Django对Planet-Column的命名,其中一种情况下是‘Planet’,另一种情况下是‘Planet_id’:

Tablemoon._meta.get_fields()
#Out: (<django.db.models.fields.AutoField: moon_id>,
#Out:  <django.db.models.fields.related.ForeignKey: planet>,
#Out:  <django.db.models.fields.TextField: name>)

Tablemoon.objects.all().values()[0]
#Out: {'moon_id': 1, 'planet_id': 'Earth', 'name': 'Moon'}

我非常感谢您在这方面的建议!

推荐答案

您的ForeignKey需要指定正确的to_field=… [Django-doc],因为它没有引用Tableplanet的主键:

class Tablemoon(models.Model):
    moon_id = models.AutoField(primary_key=True, null=False)
    planet = models.ForeignKey(
        'Tableplanet',
        models.DO_NOTHING,
        db_column='planet',
        blank=True,
        null=True,
        to_field='name',
    )
    name = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'tableMoon'

Note:型号通常没有Table前缀.模型不是表,它作为表存储在关系数据库中,但即使这样,它也有额外的逻辑,如验证器、管理器等.

Django相关问答推荐

Templatetag 在 Django 4.2 模板 IF 条件中不起作用

django 无法识别实现自定义后端

如果字段为空,则 Unique_together 不起作用.怎么约束呢?

身份验证有效,但登录无效.一直卡在pending

如何在 django 的列表中查找所有对象作为对象?

在用例图中建模前端和后端

如何在 Django 中将下一个 8 月 1 日添加为 DateTimeField 默认值

设置 SECURE_HSTS_SECONDS 可以不可逆转地 destruct 您的网站?

Django rest框架覆盖ViewSet中的page_size

使用 Django 和 South 重命名应用程序

Django - 强制执行 ManyToManyField 唯一项

ManyRelatedManager 不可迭代

Django SMTPAuthenticationError

是否可以将 FastAPI 与 Django 一起使用?

如何在 twitter-bootstrap 模式窗口中插入 django 表单?

Django - 来自 QuerySet 的唯一列表

如何使用查询参数构造 Django 反向/url?

更改 Django ModelChoiceField 以显示用户的全名而不是用户名

在 Django 中使用 LiveServerTestCase 时使用代码登录

ModelForm 上的 Django 和字段集