Should this be considered a bug? When you provide the to_field_name to a
ModelChoiceField, the instance object's field (the primary key) will not
match the form's field (the to_field_name field name). Therefore the
has_changed() function will return True. In my example, I created an app
called 'app'.
############ app/models.py ###########
from django.conf import settings
from django.db import models
class Account(models.Model):
""" Each user has an account """
name = models.CharField(max_length=64)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True)
description = models.TextField()
############ app/forms.py ###########
from django import forms
from django.apps import apps
from django.contrib.auth import get_user_model
class AccountForm(forms.ModelForm):
class Meta:
model = apps.get_model('app.Account')
fields = ['user', 'name', 'description']
user = forms.ModelChoiceField(get_user_model().objects,
to_field_name='username')
############ FROM DJANGO SHELL ###########
In [1]: from app.models import Account
In [2]: from app.forms import AccountForm
In [3]: from django.contrib.auth import get_user_model
In [4]: username = 'mynewname'
In [5]: usr = get_user_model().objects.get_or_create(username=username)[0]
In [6]: obj = Account.objects.get_or_create(name='abc', user=usr,
description='aaa')[0]
In [7]: new_form = {'name': obj.name, 'user': username, 'description': 'aaa'}
In [8]: frm = AccountForm(new_form, instance=obj)
In [9]: assert frm.is_valid()
In [10]: assert frm.cleaned_data['user'] == usr
In [11]: assert frm.cleaned_data['user'] == obj.user
In [12]: frm.has_changed()
Out[12]: *True*
In [13]: frm.changed_data
Out[13]: *['user']*
##########################################
# My Override of the ModelChoiceField #
##########################################
############# app/forms.py ############
from django import forms
from django.apps import apps
from django.contrib.auth import get_user_model
class UsernameToObjectField(forms.ModelChoiceField):
""" Take a the value of a name and return the object. """
def has_changed(self, initial, data):
if self.to_field_name is not None:
data_value = self.to_python(data) if data is not None else ''
if data_value is not None:
data_value = data_value.pk
else:
data_value = data
return super(UsernameToObjectField, self).has_changed(initial,
data_value)
class AccountForm(forms.ModelForm):
class Meta:
model = apps.get_model('app.Account')
fields = ['user', 'name', 'description']
user = UsernameToObjectField(get_user_model().objects,
to_field_name='username')
############ FROM DJANGO SHELL ###########
In [1]: from app.models import Account
In [2]: from app.forms import AccountForm
In [3]: from django.contrib.auth import get_user_model
In [4]: username = 'mynewname'
In [5]: usr = get_user_model().objects.get_or_create(username=username)[0]
In [6]: obj = Account.objects.get_or_create(name='abc', user=usr,
description='aaa')[0]
In [7]: new_form = {'name': obj.name, 'user': username, 'description': 'aaa'}
In [8]: frm = AccountForm(new_form, instance=obj)
In [9]: assert frm.is_valid()
In [10]: assert frm.cleaned_data['user'] == usr
In [11]: assert frm.cleaned_data['user'] == obj.user
In [12]: frm.has_changed()
Out[12]: *False*
In [13]: frm.changed_data
Out[13]: *[]*
--
You received this message because you are subscribed to the Google Groups
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-users/41095b7e-6bb5-4518-8558-dcbb86dc4047%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.