【问题标题】:Create Object with Foreign key with Serializer使用序列化程序创建具有外键的对象
【发布时间】:2020-02-05 07:51:54
【问题描述】:

所以我想用序列化器创建一个反馈对象:

class Location(models.Model):
    name = models.CharField(max_length=256)
    img_small = models.CharField(max_length=1024, blank=True, null=True)
    img_large = models.CharField(max_length=1024, blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'location'

class Schedules(models.Model):
    user = models.ForeignKey(Users, models.DO_NOTHING, default=None)
    name = models.CharField(max_length=512, blank=True, null=True)
    location = models.ForeignKey(Location, models.DO_NOTHING, default=None)
    detail = models.TextField(blank=True, null=True)
    start = models.DateField()
    end = models.DateField()
    created = models.DateTimeField(blank=True, null=True)
    modified = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'schedules'

class Feedbacks(models.Model):
    location = models.ForeignKey(Location, models.DO_NOTHING)
    schedule = models.ForeignKey(Schedules, models.DO_NOTHING)
    start = models.IntegerField(blank=True, null=True)
    end = models.IntegerField(blank=True, null=True)
    created = models.DateTimeField(blank=True, null=True)
    modified = models.DateTimeField(blank=True, null=True)

    class Meta:
        managed = True
        db_table = 'feedbacks'

和序列化程序类:

class FeedbackSerializer(serializers.ModelSerializer):
    location_id = serializers.PrimaryKeyRelatedField(queryset=Location.objects.all())
    schedule_id = serializers.PrimaryKeyRelatedField(queryset=Schedules.objects.all())
    class Meta:
        model = Feedbacks
        fields = ('location_id', 'schedule_id', 'start', 'end')
        # read_only_fields = ('location_id', 'schedule_id')

我的数据是

{"location_id" : 2, "schedule_id" : 2, "start" : "1", "end" : 2}

问题是验证后我的验证数据包含 Location 和 Schedule 对象,而不是 id,所以我无法插入并收到此错误

int() argument must be a string, a bytes-like object or a number, not 'Location'

【问题讨论】:

  • 这行得通吗? - location_id = serializers.PrimaryKeyRelatedField(queryset=Location.objects.all(), source='location')
  • 是的,它有效。非常感谢。但是你能解释一下这是如何工作的吗?据我了解,“源”关键字告诉我该字段属于模型的哪个属性。但是如果我不需要用 start 和 end 来做,为什么 location_id 和 schedule_id 不一样?
  • 要了解实际问题,您需要了解 django 模型在定义 ForeignKey 字段时是如何工作的。例如,如果您将 location 定义为 FK,那么在幕后您还会得到一个 location_id,它是它的实际 id(不是实例,它位于 location 字段上)。您可以尝试在 Feedback 对象上打印这些字段并查看差异。如果您输入 location_id,则返回序列化程序,它期望它的 id 不是 Location 的实例(您得到它是因为 PrimaryKeyRelatedField 在验证后返回),因此您会收到错误。
  • @GabrielMuj 我现在有点理解这个概念,但对我来说,它仍然感觉有点奇怪。验证过程知道 location_id 是一个 int,它指的是 location 对象的 id,但仍然返回该对象。
  • @NhatTon 即使您发送了 id,您也会因为来自 PrimaryKeyRelatedField 的方法 to_internal_value 而取回对象。该方法使用queryset,然后在id 上执行get(您可以查看它的源代码)。所以你得到的实际结果是Location 的实例。仅出于测试和学习目的,请尝试将IntegerField(如果您的主键是 int)用于location_id,这应该可以工作,因为它将被转换为 int 而不是位置实例。

标签: django django-rest-framework django-serializer


【解决方案1】:

如果我这样做,它也有效。我有点糊涂了。

class FeedbackSerializer(serializers.ModelSerializer):
    location = serializers.PrimaryKeyRelatedField(queryset=Location.objects.all())
    schedule = serializers.PrimaryKeyRelatedField(queryset=Schedules.objects.all())
    class Meta:
        model = Feedbacks
        fields = ('location', 'schedule', 'start', 'end')

【讨论】:

  • 我可能已经想通了。显然,要反序列化我什至不需要属性,只需将字段 location_id 更改为 location 并将 schedule_id 更改为 schedule
猜你喜欢
  • 1970-01-01
  • 2015-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-17
  • 1970-01-01
  • 2015-08-15
相关资源
最近更新 更多