Struggling to figure out how to Over-Ride the __init__() method in my Django Form to include additional values from the database. I have a group of photographers that I am trying to list as a form option for the user. Afterwards, the user’s photographer selection will be added (along with other information) to the database as an instantiation of a new model.
This is a continuation, or elaboration, of my other Current Question. @Rob Osborne has given me some great advice helping me understand how to extend BaseForm, but I still cannot get my code to execute. The linked question lists my models, form, and views, if you are interested. While I understand that using ModelForm is easier and more documented, I must use BaseForm in this instance.
Here is what I have:
class AForm(BaseForm):
def __init__(self, data=None, files=None, instance=None, auto_id='id_%s',
prefix=None, initial=None, error_class=ErrorList,
label_suffix=':', empty_permitted=False):
self.instance = instance
object_data = self.instance.fields_dict()
self.declared_fields = SortedDict()
self.base_fields = fields_for_a(self.instance)
BaseForm.__init__(self, data, files, auto_id, prefix, object_data,
error_class, label_suffix, empty_permitted)
self.fields['photographer'].queryset = Photographer.objects.all()
def save(self, commit=True):
if not commit:
raise NotImplementedError("AForm.save must commit it's changes.")
if self.errors:
raise ValueError(_(u"The Form could not be updated because the data didn't validate."))
cleaned_data = self.cleaned_data
# save fieldvalues for self.instance
fields = field_list(self.instance)
for field in fields:
if field.enable_wysiwyg:
value = unicode(strip(cleaned_data[field.name]))
else:
value = unicode(cleaned_data[field.name])
Using the above code results in a KeyError at 'photographer'.
I appreciate any ideas / comments on how to resolve this KeyError so that I can get the photographer values into my form. Thank you!
EDIT:
Trying to use super, as recommended by @supervacuo, but still getting a KeyError at photographer as before:
class AForm(BaseForm):
def __init__(self, data=None, files=None, instance=None, auto_id='id_%s',
prefix=None, initial=None, error_class=ErrorList,
label_suffix=':', empty_permitted=False):
super(AForm, self).__init__(data, files, auto_id, prefix, object_data, error_class, label_suffix, empty_permitted)
self.fields['photographer'].queryset = Photographer.objects.all()
What could I be missing that is generating the KeyError? Thanks for any advice.
EDIT 2: adding fields_dict()
from models.py
class A(models.Model):
category = models.ForeignKey(Category)
user = models.ForeignKey(User)
def fields_dict(self):
fields_dict = {}
fields_dict['title'] = self.title
for key, value in self.fields():
fields_dict[key.name] = value.value
return fields_dict
Thanks for any advice.
EDIT 3: (edited class AForm above in the initial question as well, to include more information)
def fields_for_a(instance):
fields_dict = SortedDict()
fields = field_list(instance)
for field in fields:
if field.field_type == Field.BOOLEAN_FIELD:
fields_dict[field.name] = forms.BooleanField(label=field.label, required=False, help_text=field.help_text)
elif field.field_type == Field.CHAR_FIELD:
widget = forms.TextInput
fields_dict[field.name] = forms.CharField(label=field.label, required=field.required, max_length=field.max_length, help_text=field.help_text, widget=widget)
fields_dict[field.name] = field_type(label=field.label,
required=field.required,
help_text=field.help_text,
max_length=field.max_length,
widget=widget)
return fields_dict
EDIT 4: def fields(self). from models.py:
def fields(self):
fields_list = []
fields = list(self.category.field_set.all())
fields += list(Field.objects.filter(category=None))
for field in fields:
try:
fields_list.append((field, field.fieldvalue_set.get(ad=self),))
except FieldValue.DoesNotExist:
pass # If no value is associated with that field, skip it.
return fields_list
def field(self, name):
if name == 'title':
return self.title
else:
return FieldValue.objects.get(field__name=name, ad=self).value
That GitHub link should’ve been the first thing in your question.
The
django-classifiedsapplication has an entire system of dynamic fields (based on theFieldandFieldValuemodels) which is why you’re having trouble. If you don’t fully understand this aspect ofdjango-classifieds, I recommend you base your project on something else instead.Looking down the list of
FIELD_CHOICESindjango-classified‘smodels.py, you can’t use this database-driven field system to define relationsips — so there’s no dynamic per-categoryForeignKeyfield!The alternative would be to add a
photographerfield on yourAmodel (any particular reason you’ve renamed it fromAd?), as it seems you have done based on your other question. To go the rest of the distance, however, you’d need to edit thefields_dict()method like so: