【发布时间】:2020-12-26 03:58:47
【问题描述】:
我正在尝试将大量交通数据存储在 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)
我还尝试使用序列化程序 Meta 类的 extra_kwargs 字段删除所有验证器,如下所示:
extra_kwargs = {
'name': {'validators': []}
}
我真的不想在我的视图中进行插入,因为理想情况下,序列化程序正在解析值并验证其他约束。
但是这些解决方案都没有改变任何东西。我在 SO 上找不到任何其他可以解决我的问题的东西(但如果有人找到我错过的答案,那将是天赐之物)。我认为我的问题与this question 有点相似,但没有一个好的答案。
作为参考,我的序列化程序文件:
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))
【问题讨论】:
标签: python django database postgresql django-rest-framework