【问题标题】:django-rest-framework Overriding create function not working on ModelSerializerdjango-rest-framework 覆盖创建函数在 ModelSerializer 上不起作用
【发布时间】:2020-02-02 21:41:52
【问题描述】:

我只想将新数据插入到我的数据库中。如果具有相同主键的数据已经在数据库中,我想忽略它而不引发异常。但是,如果表中已经存在该值,则默认 ModelSerializer 的创建函数似乎会引发异常。所以,我试图通过覆盖 ModelSerializer 的 create() 函数来解决这个问题。

这是我的代码:

序列化器.py

class UsrPlaceMapSerializer(serializers.ModelSerializer):
    class Meta:
        model = UsrPlaceMap
        fields = '__all__'

    def create(self, validated_data):
        place_id = validated_data.get("ggl_plc_id")
        place_map = UsrPlaceMap.objects.filter(ggl_plc_id=place_id)

        print("USRMAP INIT")

        if place_map is not None:
            print("USRMAP NOT NONE")
            return place_map

        place_map = UsrPlaceMap.objects.create(ggl_plc_id=place_id, state=validated_data.get("state"),
                                               cty_nm=validated_data.get("cty_nm"), cntry=validated_data.get("cntry"))
        print("USRMAP CREATED")

        return place_map

models.py

class UsrPlaceMap(models.Model):
    cty_nm = models.CharField(max_length=500)
    state = models.CharField(max_length=200, blank=True, null=True)
    cntry = models.CharField(max_length=500)
    ggl_plc_id = models.CharField(primary_key=True, max_length=500)

    class Meta:
        managed = False
        db_table = 'usr_place_map'

我正在使用这个调用序列化程序实例的保存方法:

instance = UsrPlaceMapSerializer(data=data, many=True)
if instance.is_valid():
    instance.save()

如果我提交新值,这些值会被保存。但是,如果我尝试提交表中已有的值,则会收到错误消息:

 {
            "ggl_plc_id": [
                "usr place map with this ggl plc id already exists."
            ]
        }
}

覆盖的 create() 上的打印语句也不打印任何内容。所以,我猜测被覆盖的方法根本没有运行。我做错了什么或者解决这个问题的正确方法是什么?谢谢。

【问题讨论】:

  • 您可能正在尝试创建一个与现有 ggl_place_id 上相同内容的 UsrPlaceMap。发生这种情况是因为您在该字段上有primary_key=True。解决方案不是覆盖序列化程序上的create 方法,而是在可能的情况下删除primary_key=True
  • 您可能希望使用logging 来帮助您调试与printHere 是文档

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


【解决方案1】:

我认为问题在于您检查查询集是否为None

if place_map is not None:
    print("USRMAP NOT NONE")
    return place_map

所以在这个place_map = UsrPlaceMap.objects.filter(ggl_plc_id=place_id) 你有一个变量place_map,它是一个queryset。您可以查看如何确定 queryset 是否返回了一些数据 here

【讨论】:

    【解决方案2】:

    您收到的错误消息是在调用 create 之前完成的序列化程序验证的结果。

    如果不调用is_valid,就不能调用serializer.save()(你会得到类似的错误:You must call .is_valid() before calling .save())。

    所以你的代码 sn-p 不完整。

    在您的模型中,您在字段 ggl_plc_id 上有主键,因此当您发出创建此类对象的发布请求时,它会验证字段值,因为它是主键,所以它必须是唯一的。

    如果我理解正确,如果新记录不存在,你想插入它。

    我建议在视图中处理它。这意味着您检查此类记录是否存在,如果存在,则使用序列化器对现有记录进行序列化,否则使用它来创建记录。

    【讨论】:

    • 谢谢。我会考虑在视图中执行此操作。覆盖验证器是个好主意吗?
    • @SarthakAdhikari 因为您想返回现有对象,如果您尝试走“oververriding vaidator”路线,您需要实现一些逻辑 - 就我个人而言,我不太喜欢。只需在视图中处理它。它会更容易理解。
    猜你喜欢
    • 2021-07-30
    • 1970-01-01
    • 2017-03-21
    • 1970-01-01
    • 1970-01-01
    • 2015-10-06
    • 1970-01-01
    • 2014-09-21
    • 2017-06-15
    相关资源
    最近更新 更多