Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How to make a form with custom templating?

Tags:

I have a model:

class Setting(models.Model):      class Meta:         abstract = True      name = models.CharField(max_length=120, primary_key=True)     description = models.CharField(max_length=300, blank=True)  class IntegerSetting(Setting):     value = models.IntegerField() 

I would like to create a form that looks something like:

<form method="POST" action="">      {% for model in models %}      <label>{{model.name}}</label> <input value='{{model.value}}' />      <p>{{model.description}}</p>      {% endfor %} </form> 

I'm not quite sure how to go about doing this. Perhaps I need to use a formset?

from django.forms.models import modelformset_factory from apps.about.models import Setting, IntegerSetting  def site_settings(request):     formset = modelformset_factory(IntegerSetting)()      return render_to_response("about/admin/site-settings.html", {'formset': formset}, RequestContext(request, {})) 

Then in the template, I'd want to render the form differently than default. I'm not quite sure how to go about accessing the model properties, however. Is this the right approach, or is there another way I should be going about doing this?

Update: This is what I'm currently doing. It renders exactly as I'd like it to, aside from the styling. However, I feel that it's deeply hacky:

class SettingsForm(ModelForm):     class Meta:         model = IntegerSetting      def as_table(self):         bound_field = BoundField(self, self.fields['value'], 'value')         return mark_safe("<tr><td><label>%s</label></td><td>%s\n<p class='help'>%s</p></td></tr>" % (self.instance.name,                                                                        self.instance.description,                                                                         bound_field.__unicode__()))   def edit_settings(request):     forms = [SettingsForm(instance=intSetting) for intSetting in IntegerSetting.objects.all()]      return render_to_response("admin/edit-settings.html", {'forms': forms}, RequestContext(request, {})) 

edit-settings.html:

{% extends "admin/base_site.html" %} {% block title %}System Settings{% endblock %}  {% block content %}     <form method="post" action="">         <table>         {% for form in forms %}         {{form}}         {% endfor %}         </table>     </form> {% endblock %} 

Is there a better approach to this?

Also, I'm not sure if I'll encounter problems when the form is submitted or not.

like image 660
Nick Heiner Avatar asked Feb 04 '11 19:02

Nick Heiner


People also ask

How do I use custom template tags in Django?

Create a custom template tagUnder the application directory, create the templatetags package (it should contain the __init__.py file). For example, Django/DjangoApp/templatetags. In the templatetags package, create a . py file, for example my_custom_tags, and add some code to it to declare a custom tag.

How do I add a template to Django?

To configure the Django template system, go to the settings.py file and update the DIRS to the path of the templates folder. Generally, the templates folder is created and kept in the sample directory where manage.py lives. This templates folder contains all the templates you will create in different Django Apps.


2 Answers

<form action="/contact/" method="post">     {% for field in form %}         <div class="fieldWrapper">             {{ field.errors }}             {{ field.label_tag }}: {{ field }}         </div>     {% endfor %}     <p><input type="submit" value="Send message" /></p> </form> 

You can find the complete documentation here: http://docs.djangoproject.com/en/dev/topics/forms/#customizing-the-form-template

like image 140
jbcurtin Avatar answered Sep 20 '22 04:09

jbcurtin


I don't think you need a formset here. Take a look here if you want a custom template for one view. If you want to create your own {{ form.as_foobar }}, just subclass forms.Form, something like this:

class MyForm(forms.Form):   def as_foobar(self):     return self._html_output(       normal_row = u'%(label)s %(field)s%(help_text)s',       error_row = u'%s',       row_ender = '',       help_text_html = u' %s',       errors_on_separate_row = False) 

and just use it in your forms.py:

class ContactForm(MyForm):   # .. 
like image 39
Bjorn Avatar answered Sep 18 '22 04:09

Bjorn