【问题标题】:select related in Django在 Django 中选择相关
【发布时间】:2026-01-16 08:05:03
【问题描述】:

我正在尝试完成与以下内容非常相似的事情: How to join 3 tables in query with Django

基本上,我有 3 张桌子。在 Django REST 中,我们展示了表 3。如下所示(models.py),表 3 有 company_name,这是表 2 的外键,表 2 是表 1 的外键。表 2 和表 3由表 1 ID 链接。表 1 包含我们希望在 API 输出中显示的实际文本,而不是 ID 号。

表 1:汽车制造商 -- 表 2:汽车是什么 -- 表 3:所有汽车的列表

Models.py

Table 1:
class ManufacturerName(models.Model):
    name_id = models.AutoField(primary_key=True)
    company_name = models.CharField(unique=True, max_length=50)

    class Meta:
        managed = False
        db_table = 'manufacturer_name'

Table 2:
    class CarBuild(models.Model):
        car_id = models.AutoField(primary_key=True)
        car_icon = models.CharField(max_length=150, blank=True, null=True)
        company_name = models.ForeignKey('ManufacturerName', models.DO_NOTHING, db_column='ManufacturerName') 

        class Meta:
              managed = False
              db_table = 'car_build'

Table 3:
class CarList(models.Model):
    list_id = models.AutoField(primary_key=True)
    company_name = models.ForeignKey('CarBuild', models.DO_NOTHING, db_column='CarBuild')
    title = models.CharField(unique=True, max_length=100)
    description = models.TextField()


    class Meta:
        managed = False
        db_table = 'cars'

在我看来: 这是我正在尝试的,基于外键关系:

queryset = CarList.objects.all().select_related('company_name__company_name')

当我保存并运行它时,我没有收到任何错误,但是仍然返回 ID,而不是与外键关系关联的文本:

[
    {
        "list_id": 1,
        "company_name": "http://127.0.0.1:8000/api/1/",
        "title": "Really fast car you're driving, and this is dummy text",

再次,我想实现从表 1 中获取与 company_name 外键关系关联的文本以显示在 JSON 中。

序列化器和视图集

class manufacturer_name(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = manufacturer_name
        fields = ('name_id', 'company_name')

class manufacturer_name(viewsets.ModelViewSet):

    queryset = manufacturer_namee.objects.all()
    serializer_class = manufacturer_name


class CarBuildViewSet(viewsets.ModelViewSet):

    queryset = CarBuild.objects.all()
    serializer_class = CarBuildSerialiser

class CarBuildSerialiser(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = CarBuild
        fields = ('car_id', 'car_icon', 'company_name')


class CarListSerialiser(serializers.HyperlinkedModelSerializer):

    class Meta:
        model = News
        fields = ('list_id', 'company_name', 'title')


class CarListViewSet(viewsets.ModelViewSet):
    serializer_class = CarList
    def get_queryset(self):
        queryset = News.objects.all().select_related('company_name__company_name')
    return queryset

【问题讨论】:

  • 这里相关的是视图和序列化器,你应该展示它们。
  • 该链接来自使用普通 Django 和模板的人。您正在使用 DRF 并希望更改由序列化程序确定的 JSON 输出。
  • @DanielRoseman 我现在已经添加了它们

标签: django django-models django-rest-framework django-views


【解决方案1】:

基于详细的对话来清除一些细节。这是答案。

您需要对模型进行一些小的更改,因为您很难理解您想要实现的目标。

型号:

class ManufacturerName(models.Model):
    name_id = models.AutoField(primary_key=True)
    company_name = models.CharField(unique=True, max_length=50)

    class Meta:
        managed = False
        db_table = 'manufacturer_name'


class CarBuild(models.Model):
    car_id = models.AutoField(primary_key=True)
    car_icon = models.CharField(max_length=150, blank=True, null=True)
    manufacturer = models.ForeignKey(ManufacturerName,on_delete=models.SET_NULL) 

    class Meta:
          managed = False
          db_table = 'car_build'


class CarList(models.Model):
    list_id = models.AutoField(primary_key=True)
    car = models.ForeignKey(CarBuild, on_delete=models.DO_NOTHING)
    title = models.CharField(unique=True, max_length=100)
    description = models.TextField()

    class Meta:
       managed = False
       db_table = 'cars'

然后你需要调整你的序列化器。

class CarListSerialiser(serializers.HyperlinkedModelSerializer):

    company_name= serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = CarList
        fields =  ('list_id', 'company_name', 'title')

    def get_company_name(self, obj):
        return obj.car.manufacturer.company_name

你在你的视图中使用它:

class CarListViewSet(viewsets.ModelViewSet):
    queryset = CarList.object.all()
    serializer_class = CarListSerialiser

【讨论】:

  • 第二个选项在哪里?
  • 你有两个,一个是company_name_1,第二个是company_name_2
  • 只是为了确认,我试图显示存储在 company_name 主键表中的文本。 SQL 等价物是内连接
  • 你只是想显示ID?我认为您想从 ManufacturerName 模型中查看 company_name,不是吗?
  • 这正是我想要做的。我想查看存储在表 1 (manufacturer_name) 中的 company_name 文本...表 2 (carbuild) 和表 3 (carlist) 通过 ID 与表 1 相关。我想在 API 框架中显示文本而不是 ID。所以换句话说,用户看到的是实际的公司名称,而不是 ID