﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
8813	BaseInlineFormSet unable to save existing objects	Tobias McNulty	jkocherhans	"The Error:
{{{
Environment:

Request Method: POST
Request URL: http://localhost:8000/caktus-books/ledger/exchange/215/edit/invoice/
Django Version: 1.0-beta_2-SVN-8874
Python Version: 2.5.2
Installed Applications:
['django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.sites',
 'django.contrib.admin',
 'django.contrib.humanize',
 'django.contrib.markup',
 'crm',
 'ledger']
Installed Middleware:
('django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.middleware.doc.XViewMiddleware')


Traceback:
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/django/core/handlers/base.py"" in get_response
  86.                 response = callback(request, *callback_args, **callback_kwargs)
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/django/contrib/auth/decorators.py"" in __call__
  67.             return self.view_func(request, *args, **kwargs)
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/django/db/transaction.py"" in _commit_on_success
  238.                 res = func(*args, **kw)
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/ledger/views.py"" in create_edit_exchange
  88. 			transactions = transaction_formset.save(commit=False)
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/django/forms/models.py"" in save
  372.         return self.save_existing_objects(commit) + self.save_new_objects(commit)
File ""/home/tobias/caktus/eclipse-workspace/caktus_books/django/forms/models.py"" in save_existing_objects
  386.             obj = existing_objects[form.cleaned_data[self._pk_field.name]]

Exception Type: KeyError at /caktus-books/ledger/exchange/215/edit/invoice/
Exception Value: None
}}}

From the debugger I found that:
{{{
self._pk_field.name = 'id'
self._pk_field.name in form.cleaned_data is True
form.cleaned_data[self._pk_field.name] is None
}}}

The Formset:
{{{
class BaseTransactionFormSet(BaseInlineFormSet):
	@requires_kwarg('exchange_type')
	def __init__(self, *args, **kwargs):
		self.exchange_type = kwargs.pop('exchange_type')
		super(BaseTransactionFormSet, self).__init__(*args, **kwargs)
	
	def add_fields(self, form, index):
		super(BaseTransactionFormSet, self).add_fields(form, index)
		form.fields.pop('project')
		
		form.fields['memo'].widget = forms.TextInput(attrs={'size':'35'})
		form.fields['quantity'].widget = forms.TextInput(attrs={'size':'5'})
		form.fields['amount'].widget = forms.TextInput(attrs={'size':'8'})
		
		et = self.exchange_type
		if et.credit:
			if et.slug == 'invoice':
				qs = ledger.Account.objects.filter(Q(type=et.credit.type) | Q(type='expense'))
			else:
				qs = ledger.Account.objects.filter(type=et.credit.type)
				
			form.fields['credit'].queryset = qs.order_by('number')
		else:
			form.fields.pop('credit')
		
		if et.debit:
			form.fields['debit'].queryset = ledger.Account.objects.filter(type=et.debit.type).order_by('number')
		else:
			form.fields.pop('debit')
		
TransactionFormSet = inlineformset_factory(ledger.Exchange, ledger.Transaction, formset=BaseTransactionFormSet)
}}}

The View:
{{{
@login_required
@transaction.commit_on_success
def create_edit_exchange(request, exchange_type_slug, exchange_id=None):
	exchange_type = get_object_or_404(ledger.ExchangeType, slug=exchange_type_slug)
	exchange = None
	
	if exchange_id:
		exchange = get_object_or_404(ledger.Exchange, pk=exchange_id, type=exchange_type)
	
	if request.POST:
		exchange_form = ExchangeForm(
			request.POST,
			instance=exchange, 
			exchange_type=exchange_type,
		)
		transaction_formset = TransactionFormSet(
			request.POST,
			instance=exchange, 
			exchange_type=exchange_type,
		)
		
		if exchange_form.is_valid() and transaction_formset.is_valid():
			exchange = exchange_form.save()
			
			transactions = transaction_formset.save(commit=False)
			for transaction in transactions:
				if exchange_type.credit:
					transaction.credit = exchange_form.cleaned_data['credit']
				if exchange_type.debit:
					transaction.debit = exchange_form.cleaned_data['debit']
				transaction.project = exchange_form.cleaned_data['project']
				transaction.save()
			
			request.user.message_set.create(message='%s successfully saved.' % exchange_type)
			return HttpResponseRedirect(reverse('list_exchanges', kwargs={'exchange_type_slug': exchange.type.slug}))
	else:
		exchange_form = ExchangeForm(
			instance=exchange, 
			exchange_type=exchange_type,
		)
		transaction_formset = TransactionFormSet(
			instance=exchange, 
			exchange_type=exchange_type,
		)

	context = {
		'exchange': exchange,
		'exchange_type': exchange_type,
		'exchange_form': exchange_form,
		'transaction_formset': transaction_formset,
	}
	
	return render_to_response('books/ledger/exchange/create.html', context, context_instance=RequestContext(request))
}}}"		closed	Forms	dev		fixed		Colin Copeland	Accepted	0	0	0	0	0	0
