django-저장하기 전에 이전 필드 값과 새 필드 값 비교
장고 모델이 있고 저장하기 전에 필드의 이전 값과 새 값을 비교해야합니다.
save () 상속과 pre_save 신호를 시도했습니다. 올바르게 트리거되었지만 실제로 변경된 필드 목록을 찾을 수없고 이전 값과 새 값을 비교할 수 없습니다. 방법이 있습니까? 사전 저장 작업의 최적화를 위해 필요합니다.
감사합니다!
아주 간단한 장고 방식이 있습니다.
다음과 같이 모델 초기화의 값을 "기억"합니다.
def __init__(self, *args, **kwargs):
super(MyClass, self).__init__(*args, **kwargs)
self.initial_parametername = self.parametername
---
self.initial_parameternameX = self.parameternameX
실제 예 :
수업에서 :
def __init__(self, *args, **kwargs):
super(MyClass, self).__init__(*args, **kwargs)
self.__important_fields = ['target_type', 'target_id', 'target_object', 'number', 'chain', 'expiration_date']
for field in self.__important_fields:
setattr(self, '__original_%s' % field, getattr(self, field))
def has_changed(self):
for field in self.__important_fields:
orig = '__original_%s' % field
if getattr(self, orig) != getattr(self, field):
return True
return False
그런 다음 modelform 저장 방법에서 :
def save(self, force_insert=False, force_update=False, commit=True):
# Prep the data
obj = super(MyClassForm, self).save(commit=False)
if obj.has_changed():
# If we're down with commitment, save this shit
if commit:
obj.save(force_insert=True)
return obj
ModelForm 수준 에서이 작업을 수행하는 것이 좋습니다 .
저장 방법에서 비교에 필요한 모든 데이터를 얻을 수 있습니다.
- self.data : Form에 전달 된 실제 데이터.
- self.cleaned_data : 검증 후 정리 된 데이터, 모델에 저장할 수있는 데이터 포함
- self.changed_data : 변경된 필드 목록. 아무것도 변경되지 않으면 비어 있습니다.
모델 수준에서이 작업을 수행하려면 Odif의 답변에 지정된 방법을 따를 수 있습니다.
또한 django-model-utils 에서 FieldTracker 를 사용할 수 있습니다 .
모델에 트래커 필드를 추가하기 만하면됩니다.
tracker = FieldTracker()
이제 pre_save 및 post_save에서 다음을 사용할 수 있습니다.
instance.tracker.previous('modelfield') # get the previous value instance.tracker.has_changed('modelfield') # just check if it is changed
다음은 모델이 저장되기 직전에 필드의 이전 값과 현재 값에 액세스 할 수있는 앱입니다. django-smartfields
다음은이 문제를 좋은 선언적 방법으로 해결할 수있는 방법입니다.
from django.db import models
from smartfields import fields, processors
from smartfields.dependencies import Dependency
class ConditionalProcessor(processors.BaseProcessor):
def process(self, value, stashed_value=None, **kwargs):
if value != stashed_value:
# do any necessary modifications to new value
value = ...
return value
class MyModel(models.Model):
my_field = fields.CharField(max_length=10, dependencies=[
Dependency(processor=ConditionalProcessor())
])
또한이 프로세서는 해당 필드의 값이 대체 된 경우에만 호출됩니다.
My use case for this was that I needed to set a denormalized value in the model whenever some field changed its value. However, as the field being monitored was a m2m relation, I didn't want to have to do that DB lookup whenever save was called in order to check whether the denormalized field needed updating. So, instead I wrote this little mixin (using @Odif Yitsaeb's answer as inspiration) in order to only update the denormalized field when necessary.
class HasChangedMixin(object):
""" this mixin gives subclasses the ability to set fields for which they want to monitor if the field value changes """
monitor_fields = []
def __init__(self, *args, **kwargs):
super(HasChangedMixin, self).__init__(*args, **kwargs)
self.field_trackers = {}
def __setattr__(self, key, value):
super(HasChangedMixin, self).__setattr__(key, value)
if key in self.monitor_fields and key not in self.field_trackers:
self.field_trackers[key] = value
def changed_fields(self):
"""
:return: `list` of `str` the names of all monitor_fields which have changed
"""
changed_fields = []
for field, initial_field_val in self.field_trackers.items():
if getattr(self, field) != initial_field_val:
changed_fields.append(field)
return changed_fields
I agree with Sahil that it is better and easier to do this with ModelForm. However, you would customize the ModelForm's clean method and perform validation there. In my case, I wanted to prevent updates to a model's instance if a field on the model is set.
My code looked like this:
from django.forms import ModelForm
class ExampleForm(ModelForm):
def clean(self):
cleaned_data = super(ExampleForm, self).clean()
if self.instance.field:
raise Exception
return cleaned_data
Something like this also works:
class MyModel(models.Model):
my_field = fields.IntegerField()
def save(self, *args, **kwargs):
# Compare old vs new
if self.pk:
obj = MyModel.objects.values('my_value').get(pk=self.pk)
if obj['my_value'] != self.my_value:
# Do stuff...
pass
super().save(*args, **kwargs)
ReferenceURL : https://stackoverflow.com/questions/23361057/django-comparing-old-and-new-field-value-before-saving
'programing' 카테고리의 다른 글
내 GitHub 계정 오류로 git 설정 문제 : 구성 파일을 잠글 수 없습니다. (0) | 2021.01.17 |
---|---|
Nginx로 PHP를 실행할 때 파일을 찾을 수 없음 (0) | 2021.01.17 |
Java에서 이벤트의 경과 시간을 어떻게 계산합니까? (0) | 2021.01.17 |
탭에서 Winforms NumericUpDown의 모든 텍스트를 선택하는 방법은 무엇입니까? (0) | 2021.01.17 |
파이썬에서 삼중 따옴표 안에 변수를 넣을 수 있습니까? (0) | 2021.01.17 |