Abstract Forms Django : __init__() got multiple values for argument - django

I want to make an AbstractEditForm (Inherited from ModelForm) form, from which there are multiple forms that would be inheriting from it. But I am getting this error :
Here is my forms.py
# This is the abstract form that I want to inherit other forms from
class AbstractEditForms(forms.ModelForm):
def __init__(self, id_fields=None, ref_field=None,
model=None, *args, **kwargs):
self.id_fields = id_fields
self.changed_fields = {}
self.ref_field = ref_field
self.model_ = model
self.ref_id_changed = False
self.check_ref_id()
try:
if 'id_fields' in kwargs.keys():
del kwargs['id_fields']
if 'ref_fields' in kwargs.keys():
del kwargs['ref_fields']
except KeyError as e:
print('Error in AbstractionEditForms :', str(e))
super(AbstractEditForms, self).__init__(*args, **kwargs)
# This is the form that I want to use
class SchemeEditForm(AbstractEditForms):
class Meta:
model = SchemeModel
exclude = ['created_on', 'financial_year']
widgets = {
'as_ref_id': forms.TextInput(attrs={'readonly': 'readonly',
'placeholder': 'Auto Generated '
}),
'admin_sanction_amount': forms.HiddenInput(),
'updated_on': forms.HiddenInput(),
}
views.py :
def edit_scheme_form_view(request, pk=None):
assert pk is not None, 'pk cannot be None, scheme edit form'
instance = get_object_or_404(SchemeModel, pk=pk)
id_fields = ['technical_authority', 'dept_name', ]
model = SchemeModel
ref_field = "as_ref_id"
if request.method == 'GET':
scheme_form = SchemeEditForm(None, id_fields=id_fields, ref_field="as_ref_id",
model=model, instance=instance)
context = {
'form': scheme_form
}
return render(request, 'Forms/forms/SchemeForm.html', context=context)
if request.method == 'POST':
scheme_form = SchemeEditForm(request.POST, id_fields=id_fields, ref_field="as_ref_id",
model=SchemeModel, instance=instance)
if scheme_form.is_valid():
instance = scheme_form.save()
return generate_success_page(request, instance,"Scheme Edit Success",
"Scheme Details - Edited", nav_dict=None,
util_dict=None)
else:
return render(request, 'Forms/forms/SchemeForm.html', {'form': scheme_form})
Error traceback:
Internal Server Error: /edit/admin-sanction-form/1/
Traceback (most recent call last):
File "C:\Python35\lib\site-packages\django\core\handlers\base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Python35\lib\site-packages\django\core\handlers\base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\karth\PycharmProjects\phc\edit_forms\views.py", line 17, in edit_scheme_form_view
model=model, instance=instance
TypeError: __init__() got multiple values for argument 'id_fields'
[04/Sep/2016 20:41:08] "GET /edit/admin-sanction-form/1/ HTTP/1.1" 500 63681
I understand that this is problem with initialization form either AbstractEditForm or the SchemeEditForm.
Any help would be much appreciated.

SchemeEditForm is interpreting the first positional argument you are passing it as being the id_fields argument. When you later try to pass id_fields by name, it thinks it is getting a duplicate of that argument and you are getting an error.
Try changing your __init__() method to accept arbitrary positional arguments before your keyword arguments like this:
def __init__(self, *args, id_fields=None, ref_field=None, model=None, **kwargs):
I am not sure if this will get you the results you want in terms of how your forms function, but it will get rid of the error you are seeing. Note that this method will not work in Python 2.X, only Python 3.

Related

Django 1.9 Type Error __init__() takes 1 positional argument but 2 were given - problems with class decorating

A bit of context: I'm trying to create a CreateView page for users to input information whilst working with Django 1.9 which is at URL '/profile/'.
When users are not logged in, and I go to the /profile/ url then it will redirect me to the login page as expected. However, when I am logged in to the site, and then go to /profile/ then it will display this error:
TypeError at /profile/
__ init __() takes 1 positional argument but 2 were given
At the moment, I'm decorating a class with a method_decorator, as mentioned in the docs here: https://docs.djangoproject.com/en/1.10/topics/class-based-views/intro/#decorating-the-class.
This is in my views.py:
#login_required(login_url = "/login/", redirect_field_name = None)
#method_decorator(login_required, name = 'dispatch')
class SpkCreateView(CreateView):
form_class = SpkCreateForm
template_name = 'userprofile/spk_form.html'
def get(self, request):
form = self.form_class(None)
return render(request, self.template_name, {'form': form})
def post(self, request):
form = self.form_class(request.POST)
if form.is_valid():
spk_fname = form.cleaned_data['spk_fname']
spk_lname = form.cleaned_data['spk_lname']
The 'name' argument for the method_decorator is also tripping me up so I'm not sure whether it's to do with that.
If anybody has any solutions then thanks!
Edit:
Changed #login_required(login_url = "/login/", redirect_field_name = None)
#method_decorator(login_required, name = 'dispatch')
to #method_decorator(login_required(login_url = "/login/", redirect_field_name = None), name = 'dispatch')
and this is the traceback from Powershell
Internal Server Error: /profile/
Traceback (most recent call last):
File "C:\Users\Programs\Python\Python36-32\lib\site-packag
es\django\core\handlers\base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Programs\Python\Python36-32\lib\site-packag
es\django\core\handlers\base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
TypeError: __init__() takes 1 positional argument but 2 were given
[28/Sep/2016 22:20:22] "GET /profile/ HTTP/1.1" 500 57532
You're decorating the class with login_required both with and without #method_decorator. You need to pass the decorator you want to use to method_decorator, in this case:
#method_decorator(login_required(login_url="/login/", redirect_field_name=None), name='dispatch')
class SpkCreateView(CreateView):
...

django-clever-selects TypeError with method is_valid()

Using django-clever-selects to chain selects but the is_valid() method in the view is causing this error:
Traceback:
File "/Applications/djangostack-1.7.10-0/apps/django/django_projects/freshTest/myenv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Applications/djangostack-1.7.10-0/apps/django/django_projects/freshTest/megaForm/views.py" in newForm
29. if form.is_valid():
File "/Applications/djangostack-1.7.10-0/apps/django/django_projects/freshTest/clever_selects/forms.py" in is_valid
191. activate(self.language_code)
File "/Applications/djangostack-1.7.10-0/apps/django/django_projects/freshTest/myenv/lib/python3.4/site-packages/django/utils/translation/__init__.py" in activate
146. return _trans.activate(language)
File "/Applications/djangostack-1.7.10-0/apps/django/django_projects/freshTest/myenv/lib/python3.4/site-packages/django/utils/translation/trans_real.py" in activate
217. if language in _DJANGO_DEPRECATED_LOCALES:
Exception Type: TypeError at /newForm/
Exception Value: unhashable type: 'QueryDict'
views.py
def newForm(request):
if request.method == 'POST':
form = SimpleChainForm(request.POST)
if form.is_valid():
print(form.cleaned_data)
return render(request, 'form1/current_form.html', {
'form': form,
'message': (request.POST['cat'],request.POST['columns']),
# 'error_message': "You didn't select a choice.",
})
#if GET or other method create blank form
else:
form=SimpleChainForm()
return render(request, 'form1/current_form.html', {'form': form})
The documentation says that django-clever-selects has been 'Tested on Django 1.4.5.', but I need to use 1.8. Is there a work-round/fix for this error? New to django so any help would be appreciated!
For anyone else struggling with this issue, the following worked for me:
https://github.com/filipefigcorreia/django-clever-selects/commit/4f6da07bb9e880aaaa188297f5866bcbf9c6cab6
https://github.com/PragmaticMates/django-clever-selects/issues/6
Firstly in clever_selects/forms.py remove these lines
def __init__(self, language_code=None, *args, **kwargs):
self.language_code = language_code
add in
def __init__(self, *args, **kwargs):
self.language_code = kwargs.get('language_code', None)
in my app, forms.py, remove reverse_lazy
ajax_url=reverse_lazy('ajax_chained_subtypes') ==> ajax_url='/ajax/chained-subtypes/',
generates a bytes string problem, solved with:
clever_selects/forms.py line 97
field.choices = field.choices + json.loads(data.content) ==>
field.choices = field.choices + json.loads(data.content.decode("utf-8"))

Upgrading from Django 1.3 to 1.5.5 app unit test failing with AttributeError: PositionForm object has no attribute 'cleaned_data

