Display an unknown number of fields in a Django template with the contents of the field of another record as a label

I have a Django application that I want to use in multiple instances. One model (Listing) can have a variable number of fields (for different instances), but will always have exactly such additional fields for an instance. I want to add these additional fields via admin, so I created such models:

class BespokeField (models.Model): name = models.CharField( max_length = 20, verbose_name = "Field Title" ) def __unicode__(self): return self.name class Listing (models.Model): name = models.CharField ( verbose_name = 'Listing', max_length = 30 ) slug = models.SlugField ( verbose_name = "Slug", allow_unicode = True, unique=True, blank=True, null=True ) class ListingBespokeField (models.Model): bespoke_field = models.ForeignKey(BespokeField) listing = models.ForeignKey(Listing) value = models.CharField ( max_length = 60 ) def __unicode__(self): return u'%s | %s' % (self.listing.name, self.bespoke_field.name) 

The admin theory defines custom fields, and they are then displayed to the user in forms. Inside the admin, this is relatively simple, since I can accept modicum for intelligence from users, so my admin.py looks like this:

 class ListingBespokeFieldInline(admin.TabularInline): model = ListingBespokeField extra = len(BespokeField.objects.all()) max_num = len(BespokeField.objects.all()) class ListingAdmin(admin.ModelAdmin): inlines = [ListingBespokeFieldInline] 

This means that the admin user must select one of each BespokeField from the drop-down list, but I'm not uncomfortable, because using unique_together, make sure that there is only one of them.

The fact that I cannot understand how to do this presents this to a user without administrator privileges in a friendly manner. I want BespokeField.name appear on the form as a label for ListingBespokeField.value .

This is what I have in forms.py (for ListingBespokeField).

 class ListingBespokeFieldInline(forms.ModelForm): class Meta: model = ListingBespokeField exclude =['id'] widgets = { 'bespoke_field' : forms.HiddenInput(), 'value' : forms.TextInput(attrs={'class' : 'form-control'}) } class ListingBespokeFieldForm(forms.ModelForm): class Meta: model = ListingBespokeField exclude = () BESPOKE_FIELD_COUNT = len(BespokeField.objects.all()) ListingBespokeFieldInlineFormSet = forms.inlineformset_factory ( Listing, ListingBespokeField, form=ListingBespokeFieldInline, extra = BESPOKE_FIELD_COUNT, max_num = BESPOKE_FIELD_COUNT, exclude = ['id'], can_delete=False, can_order=False ) 

Then I try to present it through a template as follows:

 <table class="table"> {{ bespokefields.management_form }} {% for form in bespokefields.forms %} {% if forloop.first %} <thead> <tr> {% for field in form.visible_fields %} <th>{{ field.label|capfirst }}</th> {% endfor %} </tr> </thead> {% endif %} <tr class="formset_row bespokefield"> <td> {{ form.listing }}{{ form.id }}{{ form.bespoke_field }} {{ form.bespoke_field.label }} </td> <td>{{ form.value }}</td> </tr> {% endfor %} </table> 

This does not work. I could use some understanding, please.

+7
python django django-forms django-templates
source share
1 answer

This was my solution:

 <table class="table"> {{ bespokefields.management_form }} {% for form in bespokefields.forms %} <tr class="formset_row bespokefield"> <td> {{ form.listing }}{{ form.id }} <select id="id_listingbespokefield_set-{{ forloop.counter0 }}-bespoke_field" name="listingbespokefield_set-{{ forloop.counter0 }}-bespoke_field" class="form-control"> {% with forloop.counter as counter %} {% for x,y in form.fields.bespoke_field.choices %} {% if counter == forloop.counter0 %} <option value="{{x}}" selected>{{y}}</option> {% endif %} {% endfor %} {% endwith %} </select> </td> <td>{{ form.value }}</td> </tr> {% endfor %} </table> 
+2
source share

All Articles