modelformset_factory error: (Hidden field id) <foo> with this None already exists.

121 views
Skip to first unread message

cyberjack

unread,
Dec 2, 2008, 6:49:17 PM12/2/08
to Django users
Hi all, I've been stumped by this error for the past few days and
haven't made any progress. Could someone please help out?

I've created a formset of seven entries, one for each day of the
previous week. The first submission works fine; all seven entries are
successfully submitted. Subsequent submissions, however, generate the
following error for each of the seven entries:

(Hidden field id) Status report with this None already exists.

I found an django issue from a few months ago which might be related
[1]. However, this bug was resolved back in Oct. and I'm running
1.0.2, so I assume the CL is included. Is there any way to be
certain?

Here are my models, simplified for space:
class Vehicle(models.Model):
number = models.IntegerField(unique=True)

class StatusReport(models.Model):
date = models.DateField()
vehicle = models.ForeignKey(Vehicle, to_field='number')
status = models.CharField
('status',max_length=8,choices=STATUS_REPORT_CHOICES)

class Meta:
unique_together = ("date", "vehicle")

And here's my view:

def GenerateReportDate(request, vehicle_id, date):
# removed verification code for clarity
# week_start = monday before date.
# week_end = week_start + datetime.timedelta(7)
for i in range(7):
check_date = week_start + datetime.timedelta(i)
obj, created = StatusReport.objects.get_or_create(vehicle = int
(vehicle_id),
date = check_date,
defaults={'date': check_date,
'vehicle':vehicle[0]})
# Pull 7 reports for this week
reports = StatusReport.objects.filter(
vehicle__exact=vehicle_id
).filter(
date__gte = week_start
).filter(
date__lte = week_end
).order_by("date")

ReportFormSet = modelformset_factory(StatusReport, extra=0)

if request.method == 'POST':
formset = ReportFormSet(request.POST, request.FILES)
if formset.is_valid():
formset.save()
return HttpResponseRedirect('../done/') # Redirect after POST
else:
formset = ReportFormSet(queryset=reports)
return render_to_response('ops/report.html', {'formset': formset,
'number': vehicle_id,
'weekof': week_start})

Thanks for any help,

-Josh

[1] http://code.djangoproject.com/ticket/9039

cyberjack

unread,
Dec 4, 2008, 2:12:51 AM12/4/08
to Django users
Hi,

I haven't been able to solve this problem, but have made some
progress:

It's definitely *not* bug 9039. I've download the tests from that
ticket and confirmed the fix was included in 1.0.2 final.

The problem is related to using querysets with formset_factory. Ie,
if I include a queryset filter, then I see this error. If I don't
include a queryset, and thus edit all status reports, I don't see the
error.

Lastly, I've simplified my code producing the problem:

my model:

class StatusReport(models.Model):
vehicle = models.IntegerField()
report_date = models.DateField()
status = models.CharField(max_length=10)

and my view:

def detail(request, vehicle_id):
limited_reports = StatusReport.objects.filter(vehicle=vehicle_id)

StatusFormSet = modelformset_factory(StatusReport, extra=0)
if request.method == 'POST':
formset = StatusFormSet(request.POST)
if formset.is_valid():
formset.save()
else:
# with error
#formset = StatusFormSet(queryset=limited_reports)
# without error
formset = StatusFormSet()
return render_to_response('manage_articles.html',
{'formset': formset,
'vehicle_id': vehicle_id})

Is this a bug in Django? If so, what should I include in the bug
report?

Thanks,

-Josh

Karen Tracey

unread,
Dec 4, 2008, 7:10:18 PM12/4/08
to django...@googlegroups.com

I think the bug is that you need to pass the queryset parameter when you are dealing with a POST (if you've specified it on the GET) so that the posted data can be matched up to the existing model instances.  Otherwise I think it will be trying to validate and save as all new instances, and I think the error message is saying you wind up with duplicate primary key ids when you try that (though I will say that error message might could use some improvement).

Karen

cyberjack

unread,
Dec 8, 2008, 12:52:56 PM12/8/08
to Django users
Thanks for the idea Karen,

What's the right mechanism for passing the queryset back into the
form? I don't see an example in the docs.

Thanks!

-Josh

On Dec 4, 4:10 pm, "Karen Tracey" <kmtra...@gmail.com> wrote:

Karen Tracey

unread,
Dec 8, 2008, 8:58:32 PM12/8/08
to django...@googlegroups.com
On Mon, Dec 8, 2008 at 12:52 PM, cyberjack <cyber...@gmail.com> wrote:

Thanks for the idea Karen,

 What's the right mechanism for passing the queryset back into the
form? I don't see an example in the docs.

Just pass the queryset= parm into formset creation during post as you do during GET:

formset = ReportFormSet(request.POST, request.FILES, queryset=reports)

As I mentioned in ticket #9758, I do not know if this is really what's intended to be required when using model formsets, but it is a way to make the post data get matched up properly with existing DB instances. 

Karen








 
Reply all
Reply to author
Forward
0 new messages