Django Forms

Arguments

views.py:

def get_form_kwargs(self):
    kwargs = super().get_form_kwargs()
    kwargs.update({"contact": self._contact()})
    return kwargs

forms.py:

class InvoiceUpdateForm(RequiredFieldForm):
    def __init__(self, *args, **kwargs):
        self.contact = kwargs.pop("contact")
        super().__init__(*args, **kwargs)

Fields

To change the text for a ChoiceField:

class UserModelMultipleChoiceField(forms.ModelMultipleChoiceField):
    def label_from_instance(self, obj):
        return "{} ({})".format(obj.get_full_name(), obj.username)

class AppSettingsForm(forms.ModelForm):
    class Meta:
        model = AppSettings
        fields = ("app_superusers", "contact_administrators")
        field_classes = {
            "app_superusers": UserModelMultipleChoiceField,
            "contact_administrators": UserModelMultipleChoiceField,
        }

Hidden

To hide a field:

if not settings.show_method:
    self.fields["methods"].widget = forms.HiddenInput()

Initial

def get_initial(self):
    result = super().get_initial()
    result.update(dict(category_type=self._category_type().pk))
    return result

Label

To change the label:

self.fields["category"].label = "Category"

Required

for name in ("assessor_comments", "result"):
   self.fields[name].required = True

Testing

assert HTTPStatus.FOUND == response.status_code, response.context["form"].errors

Upload

For a form, setup with multipart:

{% include '_form.html' with multipart=True %}

Include the file in the form data as follows:

import pathlib
from django.conf import settings
from django.test.client import MULTIPART_CONTENT

file_name = pathlib.Path(
    settings.BASE_DIR, settings.MEDIA_ROOT, "data", "1-2-3.doc"
)
with open(file_name, "rb") as f:
    response = client.post(
        reverse("document.create"),
        {"name": "Agriculture", "template": f},
        content_type=MULTIPART_CONTENT,
    )

Tip

Copy 1-2-3.doc to ./media/data/1-2-3.doc.