我们正在尝试实施时态数据库,以便我们能够跟踪所做的更改
我们所有型号都有以下字段
vt = models.DateTimeField(db_column='VT', default=datetime(3000, 12, 31, 23, 00, 00, 000000)) # Value To
vflag = models.IntegerField(db_column='VFlag', default=1) # Version Flag 1 = Current, 0 = Old
当使用Django rest框架时,我试图修改视图中的perform_update以复制现有记录,进行更新,然后适当地设置时间字段。
当我有1条记录和第一次更新
时,它会起作用但是,一旦我尝试进行第二次更新,它就会失败并创建更改副本并覆盖第一条记录。
原始记录
Currency = AUD, VFlag = 1, VT = time1
执行更新 - 成功
Currency = USD, VFlag = 1, VT = time2
Currency = AUD, VFlag = 0, VT = time1
接下来执行当前生成的更新 - 失败
Currency = GBP, VFlag = 1, VT = time3
Currency = GBP, VFlag = 1, VT = time3
Currency = USD , VFlag = 0, VF = time2
预期的更新输出
Currency = GBP, VFlag = 1, VT = time3
Currency = USD, VFlag = 0, VT = time2
Currency = AUD, VFlag = 0, VT = time1
暂时数据库是否可能在django休息?
是否有人能够指出正确的方向
以下是我的观看设置代码
class OptionMasterViewSet(viewsets.ModelViewSet):
serializer_class = OptionMasterSerializer
paginate_by = None
queryset = OptionMaster.objects.filter(vflag=1)
# queryset = OptionMaster.objects.all()
def get_queryset(self):
queryset = OptionMaster.objects.filter(vflag=1)
contractcode = self.request.query_params.get('contractcode', None)
if contractcode is not None:
queryset = queryset.filter(contractcode=contractcode, vflag=1)
return queryset
def perform_update(self, serializer):
changes = serializer.validated_data
original_object = serializer.instance
vt = datetime.now()
changes['vf'] = vt
#Build the old record
old_record = {}
for field in original_object._meta.get_fields():
old_record[field.name] = getattr(original_object, field.name)
old_record['vflag'] = 0
old_record['vt'] = vt
old_record = OrderedDict(old_record)
#Save the new rrecord
serializer.save()
#Create the old record
obj = OptionMaster.objects.create(**old_record)
return serializer
我的序列化
class OptionMasterSerializer(TemporalModelSerializer):
class Meta:
model = OptionMaster
fields = '__all__'
潜在的时间序列化器
class TemporalHyperlinkedModelSerializer(serializers.HyperlinkedModelSerializer):
vt = serializers.HiddenField(default=datetime(3000, 12, 31, 00, 00, 00, 000000))
vflag = serializers.HiddenField(default=1)
class TemporalModelSerializer(serializers.ModelSerializer):
vt = serializers.HiddenField(default=datetime(3000, 12, 31, 23, 00, 00, 000000))
vflag = serializers.HiddenField(default=1)
class TemporalModel(models.Model):
vt = models.DateTimeField(db_column='VT') # Field name made lowercase.
vflag = models.IntegerField(db_column='VFlag') # Field name made lowercase..
class Meta:
abstract = True
答案 0 :(得分:1)
我的问题的解决方案是使用字典数据进行FILTER和UPDATE。
self.Meta.model.objects.filter(pk=instance.pk, vflag=1).update(**new_record)
这是我最后工作的TemporalModelSerializer
class TemporalModelSerializer(serializers.ModelSerializer):
vf = serializers.HiddenField(default=timezone.now())
vt = serializers.HiddenField(default=datetime(3000, 12, 31, 23, 00, 00, 000000))
vflag = serializers.HiddenField(default=1)
vu = serializers.HiddenField(default='Theodore')
class Meta:
model = None
fields = '__all__'
def update(self, instance, validated_data):
time_now = timezone.now()
old_record = {}
new_record = {}
for (key, value) in validated_data.items():
old_record[key] = getattr(instance, key)
new_record[key] = validated_data[key]
setattr(instance, key, value)
old_record['vt'] = time_now
old_record['vflag'] = 0
new_record['vf'] = time_now
self.delete_me(old_record)
self.Meta.model.objects.filter(pk=instance.pk, vflag=1).update(**new_record)
return instance
def delete_me(self, old_record):
obj = self.Meta.model.objects.create(**old_record)
答案 1 :(得分:0)
Tbh,我以前从未处理过这样的问题,但这比django-rest更多的是数据库设计问题。因此,在不了解这些模型的目的和关系的情况下,我只能做出一个估计的猜测(如下)。
我的一个直观方法是实现额外的IntegerField
被称为series_group_id
的内容,它将作为分组时间序列的标识符和created_add
{{ 1}} DateTimeField
标志设置为auto_now_add
。这样,此字段在创建时将填充True
值。
datetime
更重要的是,如果您要跟踪时间序列,那么从技术上讲,您不会更新实例,而是创建新实例。因此,我的方法是将整个逻辑移到class SomeModel(models.Model):
# some other stuff like vflag and vt
goup_id = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
方法。实际上,ModelSerializer提供了开箱即用的这种行为。您唯一需要做的就是将create
添加到序列化程序的group_id
元组中。当您使用“所有”时,只要您将字段添加到模型中,该字段就会自动显示在您的字段中。
如果您需要更精细的控制,可以覆盖fields
方法,如下所示:
create
此方法预计到达的数据包含您当前正在跟踪的相应时间序列的class OptionMasterViewSet(viewsets.ModelViewSet):
serializer_class = OptionMasterSerializer
paginate_by = None
queryset = OptionMaster.objects.filter(vflag=1)
def get_queryset(self):
queryset = OptionMaster.objects.filter(vflag=1)
contractcode = self.request.query_params.get('contractcode', None)
if contractcode is not None:
queryset = queryset.filter(contractcode=contractcode, vflag=1)
return queryset
def create(self, request):
data = request.get('data', None)
serializer = self.serializer_class(data=data)
serializer.is_valid(raise_exception=True)
# some custom logic here in case you need it..
self.perform_create(serializer)
return Response({'detail': 'ok'}, status=status.HTTP_201_CREATED)
。