Django Rest Api - ManyToManyField,在练习数组中显示'title'而不是'id'

Posted

技术标签:

【中文标题】Django Rest Api - ManyToManyField,在练习数组中显示\'title\'而不是\'id\'【英文标题】:Django Rest Api - ManyToManyField, Display 'title' instead of 'id' in the Exercises ArrayDjango Rest Api - ManyToManyField,在练习数组中显示'title'而不是'id' 【发布时间】:2019-10-12 13:44:20 【问题描述】:

Django Rest Api - ManyToManyField,在练习数组中显示'title'而不是'id'

HTTP 200 OK
Allow: GET, POST, PUT, DELETE, PATCH
Content-Type: application/json
Vary: Accept

[

    "id": 1,
    "title": "Push Workout Bjarred",
    "description": "Kör Hårt!",
    "exercises": [
        3,
        4,
        5,
        6,
        9,
        10
    ],
    "cardio": [
        4
    ]
,

    "id": 2,
    "title": "Pull Workout Loddekopinge",
    "description": "",
    "exercises": [
        1,
        2,
        7,
        8
    ],
    "cardio": []
,

    "id": 3,
    "title": "CardioPass",
    "description": "",
    "exercises": [],
    "cardio": [
        2,
        3,
        4
    ]

]

序列化器(所以我想为每个练习显示标题而不是 id)

class WorkoutSerializer(serializers.ModelSerializer):
    class Meta:
        model = Workout
        fields = ('id', 'title', 'description', 'exercises', 'cardio')

这是模型,注意我想在 api 数组中显示每个练习的名称,我不想要 id! - 现在通过了! :)

class Bodypart(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Exercise(models.Model):
    name = models.CharField(max_length=40)
    bodyparts = models.ManyToManyField(Bodypart, blank=True)

    def __str__(self):
        return self.name

class Cardio(models.Model):
    name = models.CharField(max_length=40)
    time = models.IntegerField(default=10)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name_plural = 'cardio'

class Workout(models.Model):
    title = models.CharField(max_length=120)
    description = models.CharField(max_length=1000, blank=True)
    exercises = models.ManyToManyField(Exercise, blank=True)
    cardio = models.ManyToManyField(Cardio, blank=True)

    def __str__(self):
        return self.title

【问题讨论】:

我如何对此提出发布请求?所以 api 就像 localhost:8000/workouts/2/exercises 【参考方案1】:

您可以通过像这样更改WorkoutSerializer 来获取此信息

class WorkoutSerializer(serializers.ModelSerializer):
    exercises = serializers.StringRelatedField(many=True, read_only=True)
    class Meta:
        fields = ('id', 'title', 'description', 'exercises', 'cardio', )

你会得到这样的结果json

[

    "id": 1,
    "title": "Push Workout Bjarred",
    "description": "Kör Hårt!",
    "exercises": [
        "Exercise 1",
        "Exercise 2",
        "Exercise 4",
        "Exercise 3"
    ],
    "cardio": [
        4
    ]
,
...

有关 django rest 序列化程序的更多信息,请参阅https://www.django-rest-framework.org/api-guide/relations/

【讨论】:

【参考方案2】:

使用名称字段为Exercise 模型创建一个序列化程序:

class ExerciseSerializer(serializers.ModelSerializer):
    class Meta:
        model = Exercise
        fields = ('name', )

并将其添加到 Workout 序列化程序中:

class WorkoutSerializer(serializers.ModelSerializer):
    exercises = ExerciseSerializer(many=True, read_only=True)
    class Meta:
        fields = ('id', 'title', 'description', 'exercises', 'cardio', )

【讨论】:

我如何对此提出发布请求?所以 api 就像 localhost:8000/workouts/2/exercises【参考方案3】:

尝试在序列化程序中添加练习字段,如下所示 exercises = serializers.SlugRelatedField(read_only=True, slug_field='title')

【讨论】:

【参考方案4】:

我遇到了类似的问题,但我就是这样解决的:

class WorkoutSerializer(serializers.ModelSerializer):
     exercises = serializers.StringRelatedField(many=True, read_only=True)
     class Meta:
         fields = ('id', 'title', 'description', 'exercises', 'cardio', )

更新了模型:

class Workout(models.Model):
   title = models.CharField(max_length=120)
   description = models.CharField(max_length=1000, blank=True)
   exercises = models.ManyToManyField(Exercise, **related_name='exercises'**, blank=True)
   cardio = models.ManyToManyField(Cardio, blank=True)

   def __str__(self):
       return self.title

【讨论】:

【参考方案5】:

我遇到了同样的问题,现在我知道了答案:

class WorkoutSerializer(serializers.ModelSerializer):
    exercise = serializers.SlugRelatedField(read_only=True, slug_field='name', many=True)
    cardio = serializers.SlugRelatedField(read_only=True, slug_field='name', many=True)
    class Meta:
        fields = ('id', 'title', 'description', 'exercise', 'cardio', )

它必须是 exercisecardio,它们是锻炼中的确切字段(而不是 exercisescardios。所以基本上,上面 Mwangi Kabiru 的答案是正确的,除了 slug_field 必须是“名称”而不是标题,因为运动类和有氧运动类中的字段是名称,而不是标题。

【讨论】:

以上是关于Django Rest Api - ManyToManyField,在练习数组中显示'title'而不是'id'的主要内容,如果未能解决你的问题,请参考以下文章

如何在 django-rest-framework 中为 API 使用 TokenAuthentication

Python / Django 中的 REST API

django-rest-swagger对API接口注释

DJANGO REST API--找不到模块错误

在 HTML 页面或模板中使用 Django-REST-Framework 从在 Django 中创建的 API 获取/显示 API 数据

django-rest-framework 和 swagger api 文档