⬆️ ⬇️

We make out forms

Django forms have several predefined methods as_p (), as_table () and as_ul (), which display the form as a set of paragraphs, a table or a list. In practice, these methods are not always enough to make the forms look the way we want.



Suppose the coder has folded all forms divs. Documentation suggests in this case to write the necessary tags manually in the template. If we have only one form, you can do so. If there are several forms, then this approach immediately loses all its charm. The solution is very simple - we will inherit our own form class from forms.Form or forms.ModelForm and teach it how to draw forms as we need.



For starters, it's a good idea to look at the Django source files - the as_p methods and others like it are very simple. They call the _html_output method of the BaseForm class, instructing it on how to draw the form. So, add your as_div method:

Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  1. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  2. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  3. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  4. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  5. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  6. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  7. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)
  8. Copy Source | Copy HTML class SexyModelForm (forms.ModelForm): def as_div (self): return self ._html_output( normal_row = u '<div%(html_class_attr)s>%(label)s %(field)s %(help_text)s %(errors)s</div>' , error_row = u '<div class="error">%s</div>' , row_ender = '</div>' , help_text_html = u '<div class="hefp-text">%s</div>' , errors_on_separate_row = False)


The code is self-evident, the only thing that can cause questions is the errors_on_separate_row. If this parameter is set to True, then errors will be output in a separate block. It is used, for example, in as_p, in order not to push <ul> inside <p>.

')

Now, we can inherit our forms from SexyModelForm and call them in templates using {{form.as_div}}.



In 1.2. There was a pleasant opportunity to assign your css-classes for a required field and an error field. Simplify your life a little more - let's add a few lines to our class, and a little more uniformity will be added to the forms:

Copy Source | Copy HTML
  1. error_css_class = 'class-error'
  2. required_css_class = 'class-required'


But that's not all. Sometimes you need to add all css-classes to all fields. This can be done like this:

Copy Source | Copy HTML
  1. def __init__ (self, * args, ** kwargs):
  2. super (ModelForm, self). __init__ (* args, ** kwargs)
  3. # adding the fields to the fields:
  4. for field in self .fields:
  5. self .fields [field] .widget.attrs [ 'class' ] = 'some-class other-class'


Here, for example, you can check input_type and assign classes to different types of fields depending on it.



That's what happened in the end:

Copy Source | Copy HTML
  1. class SexyModelForm (forms.ModelForm):
  2. error_css_class = 'class-error'
  3. required_css_class = 'class-required'
  4. def __init__ (self, * args, ** kwargs):
  5. super (ModelForm, self). __init__ (* args, ** kwargs)
  6. # adding the fields to the fields:
  7. for field in self .fields:
  8. self .fields [field] .widget.attrs [ 'class' ] = 'some-class other-class'
  9. def as_div (self):
  10. return self ._html_output (
  11. normal_row = u '<div% (html_class_attr) s>% (label) s% (field) s% (help_text) s% (errors) s </ div>' ,
  12. error_row = u '<div class = "error">% s </ div>' ,
  13. row_ender = '</ div>' ,
  14. help_text_html = u '<div class = "hefp-text">% s </ div>' ,
  15. errors_on_separate_row = False)


The solution turned out to be a simple, non-cluttering code and workable.

Source: https://habr.com/ru/post/95681/



All Articles