Jamgreen
Jamgreen

Reputation: 11039

Get data in a model formset in Django

I have a formset in Django.

I print this formset in the templates as

{% for form in formset %}
    {{ form.name }}
{% endfor %}

The formset consists of the queryset as forms and a few extra forms. But I need some field values from the queryset that I wont show as forms. How is this possible? It's a queryset with a prefetch_related, so the fields aren't actually in the model, but are joined in my queryset.

My models are

class Person:
    name = CharField(max_length=200)

class Grade:
    person = ForeignKey(Person)
    grade = IntegerField()

My queryset is Person.objects.prefetch_related('grade_set').

My template is

{% for form in formset %}
    Object id: {{ obj.id }}
    {{ form.name }}
    {{ obj.grade_set.all|running_total }}
{% endfor %}

I know that obj is not defined, but I think it maybe will be possible to do something like this in the template:

{% for obj, form in object_formset %}
    Object id: {{ obj.id }}
    {{ form.name }}
    {{ obj.grade_set.all|running_total }}
{% endfor %}

Right now my formset only consists of forms, but I rather need an object list and create some forms from this object list. I could do a small hack by creating the forms and use the field names and input names and completely avoid Django's way of creating forms, but I think it will be stupid. There must be some other way.

Upvotes: 1

Views: 2260

Answers (2)

luto
luto

Reputation: 150

Assuming the FormSet is derived from BaseModelFormSet, the form is a ModelForm, which exposes its database object as .instance. You can access it like so:

{% for form in formset %}
    Object id: {{ form.instance.id }}
{% endfor %}

Upvotes: 0

sgarza62
sgarza62

Reputation: 6238

Yes, this is possible using zip.

# somewhere in views.py...
people = Person.objects.prefetch_related('grade_set')
formset = # ...(create your modelformset)...
people_and_formset = zip(people, formset)

# somewhere in template.html...
{% for person, form in people_and_formset %}
    {{ person.id }}
    {{ form.name }}
    {{ person.grade_set.all|running_total }}
{% endfor %}

Having used prefetch_related, the grade_set of each Person will be found in the Queryset cache, and will not require another hit to the db.

Upvotes: 2

Related Questions