Атрибут changed_data
Атрибут changed_data класса Form возвращает список имен полей, значения которых были изменены пользователем в процессе отправки формы. Он доступен только для связанных форм, то есть когда форма привязана к данным. Данный атрибут полезен для проверки того, какие данные пользователь изменил, и может использоваться для логирования, отправки уведомлений или другой логики, основанной на измененных данных.
Синтаксис
form.changed_data
Атрибут возвращает список строк, где каждая строка - это имя поля, которое было изменено. Если изменения не были внесены, атрибут возвращает пустой список.
Пример
Рассмотрим простую форму для редактирования профиля пользователя:
from django import forms
class ProfileForm(forms.Form):
username = forms.CharField(max_length=100)
email = forms.EmailField()
age = forms.IntegerField()
Создадим экземпляр формы с начальными данными, затем привяжем его к новым данным и проверим атрибут changed_data:
from myapp.forms import ProfileForm
from django import forms
# Initial data
initial_data = {
"username": "john_doe",
"email": "john@example.com",
"age": 30
}
# Bound data with changes
bound_data = {
"username": "john_doe",
"email": "john_new@example.com",
"age": 31
}
form = ProfileForm(data=bound_data, initial=initial_data)
is_valid = form.is_valid()
res = form.changed_data
print(res)
Результат выполнения кода:
["email", "age"]
Пример
Рассмотрим, как использовать changed_data для выполнения действий только при изменении определенного поля. Например, мы можем отправить уведомление, если пользователь изменил свой email:
from django import forms
from myapp.models import User
from myapp.services import send_email_notification
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ["username", "email", "age"]
def save(self, commit=True):
user = super().save(commit=False)
if "email" in self.changed_data:
send_email_notification(user.email)
if commit:
user.save()
return user
В этом примере, после валидации формы, метод save проверяет, было ли поле email в списке измененных полей. Если да - отправляется уведомление.
Пример
Атрибут changed_data также работает с формами, которые используют начальные данные. Если форма не была изменена, список будет пустым:
from myapp.forms import ProfileForm
initial_data = {
"username": "alex_smith",
"email": "alex@example.com",
"age": 25
}
bound_data = {
"username": "alex_smith",
"email": "alex@example.com",
"age": 25
}
form = ProfileForm(data=bound_data, initial=initial_data)
is_valid = form.is_valid()
res = form.changed_data
print(res)
Результат выполнения кода:
[]
Как видно, несмотря на то, что форма была связана, изменения не были внесены, и список остается пустым.
Пример
В некоторых случаях полезно использовать changed_data для условной валидации. Например, мы можем запретить изменение email, если пользователь уже изменил его ранее:
from django import forms
from django.core.exceptions import ValidationError
class ProfileForm(forms.Form):
username = forms.CharField(max_length=100)
email = forms.EmailField()
age = forms.IntegerField()
def clean_email(self):
email = self.cleaned_data["email"]
if "email" in self.changed_data:
raise ValidationError("Email cannot be changed.")
return email
В этом примере, если поле email находится в списке измененных полей, возникает ошибка валидации, и форма не будет сохранена.
Смотрите также
-
атрибут
cleaned_data,
который содержит валидированные данные формы -
метод
has_changed,
который проверяет, были ли изменения в данных формы -
атрибут
is_bound,
который проверяет, связана ли форма с данными -
атрибут
initial,
который содержит начальные данные формы