====== Django Forms ====== ===== Render a form =====
{% csrf_token %} {{ form.as_p }}
{% csrf_token %} {{ form }}
Fíjate aquí, con ''novalidate'' no haría la validación de datos local.
{% csrf_token %}
{{ form.username.label_tag }} {{ form.username }}
{{ form.password.label_tag }} {{ form.password }}
{% csrf_token %}
{% csrf_token %} {{ form.non_field_errors }} {% for hidden_field in form.hidden_fields %} {{ hidden_field.errors }} {{ hidden_field }} {% endfor %} {% for field in form.visible_fields %} {% endfor %}
{{ field.label_tag }} {{ field.errors }} {{ field }} {{ field.help_text }}
==== How does it work? ==== When we write ''{{ form }}'' in a template, it’s actually accessing the ''__str__'' method from the BaseForm class. We can use other three methods to render it (as table, as p, as ul tags): as_table(), as_ul(), as_p(). The as_table() and as_ul() methods do not create the and the
{{ form }}
==== The form definition ==== class ColorfulContactForm(forms.Form): name = forms.CharField( max_length=30, widget=forms.TextInput( attrs={ 'style': 'border-color: blue;', 'placeholder': 'Write your name here' } ) ) email = forms.EmailField( max_length=254, widget=forms.EmailInput(attrs={'style': 'border-color: green;'}) ) message = forms.CharField( max_length=2000, widget=forms.Textarea(attrs={'style': 'border-color: orange;'}), help_text='Write here your message!' ) ==== The validation process... ==== Converts all the data to proper values in ''cleaned_data'' if they are, for sure, valid. An example of a Boolean field: class MyForm(forms.Form): has_code = forms.BooleanField(widget= forms.CheckboxInput()) def my_form_view(request): if request.method == 'POST': my_form = MyForm(request.POST) if my_form.is_valid(): # my_form.cleaned_data['has_code'] is now a bool ===== Gotchas ===== unique_together = ('accounting_year', 'number',) ===== Widgets ===== You can define widgets on for the fields on the same form: class PurchaseOrderForm(forms.ModelForm): class Meta: model = PurchaseOrder fields = '__all__' widgets = { 'bill_price': EuroWidget(), 'total_amount': EuroWidget(), } ==== Add a widget to a field ==== city = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'})) También lo puedes añadir en el meta: 'widgets': {'city': forms.TextInput} ===== Fields ===== ==== Choice ==== === From DB === IF you are saving cities into the database, you can use ModelChoiceField: class SelectCityForm(forms.Form): cities = forms.ModelChoiceField(queryset=City.objects.all()) ==== Create your own field ==== You need the field and the widget: class SelectMultipleChecks(forms.Widget): template_name = 'widgets/multiple_checks.html' def __init__(self, *args, choices=(), defaults=(), **kwargs): super().__init__(*args, **kwargs) self.choices = choices def get_context(self, name, value, attrs): context = super().get_context(name, value, attrs) context['choices'] = self.choices return context class SelectMultipleChecksField(forms.Field): widget = SelectMultipleChecks def __init__(self, *args, choices=(), defaults=(), **kwargs): super().__init__(*args, **kwargs) self.choices = choices def _get_choices(self): return self._choices def _set_choices(self, value): if callable(value): value = CallableChoiceIterator(value) else: value = list(value) self._choices = self.widget.choices = value choices = property(_get_choices, _set_choices) def to_python(self, value): import json values = json.loads(value) i_values = [int(v) for v in values] return [choice for choice in self._choices if choice.pk in i_values] def validate(self, value): assert len(value) > 0 def valid_value(self, value): return value With this we can have the template ''widgets/multiple_checks.html'':
{% for choice in choices %}
{{ choice }}
{% endfor %}
=== Set rendered properties === You can set properties to render like this: city = forms.CharField(widget=forms.TextInput(attrs={'autocomplete':'off'}))