【问题标题】:Django Rest Framework display reverse fieldDjango Rest Framework 显示反向字段
【发布时间】:2023-03-05 04:52:01
【问题描述】:

我的问题是关于使用 Django Rest Framework 设计一个 RESTful API。我有以下两个数据文件。

# cars.csv
Escalade, Ford
Outback, Subaru
Fiesta, Ford

# description.csv
new, "Escalade", 2018, "perfect condition"
used, "Escalade", 2016, "in good shape"
used, "Escalade", 2010, "bad condition"

我想要一个仅 GET 的 API 端点,它会输出以下内容:

{
  "model": "Escalade",
  "company": "Ford",
  "year": 2018,
  "details": [
    {
      "condition": "new",
      "description": "perfect condition"
    }
 ]

}

问题是如何显示year,使其显示在模型位置的上一级。如果我更改了原始 csv 文件,我可以将 year 添加到 cars.csv 但假设我不能这样做。如何配置我的序列化程序以输出所需的 API 端点?

这是模型、序列化程序、视图和 url。

# models.py
from django.db import models

class Car(models.Model):
    model = models.CharField(max_length=100)
    company = models.CharField(max_length=100)

class Detail(models.Model):
    year = models.CharField(
    condition = models.CharField(max_length=100)    
    car = models.ForeignKey('Car', related_name='details',
                        on_delete=models.CASCADE,)
    description = models.CharField(max_length=100)


# serializers.py
from rest_framework import serializers
from . import models


class DetailSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        fields = ('year', 'condition', 'description',)
        model = models.Detail


class CarSerializer(serializers.HyperlinkedModelSerializer):
    details = DetailSerializer(many=True, read_only=True)

class Meta:
    fields = ('model', 'company', 'details',)
    model = models.Car

# views.py
from rest_framework import generics

from . import models
from . import serializers


class CarDetail(generics.RetrieveAPIView):
    queryset = models.Detail.objects.all()
    serializer_class = serializers.DetailSerializer


class CarList(generics.ListAPIView):
    queryset = models.Car.objects.all()
    serializer_class = serializers.CarSerializer



# urls.py 
from django.urls import path

from . import views

urlpatterns = [
    path('', views.CarList.as_view()),
    path('<int:pk>', views.CarDetail.as_view()),
]

【问题讨论】:

    标签: rest django-rest-framework


    【解决方案1】:

    也许使用SerializerMethodField

    class CarSerializer(serializers.HyperlinkedModelSerializer):
        details = DetailSerializer(many=True, read_only=True)
        year = serializers.SerializerMethodField()
    
        class Meta:
            fields = ('model', 'company', 'details', 'year',)
            model = models.Car
    
        def get_year(self, car):
            return car.details.first().year
    

    您需要小心一点,因为上面的示例假定汽车总是至少有一个Detail,它会使用找到的第一个。

    【讨论】:

    • 感谢您的回复。请注意我稍微修改了原始代码,所以Description 表现在是Detail。我看到了您的方法的智慧,但是我坚持使用AttributeError at / 'Car' object has no attribute 'detail_set'。它应该能够在get_year 方法中对detail_set 进行反向查找,所以我不确定。
    • 另外,我认为您注意到的解决方法表明,如果可能的话,也许更好的选择是简单地更新原始 csv 文件,而不是尝试实现这种反向。是吗?
    • 啊,是的,外键有一个 related_namedetails - 我已经相应地修改了我的答案。
    • 但是,是的,它确实突出了一个事实,即数据模型可能不太正确 - 将 year 移动到 Car 可能是更好的方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 2012-12-25
    • 2015-10-04
    • 2020-06-09
    • 2021-09-03
    • 2018-03-29
    相关资源
    最近更新 更多