【问题标题】:how do I post a foreign key by some other field rather than primary key in django rest framework如何在 django rest 框架中通过其他字段而不是主键发布外键
【发布时间】:2021-03-05 07:11:38
【问题描述】:

我正在开发一个宠物管理 API,这是我在为宠物分配一周中的某一天时发布到正文的内容:

{
   "day": "Sunday",
   "pet_name": 2 <-- how to add pet name (rather than the primary key)(this is a foreign key)
}

如何传入外键字段而不是主键字段的宠物名。

【问题讨论】:

  • 您必须发布更多代码。主要是您正在使用的 Serializer 类,但添加视图也没有什么坏处。这可能会清楚您所说的 pet name 和主键/外键是什么意思。
  • 让我编辑我的。问题:)
  • 好吧,我会写一个答案。
  • 版主注意 - 请不要用完全不同且不相关的问题覆盖您提出的特定问题。 Ask a new question instead.

标签: python-3.x django django-models django-rest-framework django-serializer


【解决方案1】:

为避免混淆,我将 Daypet_name 属性重命名为 pet,因为它引用了 Pet 模型。

class Day(models.Model):
    pet = models.ForeignKey(Pet, on_delete=models.CASCADE, null=True)

在您的DaySerializer 中,您只需使用SlugRelatedField 即可使用宠物的name 来引用宠物。

class DaySerializer(serializers.ModelSerializer):
    pet_props = PropsSerializer(read_only=True, many=True)
    pet = serializers.SlugRelatedField(slug_field='name')

    class Meta:
        model = models.Day
        fields = ("id", "day", "pet", "pet_props")

此序列化程序的表示会将宠物的name 作为pet 字段的值。同样在写作时,这允许您使用宠物的name 来引用pet 实例,这解决了您问题中的实际问题。

(从技术上讲,您也可以使用pet_name = serializers.SlugRelatedField(slug_field='name'),但我不会这样做以避免混淆。)

不过,我建议您对宠物的 name 属性设置一个唯一约束。

【讨论】:

  • 还有一个问题,我怎么只允许用户自己的宠物。被选中?
  • 表示认证用户
  • 只让他得到他拥有的宠物。在他的认证帐户下
  • 有多种方法可以做到这一点,例如,您可以将用户传递到序列化程序的上下文中,然后在序列化程序上放入 validate 方法(然后将用户从上下文中取出并验证获取的Pet 对象)。查看 drf 序列化程序验证,如果您无法弄清楚,请随时在 Stack Overflow 上提出另一个问题,否则会混淆这个问题。您能否也将您的序列化程序和模型代码放回原始问题中?这可能会帮助那些也偶然发现这个问题的人。
  • 有什么帮助吗?如何只允许发布用户创建的宠物?
【解决方案2】:

如果只想显示一些只读数据,可以使用SerializerMethodField

from django.core.exceptions import ObjectDoesNotExist

class DaySerializer(serializers.ModelSerializer):
    pet_name = serializers.SerializerMethodField()

    def get_pet_name(self, obj):
        try:
            return obj.pet_name.name
        except ObjectDoesNotExist:
            # the day object doesn't have any
            # pet associated, so return None
            return None

注意:最好将 pet_name 外键更改为 pet,因为它包含一个 Pet 实例,而不仅仅是它的名称。

【讨论】:

  • 所以我不会分配一个数字主键,而是分配一个现有的宠物名称,对吧?
  • 我不会使用SerializerMethodField,这只会在获取数据的情况下有所帮助,而不是在写入数据时。我使用SlugRelatedField 的建议解决方案将解决这两种情况。
  • 你能提供一些代码吗?我对此有点陌生:D
  • @GlennDJ 是的,我已经提到该解决方案用于显示只读数据。它将不可编辑。
  • 非常感谢,最后一件事...您可以推荐任何课程来像专业人士一样学习休息框架吗?
猜你喜欢
  • 2021-12-09
  • 2019-02-28
  • 2017-11-02
  • 2016-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多