#7006 closed (invalid)
Overridden fields/widgets for ForeignKeys in ModelForms
Reported by: | Owned by: | Manuel Saelices | |
---|---|---|---|
Component: | Forms | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The docs give the impression one can easily override fields/widgets in ModelForm declarations, but for ForeignKeys that doesn't seem to work.
http://www.djangoproject.com/documentation/modelforms/#overriding-the-default-field-types
class Booking(models.Model): ... affiliate = models.ForeignKey(Affiliate, null=True, blank=True, related_name='bookings') ... class BookingForm(forms.ModelForm): affiliate = forms.CharField(max_length=20, required=False, label='Affiliate Code') class Meta: model = Booking fields = ('first_name', 'last_name', 'company', 'email', 'phone', 'mobile', 'adults', 'children', 'affiliate', 'notes')
I need the user to be able to type the 'affiliate' key value straight in without using a dropdown, but using the above approach doesn't attempt to save the affiliate value at all, using r7409. Am I missing something or has this functionality not been catered for?
Change History (10)
comment:1 by , 16 years ago
follow-up: 3 comment:2 by , 16 years ago
Sorry - Apologies for my stupidity regarding the formatting and double post.
class Article(models.Model): title = models.CharField(max_length=100) class ArticleForm(ModelForm): pub_date = models.CharField('Bump!',max_length=10) class Meta: model = Article
comment:3 by , 16 years ago
milestone: | → 1.0 beta |
---|
FYI The correct output can be obtained by doing the following:
class Article(models.Model): title = models.CharField(max_length=100) class ArticleForm(ModelForm): class Meta: model = Article af = ArticleForm() af.base_fields['pub_date'] = forms.CharField(...)
Which then shows two fields. You can also overwrite a field using this same method.
An example of ModelForm has been referenced on this page:
http://www.djangoproject.com/documentation/models/model_forms/
which is also not working.
comment:4 by , 16 years ago
milestone: | 1.0 beta → 1.0 |
---|
Looks like just a normal bug, not a 1.0-beta thing.
comment:5 by , 16 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:6 by , 16 years ago
I suspect the issue here is that it still needs to be a ModelChoiceField
, though you can drop in whatever widget you like. Please check whether this works or not.
comment:7 by , 16 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:8 by , 16 years ago
I've tested ticket with this models and form (used admin site for test):
# Models class Affiliate(models.Model): name = models.CharField(max_length=100) class Booking(models.Model): first_name = models.CharField(max_length=100) last_name = models.CharField(max_length=100) affiliate = models.ForeignKey(Affiliate, null=True, blank=True, related_name='bookings') # Forms class BookingForm(forms.ModelForm): affiliate = forms.CharField(max_length=20, required=False, label='Affiliate Code') class Meta: model = Booking fields = ('first_name', 'last_name', 'affiliate') # Admin class BookingAdmin(admin.ModelAdmin): form = BookingForm admin.site.register(Affiliate) admin.site.register(Booking, BookingAdmin)
Admin rendered successfully a CharField
, but problem was adding a Booking
object.
The traceback I got when tried to adding a Booking
object with an affiliate value of '1'
was:
Traceback: File "/var/lib/python-support/python2.5/django/core/handlers/base.py" in get_response 86. response = callback(request, *callback_args, **callback_kwargs) File "/var/lib/python-support/python2.5/django/contrib/admin/sites.py" in root 173. return self.model_page(request, *url.split('/', 2)) File "/var/lib/python-support/python2.5/django/views/decorators/cache.py" in _wrapped_view_func 44. response = view_func(request, *args, **kwargs) File "/var/lib/python-support/python2.5/django/contrib/admin/sites.py" in model_page 192. return admin_obj(request, rest_of_url) File "/var/lib/python-support/python2.5/django/contrib/admin/options.py" in __call__ 185. return self.add_view(request) File "/var/lib/python-support/python2.5/django/db/transaction.py" in _commit_on_success 238. res = func(*args, **kw) File "/var/lib/python-support/python2.5/django/contrib/admin/options.py" in add_view 483. new_object = self.save_form(request, form, change=False) File "/var/lib/python-support/python2.5/django/contrib/admin/options.py" in save_form 361. return form.save(commit=False) File "/var/lib/python-support/python2.5/django/forms/models.py" in save 218. return save_instance(self, self.instance, self._meta.fields, fail_message, commit) File "/var/lib/python-support/python2.5/django/forms/models.py" in save_instance 43. f.save_form_data(instance, cleaned_data[f.name]) File "/var/lib/python-support/python2.5/django/db/models/fields/__init__.py" in save_form_data 406. setattr(instance, self.name, data) File "/var/lib/python-support/python2.5/django/db/models/fields/related.py" in __set__ 264. self.field.name, self.field.rel.to._meta.object_name)) Exception Type: ValueError at /admin/ticket7006/booking/add/ Exception Value: Cannot assign "u'1'": "Booking.affiliate" must be a "Affiliate" instance.
comment:9 by , 16 years ago
Resolution: | → invalid |
---|---|
Status: | assigned → closed |
I think error is the normal behaviour here. Validation success because is a simple CharField
, but when you save form, form.cleaned_data['affiliate']
is '1'
instead of a instance to Affiliate
.
This can be quickly done with this form (if you don't want to use other custom Field):
class BookingForm(forms.ModelForm): affiliate = forms.CharField(max_length=20, required=False, label='Affiliate Code') class Meta: model = Booking fields = ('first_name', 'last_name', 'affiliate') def clean_affiliate(self): value = self.cleaned_data['affiliate'] try: return Affiliate.objects.get(id=value) except Affiliate.DoesNotExist: raise ValidationError('Affiliate %s does not exist' % value)
I will mark this as invalid, because I think behaviour is right.
Re: Documentation on this page
http://www.djangoproject.com/documentation/modelforms/#overriding-the-default-field-types
class Article(models.Model):
class ArticleForm(ModelForm):
Output result is "Title: <input ...>"
So it seems the lack of an override is generic, and not just for ForeignKeys.