当前位置: 首页 > 知识库问答 >
问题:

Django Rest框架:如何在验证序列化程序时忽略唯一主键约束?

汪德寿
2023-03-14

我试图在PostgreSQL数据库中存储大量传输数据,客户端一次上传多个记录(数万条)。我只需要一个到达时间,每站,每条路线,每趟行程和唯一的标识符为该站,路线,行程是我的表的主键(和一个外键在不同的表)。我正在尝试在我的序列化器中使用Django的update_or_create来创建到达时间的条目,或者使用已经存在的最新数据更新到达时间。不幸的是,在我的序列化程序上调用is_valid()时,它发现重复记录违反了主键的唯一性约束(这是有意义的),给我这个错误消息:

'real_id': [ErrorDetail(string='actual with this real id already exists.', code='unique')]

我想重写这个行为,因为如果主键不是唯一的,它只会更新条目。我已经尝试过循环并删除验证程序,如下所示:

    def run_validators(self, value):
        for validator in self.validators:
            self.validators.remove(validator)
        super(ActualSerializer, self).run_validators(value)

我还尝试使用序列化器元类的extra_kwargs字段删除所有验证器,如下所示:

extra_kwargs = {
            'name': {'validators': []}
        }

我真的不想在我的视图中进行插入,因为理想情况下,序列化器正在解析值并验证其他约束。

但这些解决方案都没有改变任何事情。我找不到其他可以解决我问题的东西(但如果有人找到我错过的答案,那将是天赐良机)。我想我的问题与这个问题有些相似,但那个问题没有一个好的答案。

作为参考,我的序列化程序文件:

from .models import Future, Actual
from rest_framework import serializers


class ActualSerializer(serializers.ModelSerializer):

    def create(self, validated_data):
        actual, created = Actual.objects.update_or_create(
            real_id=validated_data['real_id'],
            defaults={'arrival': validated_data.get('arrival', None)}
        )
        return actual

    class Meta:
        model = Actual
        fields = ['real_id', 'arrival']


class FutureSerializer(serializers.ModelSerializer):

    class Meta:
        model = Future
        fields = ['row_id', 'stop_id', 'route_id', 'record_time', 'predicted_arrival', 'delay', 'real_id']

我的模型

from django.db import models
import json


class Actual(models.Model):
    real_id = models.CharField(max_length=100, primary_key=True)
    arrival = models.BigIntegerField(null=True)

    def __str__(self):
        return json.dumps([self.real_id, self.arrival])


class Future(models.Model):
    row_id = models.BigAutoField(primary_key=True)
    stop_id = models.CharField(max_length=20)
    route_id = models.CharField(max_length=10)
    record_time = models.BigIntegerField()
    predicted_arrival = models.IntegerField(null=True)
    delay = models.IntegerField()
    real_id = models.ForeignKey(Actual, on_delete=models.CASCADE)

    def __str__(self):
        return json.dumps([self.row_id,
                           self.stop_id,
                           self.route_id,
                           self.record_time,
                           self.predicted_arrival,
                           self.delay,
                           self.real_id])

最后,我的观点是:

class ArrivalData(APIView):

    queryset = Future.objects.all()
    permission_classes = [OperationAllowed]

    def post(self, request: Request, format=None) -> Response:
        parsed_data = json.loads(request.data['data'])
        actual_arrivals = []
        for datum in parsed_data:
            saved_time = None
            if datum['predicted_arrival'] is not None and -200 < datum['predicted_arrival'] - datum['record_time'] < 0:
                saved_time = datum['predicted_arrival']

            actual_arrivals.append({
                'real_id': datum['real_id'],
                'arrival': saved_time,
            })

        actual_serializer = ActualSerializer(data=actual_arrivals, many=True)
        if actual_serializer.is_valid(raise_exception=False):
            actual_serializer.save()
        future_serializer = FutureSerializer(data=parsed_data, many=True)

        if future_serializer.is_valid():

            future_serializer.save()
            return Response("Data saved")
        
        return Response(str(actual_serializer.errors))

共有1个答案

年文柏
2023-03-14

因此,唯一的约束是字段级别的验证器,这就是为什么试图在类级别删除它不起作用。

我在serializer类中显式声明了字段,但没有任何验证器real\u id=serializers.CharField(validators=[]),这解决了问题。

如果其他人有这个问题,这个页面最终帮助了我。

 类似资料:
  • 问题内容: 我有一个MySQL表来保存标签(即像在Stack Overflow上使用的那些标签)。它仅具有一个id(pk)和一个标签列来保存标签本身。 我的Tag实体的带注释的get方法如下所示。 我在标签上使用了唯一的列约束,因为给定标签的行不应超过一行。但是,Hibernate似乎忽略了这一点,即我可以多次保存完全相同的标签,并且它只是创建一个新行而不是抛出异常。 我是否缺少某些东西,还是应该

  • 有没有一种方法让我忽略这些异常并在消费者处移动偏移量?我想,因为我使用手动偏移提交,我有这个问题。有人知道如何配置kafka-avro-serializer-6.0.0.jar来完成我想要的任务吗? 多谢了。

  • 问题内容: 我使用以下代码来序列化从外部服务获得的响应,并作为我的服务的一部分返回json响应。但是,当外部服务返回带有时区(10:30:00.000-05.00)的时间值时,杰克逊会将其转换为15:30:00。如何忽略时区值? 问题答案: 您可以创建自定义解串器 告诉杰克逊使用您的自定义解串器 并像这样使用它: 您可以使用Jackson自定义序列化为服务响应添加时区信息

  • 问题内容: 我有一个简单的接口与属性的getter和setter。 我还有另一个实现此接口的UserAccount类。 我的问题是我想序列化money属性,但在反序列化它时忽略它,即,不接受用户对此属性的任何值。我在setter上尝试过@JsonIgnore,在getter上尝试过@JsonIgnore(false),它确实会忽略它,但是在序列化它时也会这样做。 我在setter上尝试了@Json

  • 在这种情况下,如果验证失败,我希望将请求返回给用户,并附上相应的错误消息。我遇到的问题是,我使用Jackson处理JSON请求,验证失败也会导致Jackson无法序列化消息。 例如,如果我有此对象: ...当我去序列化时,字段无效(假设它有11个字符)... ...我得到了一个JsonProcessingException(错误验证对象)。我已经确认一个有效的对象序列化没有问题。所以我的问题是:我

  • 我有另一个类UserAccount实现了这个接口。 我的问题是,我想序列化money属性,但在反序列化时忽略它,即不接受用户对该属性的任何值。我在setter上尝试了@jsonIgnore,在getter上尝试了@jsonIgnore(false),它确实忽略了它,但是它在序列化它的同时也忽略了它。 我在setter上尝试了@jsonIgnore,在getter上尝试了@jsonProperty,