I am upgrading from Django 1.3 to 1.5.5. All the tests worked before but now this one is failing and I cant figure out why. I have included the stack trace and functions that appear in the stack trace. There are a lot of log statements for debugging so be warned.
Traceback (most recent call last):
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/mock.py", line 1201, in patched
return func(*args, **keywargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/tests.py", line 878, in test_edit_profile
response = self.client.post(edit_profile_url, self.profile_post_data)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 463, in post
response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 297, in post
return self.request(**r)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/test/client.py", line 424, in request
six.reraise(*exc_info)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/views.py", line 268, in public_profile
form.save(commit=False)
File "/Users/athom09/Projects/openemory/openemory/../openemory/accounts/forms.py", line 122, in save
return super(ProfileForm, self).save(*args, **kwargs)
File "/Users/athom09/Projects/openemory/openemory/../openemory/inlinemodelformsets.py", line 119, in save
fset.save()
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/models.py", line 514, in save
return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/models.py", line 646, in save_new_objects
if self.can_delete and self._should_delete_form(form):
File "/Users/athom09/Projects/openemory/openemoryEnv/lib/python2.7/site-packages/django/forms/formsets.py", line 266, in _should_delete_form
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
AttributeError: 'PositionForm' object has no attribute 'cleaned_data'
Accounts.test.py:
profile_post_data = {
'interests-MAX_NUM_FORMS': '',
'interests-INITIAL_FORMS': 0,
'interests-TOTAL_FORMS': 2,
'interests-0-interest': 'esoteric stuff',
'interests-0-DELETE': '',
'interests-1-interest': '',
'interests-1-DELETE': '',
# degrees, with formset management fields
'_DEGREES-MAX_NUM_FORMS': '',
'_DEGREES-INITIAL_FORMS': 0,
'_DEGREES-TOTAL_FORMS': 2,
'_DEGREES-0-name': 'BA',
'_DEGREES-0-institution': 'Somewhere Univ',
'_DEGREES-0-year': 1876,
'_DEGREES-1-name': 'MA',
'_DEGREES-1-institution': 'Elsewhere Institute',
# (degree year is optional)
# positions, with same
'_POSITIONS-MAX_NUM_FORMS': '',
'_POSITIONS-INITIAL_FORMS': 0,
'_POSITIONS-TOTAL_FORMS': 3,
'_POSITIONS-0-name': 'Big Cheese, Association of Curd Curators',
'_POSITIONS-1-name': 'Hole Editor, Journal of Swiss Studies',
#external links
'_EXTERNAL_LINKS-MAX_NUM_FORMS': '',
'_EXTERNAL_LINKS-INITIAL_FORMS': 0,
'_EXTERNAL_LINKS-TOTAL_FORMS': 2,
'_EXTERNAL_LINKS-0-title': 'Google',
'_EXTERNAL_LINKS-0-url': 'http://www.google.com',
'_EXTERNAL_LINKS-1-title': 'Yahoo!',
'_EXTERNAL_LINKS-1-url': 'http://www.yahoo.com',
# grants: TODO: not currently included in templates
# '_GRANTS-MAX_NUM_FORMS': '',
# '_GRANTS-INITIAL_FORMS': 0,
# '_GRANTS-TOTAL_FORMS': 3,
# '_GRANTS-0-name': 'Advanced sharpness research',
# '_GRANTS-0-grantor': 'Cheddar Institute',
# '_GRANTS-0-project_title': 'The effect of subject cheesiness on cheddar sharpness assessment',
# '_GRANTS-0-year': '1492',
# '_GRANTS-1-grantor': u'Soci\xb4t\xb4 Brie',
# '_GRANTS-1-project_title': 'A comprehensive analysis of yumminess',
'biography': 'Went to school *somewhere*, studied something else **elsewhere**.',
}
response = self.client.post(edit_profile_url, self.profile_post_data)
Accounts.views.py:
def public_profile(request, username):
'''Display public profile information and publications for the
requested author.
When requested via AJAX, returns HTML that can be displayed inside
a faculty dashboard tab.
'''
user, userprofile = _get_profile_user(username)
logger.info("AFTER USER")
form, interest_formset = None, None
context = {}
if request.method == 'POST':
logger.info("IN POST")
form = ProfileForm(request.POST, request.FILES, instance=userprofile)
logger.info("AFTER PROFILE FORM")
interest_formset = InterestFormSet(request.POST, prefix='interests')
logger.info("AFTER INTREST FORM")
if form.is_valid() and interest_formset.is_valid():
logger.info("IN VALID FORM")
logger.info("====================")
logger.info(dir(form))
logger.info("--------------------")
logger.info(dir(interest_formset))
logger.info("====================")
# save and redirect to profile
logger.info("B4 SAVE")
form.save(commit=False)
logger.info("AFTER SAVE")
new_interests = [f.cleaned_data.get('interest')
for f in interest_formset.forms
if f.cleaned_data.get('interest', '') and
not f.cleaned_data.get('DELETE', False)]
logger.info("AFTER GET INTRESTS")
userprofile.research_interests.set(*new_interests)
logger.info("AFTER SET INTRESTS")
# if a new photo file was posted, resize it
if 'photo' in request.FILES:
form.instance.resize_photo()
userprofile.save()
messages.success(request, 'Your profile was updated.')
# TODO: might want a different behavior when POSTed via ajax
logger.info("BEFORE POST REDIRECT")
return HttpResponseSeeOtherRedirect(reverse('accounts:dashboard-profile',
kwargs={'username': username}))
else:
logger.info("IN INVALID FORM")
context['invalid_form'] = True
if (request.user.has_perm("accounts.change_userprofile") or request.user == user) and not request.method == 'POST':
form = ProfileForm(instance=userprofile)
form.inlineformsets
interest_data = [{'interest': i}
for i in sorted(userprofile.research_interests.all())]
interest_formset = InterestFormSet(initial=interest_data, prefix='interests')
context.update({
'author': user,
'form': form,
'interest_formset': interest_formset,
})
if request.is_ajax():
# display a briefer version of the profile, for inclusion in faculty dash
template_name = 'accounts/snippets/profile-tab.html'
# for non-ajax requests, display full profile with documents
else:
# get articles where the user is the author
articles_query = userprofile.recent_articles_query()
paginated_articles, show_pages = paginate(request, articles_query)
url_params = request.GET.copy()
url_params.pop('page', None)
context.update({
'results': paginated_articles,
'show_pages': show_pages,
'url_params': url_params.urlencode(),
})
template_name = 'accounts/profile.html'
return render(request, template_name, context)
Accounts.forms.py:
def save(self, *args, **kwargs):
logger.info("INSIDE SAVE")
if hasattr(self, 'cleaned_data') and self.cleaned_data.get('delete_photo', False):
logger.info("INSIDE CLEAN IF")
# save=False because we're in the middle of save, and that would
# probably cause this to go recursive or the world to implode or
# something.
logger.info("BEFORE PHOTO DELETE")
self.instance.photo.delete(save=False)
logger.info("AFTER PHOTO DELETE")
logger.info("BEFORE SAVE RETURN")
inlinemodelformsets.py:
def save(self, *args, **kwargs):
logger.info("IN PSAVE")
instance = super(ModelForm, self).save(*args, **kwargs)
if hasattr(self._forms, 'inlines'):
for key, FormSet in self._forms.inlines.items():
fset = FormSet(self.data, self.files, prefix=self._get_formset_prefix(key),
instance=instance)
logger.info("BEFORE PSAVE FSET SAVE")
fset.save()
logger.info("BEFORE PSAVE RETURN")
return instance
return super(ProfileForm, self).save(*args, **kwargs)
You need to validate the formset before saving it.
fset = FormSet(self.data, self.files, prefix=self._get_formset_prefix(key),
instance=instance)
logger.info("BEFORE PSAVE FSET SAVE")
if fset.is_valid():
fset.save()
else:
// display form errors
When you come to know the error which was preventing the formset from being saved, you can tweak the profile_post_data data to make sure it validates.

Django - Mixing ListView and CreateView

I'm want to create one page with a form, and every time I submit the form it adds an item to the list below the form.
I can make it work using 2 pages:
one page using the mixin CreateView to add items
one page ListView to have the list.
But I'm trying to have the form and the list on the same page. So I tried to create a class with both mixin:
class FormAndListView(ListView, CreateView):
pass
Then I've used this class:
FormAndListView.as_view(
queryset=PdfFile.objects.order_by('id'),
context_object_name='all_PDF',
success_url = 'listview',
form_class = UploadFileForm,
template_name='textfrompdf/index.html',)),
But when I try to load the page, I get the error: Exception Value: 'FormAndListView' object has no attribute 'object'
Traceback:
File "C:\Program Files\Python_2.7\lib\site-packages\django\core\handlers\base.py" in get_response
111. response = callback(request, *callback_args, **callback_kwargs)
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in view
47. return self.dispatch(request, *args, **kwargs)
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in dispatch
68. return handler(request, *args, **kwargs)
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get
122. return self.render_to_response(context)
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\base.py" in render_to_response
94. template = self.get_template_names(),
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\list.py" in get_template_names
134. names = super(MultipleObjectTemplateResponseMixin, self).get_template_names()
File "C:\Program Files\Python_2.7\lib\site-packages\django\views\generic\detail.py" in get_template_names
122. if self.object and self.template_name_field:
Exception Type: AttributeError at /PDF/
Exception Value: 'FormAndListView' object has no attribute 'object'
I've no idea how to debug that. Where to start?
I use a lot of views that involve a form and a list of objects. Rather than trying to mixin things I just add the queryset into the context data as below.
class UploadFileView(CreateView):
form_class = UploadFileForm
success_url = 'listview'
template_name = 'textfrompdf/index.html'
def get_context_data(self, **kwargs):
kwargs['object_list'] = PdfFile.objects.order_by('id')
return super(UploadFileView, self).get_context_data(**kwargs)
Do not mix list and update views.
Instead, create two separate views for these tasks:
List view displays the list and a web form with action URL pointing to the create view.
Create view accepts POST data and
displays form with error message in case of failure;
redirects to the list view in case of success.
Also I've tried to use class-based views and found that they are too complex.
I think it is much easier to use old-style function views.
I found the answer, there is 2 problems:
ListView and CreateView are "high level" mixin which aggregate "lower
level" mixins. But these lower level mixins are not compatible together.
The View class calls directly the render_to_response(), but in my scenario, there is 2 view class and render_to_response() should only be called once at the end.
I was able "solve" this issue using the following steps:
Instead of calling ListView and CreateView, I used lower level mixins. Moreover I called explicitly BaseCreateView and BaseListView from which I "extracted" the form and object_list
class FormAndListView(BaseCreateView, BaseListView, TemplateResponseMixin):
def get(self, request, *args, **kwargs):
formView = BaseCreateView.get(self, request, *args, **kwargs)
listView = BaseListView.get(self, request, *args, **kwargs)
formData = formView.context_data['form']
listData = listView.context_data['object_list']
return render_to_response('textfrompdf/index.html', {'form' : formData, 'all_PDF' : listData},
context_instance=RequestContext(request))
It's not clean but it works!
I have made my own class to solve this problem. I don't know if it's better or worse, but it works too. I have tried to use the generic mixins and have tested that validation and pagination work.
The code in GitHub
class ListAppendView(MultipleObjectMixin,
MultipleObjectTemplateResponseMixin,
ModelFormMixin,
ProcessFormView):
""" A View that displays a list of objects and a form to create a new object.
The View processes this form. """
template_name_suffix = '_append'
allow_empty = True
def get(self, request, *args, **kwargs):
self.object_list = self.get_queryset()
allow_empty = self.get_allow_empty()
if not allow_empty and len(self.object_list) == 0:
raise Http404(_(u"Empty list and '%(class_name)s.allow_empty' is False.")
% {'class_name': self.__class__.__name__})
self.object = None
form_class = self.get_form_class()
form = self.get_form(form_class)
context = self.get_context_data(object_list=self.object_list, form=form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.object = None
return super(ListAppendView, self).post(request, *args, **kwargs)
def form_invalid(self, form):
self.object_list = self.get_queryset()
return self.render_to_response(self.get_context_data(object_list=self.object_list, form=form))
If you try it and find any errors, please tell me here or in GitHub.
I got into this problem and solve it with the following code, the answer by #jondykeman does not have pagination and other utilities for base classes. the other approaches that are proposed are a little complicated than the following:
class ObjectCreateView(LoginRequiredMixin, MultipleObjectMixin, View):
queryset = Wallet.objects.all()
def get(self, request):
self.object_list = super(ObjectCreateView, self).get_queryset().filter(user=request.user)
allow_empty = super(ObjectCreateView, self).get_allow_empty()
if not allow_empty:
if super(ObjectCreateView, self).get_paginate_by(self.object_list) is not None and hasattr(self.object_list, 'exists'):
is_empty = not self.object_list.exists()
else:
is_empty = not self.object_list
if is_empty:
raise Http404()
context = super(ObjectCreateView, self).get_context_data()
form = CreateObjectForm()
context['form'] = form
return render(request, 'objects/object-list.html', context=context)
def post(self, request):
form = CreateWalletForm(request.POST)
if form.is_valid():
Object.objects.create(name=form.cleaned_data['name'], user=request.user)
messages.success(request, 'Object is created')
else:
messages.error(request, utility.get_form_errors_as_string(form))
return redirect('objects:create')

Django modelformset validation problem: how to use queryset in request.POST?

I am working with modelformset, and am a little stuck. I am passing, say 20 forms using modelformsetfactory. These forms are constructed and displayed in the page. When I return after the posting, I only want some of these forms to be validated and saved, not all of them, depending upon the value of a model field.
I figured I could use queryset in the request.POST to limit the forms that I want in my formset that are to be validated. But this is not working. Is there any way I can limit the number of forms?
For the queryset that limits model instances I tried
formset = PaymentOptionFormSet(request.POST, queryset=payment_option_posted_queryset)
I get the following error:
IndexError at /seller/seller_profile/
list index out of range
Traceback:
File "/home/shagun/work/tinla/django/core/handlers/base.py" in get_response
100. response = callback(request, *callback_args, **callback_kwargs)
File "/home/shagun/work/tinla/web/views/user_views.py" in seller_profile
164. formset = PaymentOptionFormSet(request.POST, queryset=payment_option_posted_queryset)
File "/home/shagun/work/tinla/orders/forms.py" in __init__
400. super(BasePaymentOptionFormSet, self).__init__(*args,**kwargs)
File "/home/shagun/work/tinla/django/forms/models.py" in __init__
423. super(BaseModelFormSet, self).__init__(**defaults)
File "/home/shagun/work/tinla/django/forms/formsets.py" in __init__
47. self._construct_forms()
File "/home/shagun/work/tinla/django/forms/formsets.py" in _construct_forms
97. self.forms.append(self._construct_form(i))
File "/home/shagun/work/tinla/django/forms/models.py" in _construct_form
447. kwargs['instance'] = self.get_queryset()[i]
File "/home/shagun/work/tinla/django/db/models/query.py" in __getitem__
172. return self._result_cache[k]
Exception Type: IndexError at /seller/seller_profile/
Exception Value: list index out of range
My code looks like this:
def seller_profile(request):
from accounts.models import PaymentOption, PaymentMode
payment_options = PaymentOption.objects.select_related('payment_mode').filter(payment_mode__client__id=1)
payment_option_queryset = PaymentOption.objects.filter(payment_mode__client__id='1')
payment_option_posted_queryset = PaymentOption.objects.filter(payment_mode__client__id='1', is_active='1')
if request.user.is_authenticated():
PaymentOptionFormSet = modelformset_factory(PaymentOption, formset = BasePaymentOptionFormSet, extra=0, fields = ("payment_delivery_address", "bank_branch", "bank_ac_name", "bank_ac_type", "bank_ac_no", "bank_address", "bank_ifsc", "is_active"))
user = request.user.get_profile()
if request.method == "POST":#If the form has been submitted
form1 = SellerProfileForm(request.POST, instance = user)
form2 = SellerNotificationForm(request.POST, instance = user)
formset = PaymentOptionFormSet(request.POST, queryset=PaymentOption.objects.all())
counting = 0
for form in formset.forms:
counting +=1
print "count = ",counting
print formset.is_valid()
if form1.is_valid() and form2.is_valid:
form1.save()
form2.save()
else:
my_acct_ctxt = getMyAccountContext(request)
return render_to_response('seller/seller_profile.html',
{
'form1': form1,
'form2': form2,
'formset': formset,
'error1': form1.errors,
'error2': form2.errors,
'errorformset': formset.errors,
'payment_options': payment_options,
'acc': my_acct_ctxt,
},
context_instance=RequestContext(request))
else: #If the form has not been submitted
form1 = SellerProfileForm(instance = user)
form2 = SellerNotificationForm(instance = user)
formset = PaymentOptionFormSet(queryset=payment_option_queryset)
counter = 0
my_acct_ctxt = getMyAccountContext(request)
return render_to_response('seller/seller_profile.html',
{
'form1': form1,
'form2': form2,
'formset': formset,
'payment_options': payment_options,
'acc':my_acct_ctxt,
},
context_instance=RequestContext(request))
If you're needing to conditionally validate a formset, you can override the clean method of the formset. Here's an example of how I've done this within admin on an inline formset, which you can probably change to suit your needs as the Formset classes are pretty homogenous.
class MyInlineFormset(forms.models.BaseInlineFormSet):
def clean(self):
for form in self.forms:
try:
if form.cleaned_data:
delete = form.cleaned_data.get('DELETE')
if not delete:
my_field = form.cleaned_data.get('my_field', None)
if my_field:
if my_field == 'some_value':
#only validate the other values
#if the field you're looking for
#has a particular value, etc
another_field = form.cleaned_data.get('another_field')
#more validation here where you can raise
#forms.ValidationError()
except AttributeError:
pass
I hope that helps you out!