When creating a flatpage, I want the user to select a template from a predefined list. In order to keep the Flatpage
model untouched, I prefer ChoiceField
over ModelChoiceField
(the latter provides the PK of the template, but I need the name for the template_name field):
class NewFlatpageForm(FlatpageForm):
template_name = forms.ChoiceField(choices = [])
def __init__(self, *args, **kwargs):
self.base_fields['template_name'].choices = ProjectTemplate.objects.values_list('path', 'name')
super(NewFlatpageForm, self).__init__(*args, **kwargs)
I override __init__
or Django populates choices at server start and does not update the list then.
I don't have any admin experience, but I did similar things using the fields
attribute when not using admin. However in this case, I got an exception telling fields
is not an attribute of the form. __dict__
showed me there's a base_fields
attribute and using it works. So, why use base_fields here, and why is fields
not present and finally am I doing something hacky?
Fields in Django are the data types to store a particular type of data. For example, to store an integer, IntegerField would be used. These fields have in-built validation for a particular data type, that is you can not store “abc” in an IntegerField.
The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class. It returns True if data is valid and place all data into a cleaned_data attribute. Let's see an example that takes user input and validate input as well.
Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.
Every field comes in with built-in validations from Django validators. One can also add more built-in field validations for applying or removing certain constraints on a particular field. editable=False will make the field disappear from all forms including admin and ModelForm i.e., it can not be edited using any form.
fields
doesn't exist until after you've called super
. So just swap the order of the lines, so that super
comes first.
In addition to Joe Germuska. If you truly need to change the form based on the request, you can use a deepcopy to make sure nothing is changed by reference:
def get_form(self, request, obj=None, **kwargs):
form = super(ResourceAdmin, self).get_form(request, obj, **kwargs)
form = copy.deepcopy(form)
if obj:
form.base_fields['email'] = EmailField(initial=obj.user.email)
if not request.user.is_superuser:
form.base_fields['user'].widget = HiddenInput(attrs={'class': 'hide_form_row'})
return form
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With