# Django 6.0.5 documentation

# Skapa formulär från modeller

## `ModelForm`

class ModelForm

Om du bygger en databasdriven app är chansen stor att du har formulär som är nära kopplade till Django-modeller. Till exempel kan du ha en `BlogComment`-modell, och du vill skapa ett formulär som låter människor skicka in kommentarer. I det här fallet skulle det vara överflödigt att definiera fälttyperna i ditt formulär, eftersom du redan har definierat fälten i din modell.

Av denna anledning tillhandahåller Django en hjälpklass som låter dig skapa en `Form`-klass från en Django-modell.

Till exempel:

    >>> from django.forms import ModelForm
    >>> from myapp.models import Article

    # Create the form class.
    >>> class ArticleForm(ModelForm):
    ...     class Meta:
    ...         model = Article
    ...         fields = ["pub_date", "headline", "content", "reporter"]
    ...

    # Creating a form to add an article.
    >>> form = ArticleForm()

    # Creating a form to change an existing article.
    >>> article = Article.objects.get(pk=1)
    >>> form = ArticleForm(instance=article)

### Fälttyper

Den genererade klassen `Form` kommer att ha ett formulärfält för varje modellfält som anges, i den ordning som anges i attributet `fields`.

Varje modellfält har ett motsvarande standardformulärsfält. Till exempel representeras ett `CharField` i en modell som ett `CharField` i ett formulär. En modells `ManyToManyField` representeras som en `MultipleChoiceField`. Här är den fullständiga listan över konverteringar:

Modellfält | Formulärfält
--- | ---
`AutoField` | Ej representerad i formuläret
`BigAutoField` | Ej representerad i formuläret
`BigIntegerField` | `IntegerField` med `min_value` satt till -9223372036854775808 och `max_value` satt till 9223372036854775807.
`BinaryField` | `CharField`, om `editable` är satt till `True` på modellfältet, annars inte representerad i formuläret.
`BooleanField` | `BooleanField`, eller `NullBooleanField` om `null=True`.
`CharField` | `CharField` med `max_length` satt till modellfältets `max_length` och `empty_value` satt till `None` om `null=True`.
`DateField` | `DateField`
`DateTimeField` | `DateTimeField`
`DecimalField` | `DecimalField`
`DurationField` | `DurationField`
`EmailField` | `EmailField`
`FileField` | `FileField`
`FilePathField` | `FilePathField`
`FloatField` | `FloatField`
`ForeignKey` | `ModelChoiceField` (se nedan)
`ImageField` | `ImageField`
`IntegerField` | `IntegerField`
`IPAddressField` | `IPAddressField`
`GeneriskIPAddressField` | `GenericIPAddressField`
`JSONField` | `JSONField`
`ManyToManyField` | `ModelMultipleChoiceField` (se nedan)
`PositivBigIntegerField` | `IntegerField`
`PositivIntegerField` | `IntegerField`
`Positiv LitenIntegerField` | `IntegerField`
`SlugField` | `SlugField`
`SmallAutoField` | Ej representerad i formuläret
`SmallIntegerField` | `IntegerField`
`TextField` | `CharField` med `widget=forms.Textarea`
`TimeField` | `TimeField`
`URLField` | `URLField`
`UUIDField` | `UUIDField`

Som du kanske förväntar dig är modellfälttyperna `ForeignKey` och `ManyToManyField` specialfall:

- `ForeignKey` representeras av `django.forms.ModelChoiceField`, som är en `ChoiceField` vars val är en modell `QuerySet`.

- `ManyToManyField` representeras av `django.forms.ModelMultipleChoiceField`, som är en `MultipleChoiceField` vars val är en modell `QuerySet`.

Dessutom har varje genererat formulärfält attribut som är inställda enligt följande:

- Om modellfältet har `blank=True`, sätts `required` till `False` på formulärfältet. Annars är `required=True`.

- Formulärfältets `label` sätts till modellfältets `verbose_name`, med det första tecknet med stor bokstav.

- Formulärfältets `help_text` sätts till modellfältets `help_text`.

- Om modellfältet har `choices` inställt, kommer formulärfältets `widget` att vara inställt på `Select`, med val som kommer från modellfältets `choices`. Valmöjligheterna inkluderar normalt det tomma valet som är valt som standard. Om fältet är obligatoriskt tvingar detta användaren att göra ett val. Det tomma valet kommer inte att inkluderas om modellfältet har `blank=False` och ett explicit `default`-värde (`default`-värdet kommer att väljas initialt istället).

Observera slutligen att du kan åsidosätta det formulärfält som används för ett visst modellfält. Se Overstyra standardfälten nedan.

### Ett fullständigt exempel

Tänk på denna uppsättning modeller:

    from django.db import models
    from django.forms import ModelForm

    TITLE_CHOICES = {
        "MR": "Mr.",
        "MRS": "Mrs.",
        "MS": "Ms.",
    }

    class Author(models.Model):
        name = models.CharField(max_length=100)
        title = models.CharField(max_length=3, choices=TITLE_CHOICES)
        birth_date = models.DateField(blank=True, null=True)

        def __str__(self):
            return self.name

    class Book(models.Model):
        name = models.CharField(max_length=100)
        authors = models.ManyToManyField(Author)

    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ["name", "title", "birth_date"]

    class BookForm(ModelForm):
        class Meta:
            model = Book
            fields = ["name", "authors"]

Med dessa modeller skulle `ModelForm`-underklasserna ovan vara ungefär likvärdiga med detta (den enda skillnaden är `save()`-metoden, som vi kommer att diskutera om ett ögonblick.):

    from django import forms

    class AuthorForm(forms.Form):
        name = forms.CharField(max_length=100)
        title = forms.CharField(
            max_length=3,
            widget=forms.Select(choices=TITLE_CHOICES),
        )
        birth_date = forms.DateField(required=False)

    class BookForm(forms.Form):
        name = forms.CharField(max_length=100)
        authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())

### Validering på en `ModelForm`

Det finns två huvudsakliga steg i valideringen av en `ModelForm`:

1. Validering av formuläret

2. Validering av modellinstansen

Just like normal form validation, model form validation is triggered implicitly when calling `is_valid()` or accessing the `errors` attribute and explicitly when calling `full_clean()`, although you will typically not use the latter method in practice.

`Model` validation is triggered from within the form validation step right after the form’s `clean()` method is called. First, the model’s `full_clean()` is called with `validate_unique=False` and `validate_constraints=False`, then the model’s `validate_unique()` and `validate_constraints()` methods are called in order.

Varning

Rengöringsprocessen ändrar den modellinstans som skickas till konstruktören `ModelForm` på olika sätt. Till exempel konverteras alla datumfält i modellen till faktiska datumobjekt. Misslyckad validering kan lämna den underliggande modellinstansen i ett inkonsekvent tillstånd och därför rekommenderas det inte att återanvända den.

#### Åsidosättande av metoden `clean()`

Du kan åsidosätta metoden `clean()` på ett modellformulär för att tillhandahålla ytterligare validering på samma sätt som du kan på ett normalt formulär.

En model form-instans som är kopplad till ett model-objekt innehåller ett `instance`-attribut som ger dess metoder tillgång till den specifika model-instansen.

Varning

The `ModelForm.clean()` method sets flags that make the model validation step validate the uniqueness of model fields that are marked as `unique`, `unique_together` or `unique_for_date|month|year`, as well as constraints.

Om du vill åsidosätta metoden `clean()` och behålla denna validering måste du anropa den överordnade klassens metod `clean()`.

#### Samverkan med modellvalidering

Som en del av valideringsprocessen kommer `ModelForm` att anropa `clean()`-metoden för varje fält i din modell som har ett motsvarande fält i ditt formulär. Om du har uteslutit några modellfält kommer valideringen inte att köras på dessa fält. Se formulärsvalidering-dokumentationen för mer information om hur fältrengöring och validering fungerar.

The model’s `clean()` method will be called before any uniqueness or constraint checks are made. See Validating objects for more information on the model’s `clean()` hook.

#### Överväganden angående modellens `error_messages`

Felmeddelanden som definieras på nivån `form field` eller på nivån form Meta har alltid företräde framför felmeddelanden som definieras på nivån `model field`.

Felmeddelanden som definieras på `modellfält` används endast när `ValidationError` uppstår under modellvalidering och inga motsvarande felmeddelanden har definierats på formulärnivå.

Du kan åsidosätta felmeddelandena från `NON_FIELD_ERRORS` som uppkommer vid modellvalidering genom att lägga till `NON_FIELD_ERRORS`-nyckeln i `error_messages`-ordlistan i `ModelForm`:s inre `Meta`-klass:

    from django.core.exceptions import NON_FIELD_ERRORS
    from django.forms import ModelForm

    class ArticleForm(ModelForm):
        class Meta:
            error_messages = {
                NON_FIELD_ERRORS: {
                    "unique_together": "%(model_name)s's %(field_labels)s are not unique.",
                }
            }

### Metoden ”spara()``

Varje `ModelForm` har också en `save()`-metod. Denna metod skapar och sparar ett databasobjekt från de data som är bundna till formuläret. En subklass av `ModelForm` kan acceptera en befintlig modellinstans som nyckelordsargumentet `instance`; om detta tillhandahålls kommer `save()` att uppdatera den instansen. Om det inte anges kommer `save()` att skapa en ny instans av den angivna modellen:

    >>> from myapp.models import Article
    >>> from myapp.forms import ArticleForm

    # Create a form instance from POST data.
    >>> f = ArticleForm(request.POST)

    # Save a new Article object from the form's data.
    >>> new_article = f.save()

    # Create a form to edit an existing Article, but use
    # POST data to populate the form.
    >>> a = Article.objects.get(pk=1)
    >>> f = ArticleForm(request.POST, instance=a)
    >>> f.save()

Observera att om formuläret inte har validerats, kommer anrop av `save()` att göra det genom att kontrollera `form.errors`. Ett `ValueError` kommer att uppstå om data i formuläret inte valideras – dvs. om `form.errors` utvärderas till `True`.

Om ett valfritt fält inte visas i formulärets data använder den resulterande modellinstansen modellfältet `default`, om det finns ett sådant, för det fältet. Detta beteende gäller inte för fält som använder `CheckboxInput`, `CheckboxSelectMultiple`, eller `SelectMultiple` (eller någon anpassad widget vars `value_omitted_from_data()` alltid returnerar `False`) eftersom en avmarkerad kryssruta och omarkerad `<select multiple>` inte visas i data för en HTML-formulärinlämning. Använd ett anpassat formulärfält eller en widget om du utformar ett API och vill ha ett standardfallbackbeteende för ett fält som använder en av dessa widgetar.

Denna metod `save()` accepterar ett valfritt nyckelordsargument `commit`, som accepterar antingen `True` eller `False`. Om du anropar `save()` med `commit=False` kommer den att returnera ett objekt som ännu inte har sparats i databasen. I det här fallet är det upp till dig att anropa `save()` på den resulterande modellinstansen. Detta är användbart om du vill göra anpassad bearbetning på objektet innan du sparar det, eller om du vill använda ett av de specialiserade modellsparingsalternativen. `commit` är `True` som standard.

En annan bieffekt av att använda `commit=False` är när din modell har en många-till-många-relation med en annan modell. Om din modell har en many-to-many-relation och du anger `commit=False` när du sparar ett formulär, kan Django inte omedelbart spara formulärdata för many-to-many-relationen. Detta beror på att det inte är möjligt att spara many-to-many-data för en instans förrän instansen finns i databasen.

För att komma runt detta problem lägger Django till en metod `save_m2m()` till din underklass `ModelForm` varje gång du sparar ett formulär med `commit=False`. När du manuellt har sparat den instans som produceras av formuläret kan du anropa `save_m2m()` för att spara formulärdata från många till många. Ett exempel:

    # Create a form instance with POST data.
    >>> f = AuthorForm(request.POST)

    # Create, but don't save the new author instance.
    >>> new_author = f.save(commit=False)

    # Modify the author in some way.
    >>> new_author.some_field = "some_value"

    # Save the new instance.
    >>> new_author.save()

    # Now, save the many-to-many data for the form.
    >>> f.save_m2m()

Calling `save_m2m()` is only required if you use `save(commit=False)`. When you use a `save()` on a form, all data – including many-to-many data – is saved without the need for any additional method calls. For example:

    # Create a form instance with POST data.
    >>> a = Author()
    >>> f = AuthorForm(request.POST, instance=a)

    # Create and save the new author instance. There's no need to do anything else.
    >>> new_author = f.save()

Förutom metoderna `save()` och `save_m2m()` fungerar en `ModelForm` på exakt samma sätt som alla andra `forms`-formulär. Till exempel används metoden `is_valid()` för att kontrollera giltigheten, metoden `is_multipart()` används för att avgöra om ett formulär kräver uppladdning av flera filer (och därmed om `request.FILES` måste skickas till formuläret), etc. Se Binder uppladdade filer till ett formulär för mer information.

### Välja de fält som ska användas

Det rekommenderas starkt att du uttryckligen anger alla fält som ska redigeras i formuläret med hjälp av attributet `fields`. Om man inte gör det kan det lätt leda till säkerhetsproblem när ett formulär oväntat tillåter en användare att ställa in vissa fält, särskilt när nya fält läggs till i en modell. Beroende på hur formuläret renderas kanske problemet inte ens är synligt på webbsidan.

The alternative approach would be to include all fields automatically, or remove only some. This fundamental approach is known to be much less secure and has led to serious exploits on major websites (e.g. GitHub ).

Det finns dock två genvägar för de fall där du kan garantera att dessa säkerhetsproblem inte gäller dig:

1. Sätt attributet `fields` till specialvärdet `'__all__'` för att ange att alla fält i modellen ska användas. Till exempel:

       from django.forms import ModelForm

       class AuthorForm(ModelForm):
           class Meta:
               model = Author
               fields = "__all__"

2. Ställ in attributet `exclude` i `ModelForm`:s inre `Meta`-klass till en lista över fält som ska uteslutas från formuläret.

   Till exempel:

       class PartialAuthorForm(ModelForm):
           class Meta:
               model = Author
               exclude = ["title"]

   Eftersom modellen `Author` har de 3 fälten `name`, `title` och `birth_date`, kommer detta att resultera i att fälten `name` och `birth_date` finns på formuläret.

Om något av dessa alternativ används kommer fälten att visas i formuläret i den ordning som fälten definieras i modellen, med `ManyToManyField`-instanser sist.

Dessutom tillämpar Django följande regel: om du ställer in `editable=False` på modellfältet, kommer alla formulär som skapas från modellen via `ModelForm` inte att innehålla det fältet.

Observera

Alla fält som inte inkluderas i ett formulär med ovanstående logik kommer inte att ställas in med formulärets `save()`-metod. Om du manuellt lägger till de uteslutna fälten i formuläret kommer de inte heller att initialiseras från modellinstansen.

Django will prevent any attempt to save an incomplete model, so if the model does not allow the missing fields to be empty, and does not provide a default value for the missing fields, any attempt to `save()` a `ModelForm` with missing fields will fail. To avoid this failure, you must instantiate your model with initial values for the missing, but required fields:

    author = Author(title="Mr")
    form = PartialAuthorForm(request.POST, instance=author)
    form.save()

Alternativt kan du använda `save(commit=False)` och manuellt ange eventuella extra obligatoriska fält:

    form = PartialAuthorForm(request.POST)
    author = form.save(commit=False)
    author.title = "Mr"
    author.save()

Se avsnittet om att spara formulär för mer information om hur du använder `save(commit=False)`.

### Åsidosätta standardfälten

Standardfälttyperna, som beskrivs i tabellen Field types ovan, är förnuftiga standardvärden. Om du har ett `DateField` i din modell är chansen stor att du vill att det ska representeras som ett `DateField` i ditt formulär. Men `ModelForm` ger dig flexibiliteten att ändra formulärfältet för en given modell.

Om du vill ange en anpassad widget för ett fält använder du attributet `widgets` i den inre klassen `Meta`. Detta bör vara en ordbok som mappar fältnamn till widgetklasser eller -instanser.

Om du till exempel vill att `CharField` för attributet `name` i `Author` ska representeras av en `<textarea>` i stället för standardvärdet `<input type="text">`, kan du åsidosätta fältets widget:

    from django.forms import ModelForm, Textarea
    from myapp.models import Author

    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ["name", "title", "birth_date"]
            widgets = {
                "name": Textarea(attrs={"cols": 80, "rows": 20}),
            }

Ordboken `widgets` accepterar antingen widgetinstanser (t.ex. `Textarea(...)`) eller klasser (t.ex. `Textarea`). Observera att `widgets`-dictionary ignoreras för ett modellfält med ett icke-tomt `choices`-attribut. I det här fallet måste du åsidosätta formulärfältet för att använda en annan widget.

På samma sätt kan du ange attributen `labels`, `help_texts` och `error_messages` i den inre klassen `Meta` om du vill anpassa ett fält ytterligare.

Om du till exempel vill anpassa ordalydelsen i alla strängar för fältet `namn` för användare:

    from django.utils.translation import gettext_lazy as _

    class AuthorForm(ModelForm):
        class Meta:
            model = Author
            fields = ["name", "title", "birth_date"]
            labels = {
                "name": _("Writer"),
            }
            help_texts = {
                "name": _("Some useful help text."),
            }
            error_messages = {
                "name": {
                    "max_length": _("This writer's name is too long."),
                },
            }

Du kan också ange `field_classes` eller `formfield_callback` för att anpassa typen av fält som instansieras av formuläret.

Om du till exempel vill använda `MySlugFormField` för fältet `slug` kan du göra följande:

    from django.forms import ModelForm
    from myapp.models import Article

    class ArticleForm(ModelForm):
        class Meta:
            model = Article
            fields = ["pub_date", "headline", "content", "reporter", "slug"]
            field_classes = {
                "slug": MySlugFormField,
            }

eller:

    from django.forms import ModelForm
    from myapp.models import Article

    def formfield_for_dbfield(db_field, **kwargs):
        if db_field.name == "slug":
            return MySlugFormField()
        return db_field.formfield(**kwargs)

    class ArticleForm(ModelForm):
        class Meta:
            model = Article
            fields = ["pub_date", "headline", "content", "reporter", "slug"]
            formfield_callback = formfield_for_dbfield

Slutligen, om du vill ha fullständig kontroll över ett fält - inklusive dess typ, validerare, obligatoriska osv. – kan du göra detta genom att deklarativt specificera fält som du skulle göra i en vanlig `Form`.

Om du vill ange ett fälts validatorer kan du göra det genom att definiera fältet deklarativt och ange parametern `validators`:

    from django.forms import CharField, ModelForm
    from myapp.models import Article

    class ArticleForm(ModelForm):
        slug = CharField(validators=[validate_slug])

        class Meta:
            model = Article
            fields = ["pub_date", "headline", "content", "reporter", "slug"]

Observera

När du uttryckligen instansierar ett formulärfält på det här sättet är det viktigt att förstå hur `ModelForm` och vanliga `Form` hänger ihop.

`ModelForm` är en vanlig `Form` som automatiskt kan generera vissa fält. De fält som genereras automatiskt beror på innehållet i klassen `Meta` och på vilka fält som redan har definierats deklarativt. I grund och botten kommer `ModelForm` endast att generera fält som saknas i formuläret, eller med andra ord, fält som inte definierats deklarativt.

Fält som definieras deklarativt lämnas som de är, och därför ignoreras alla anpassningar som gjorts av `Meta`-attribut som `widgets`, `labels`, `help_texts` eller `error_messages`; dessa gäller endast för fält som genereras automatiskt.

På samma sätt hämtar fält som definieras deklarativt inte sina attribut som `max_length` eller `required` från motsvarande modell. Om du vill behålla det beteende som anges i modellen måste du ange de relevanta argumenten explicit när du deklarerar formulärfältet.

Till exempel, om modellen `Artikel` ser ut så här:

    class Article(models.Model):
        headline = models.CharField(
            max_length=200,
            null=True,
            blank=True,
            help_text="Use puns liberally",
        )
        content = models.TextField()

och du vill göra en anpassad validering för `headline`, samtidigt som du behåller värdena `blank` och `help_text` som specificerade, kan du definiera `ArticleForm` så här:

    class ArticleForm(ModelForm):
        headline = MyFormField(
            max_length=200,
            required=False,
            help_text="Use puns liberally",
        )

        class Meta:
            model = Article
            fields = ["headline", "content"]

Du måste se till att formulärfältets typ kan användas för att ange innehållet i motsvarande modellfält. Om de inte är kompatibla kommer du att få ett `ValueError` eftersom ingen implicit konvertering sker.

Se Formulärfältsdokumentation för mer information om fält och deras argument.

### Möjliggör lokalisering av fält

Som standard kommer fälten i ett `ModelForm` inte att lokalisera sina data. För att aktivera lokalisering för fält kan du använda attributet `localized_fields` på klassen `Meta`.

    >>> from django.forms import ModelForm
    >>> from myapp.models import Author
    >>> class AuthorForm(ModelForm):
    ...     class Meta:
    ...         model = Author
    ...         localized_fields = ['birth_date']

Om `localized_fields` är satt till specialvärdet `'__all__'`, kommer alla fält att lokaliseras.

### Form av arv

Precis som med grundläggande formulär kan du utöka och återanvända `ModelForm`-klasser genom att ärva dem. Detta är användbart om du behöver deklarera extra fält eller extra metoder i en överordnad klass som ska användas i ett antal formulär som härrör från modeller. Till exempel genom att använda den tidigare klassen `ArticleForm`:

    >>> class EnhancedArticleForm(ArticleForm):
    ...     def clean_pub_date(self): ...
    ...

Detta skapar ett formulär som beter sig identiskt med `ArticleForm`, förutom att det finns lite extra validering och rengöring för fältet `pub_date`.

Du kan också subklassa förälderns inre klass `Meta` om du vill ändra listorna `Meta.fields` eller `Meta.exclude`:

    >>> class RestrictedArticleForm(EnhancedArticleForm):
    ...     class Meta(ArticleForm.Meta):
    ...         exclude = ["body"]
    ...

Detta lägger till den extra metoden från `EnhancedArticleForm` och ändrar den ursprungliga `ArticleForm.Meta` för att ta bort ett fält.

Det finns dock ett par saker att notera.

- Normala Python-regler för namnupplösning gäller. Om du har flera basklasser som deklarerar en `Meta` innerklass, kommer endast den första att användas. Detta innebär barnets `Meta`, om det finns, annars den första förälderns `Meta`, etc.

- Det är möjligt att ärva från både `Form` och `ModelForm` samtidigt, men du måste se till att `ModelForm` visas först i MRO. Detta beror på att dessa klasser förlitar sig på olika metaklasser och en klass kan bara ha en metaklass.

- Det är möjligt att deklarativt ta bort ett `Field` som ärvts från en överordnad klass genom att ställa in namnet till `None` i underklassen.

  Du kan bara använda den här tekniken för att välja bort ett fält som definieras deklarativt av en överordnad klass; det hindrar inte metaklassen `ModelForm` från att generera ett standardfält. För att välja bort standardfält, se Välja de fält som ska användas.

### Tillhandahållande av initiala värden

Precis som med vanliga formulär går det att ange initiala data för formulär genom att ange en `initial`-parameter när formuläret instansieras. Initiala värden som anges på detta sätt åsidosätter både initiala värden från formulärfältet och värden från en ansluten modellinstans. Ett exempel:

    >>> article = Article.objects.get(pk=1)
    >>> article.headline
    'My headline'
    >>> form = ArticleForm(initial={"headline": "Initial headline"}, instance=article)
    >>> form["headline"].value()
    'Initial headline'

### ModelForm fabriksfunktion

Du kan skapa formulär från en given modell med hjälp av den fristående funktionen `modelform_factory()`, istället för att använda en klassdefinition. Detta kan vara mer praktiskt om du inte har många anpassningar att göra:

    >>> from django.forms import modelform_factory
    >>> from myapp.models import Book
    >>> BookForm = modelform_factory(Book, fields=["author", "title"])

Detta kan också användas för att göra ändringar i befintliga formulär, t.ex. genom att ange vilka widgets som ska användas för ett visst fält:

    >>> from django.forms import Textarea
    >>> Form = modelform_factory(Book, form=BookForm, widgets={"title": Textarea()})

De fält som ska inkluderas kan anges med hjälp av nyckelordsargumenten `fields` och `exclude`, eller motsvarande attribut på den inre `Meta`-klassen `ModelForm`. Se dokumentationen för `ModelForm` Välja de fält som ska användas.

… eller aktivera lokalisering för specifika fält:

    >>> Form = modelform_factory(Author, form=AuthorForm, localized_fields=["birth_date"])

## Modellformsatser

class models.BaseModelFormSet

Liksom regelbundna formulär tillhandahåller Django ett par förbättrade formulärklasser för att göra arbetet med Django-modeller mer bekvämt. Låt oss återanvända modellen `Author` från ovan:

    >>> from django.forms import modelformset_factory
    >>> from myapp.models import Author
    >>> AuthorFormSet = modelformset_factory(Author, fields=["name", "title"])

Om du använder `fields` begränsas formuläret till att endast använda de angivna fälten. Alternativt kan du välja en ”opt-out”-strategi och ange vilka fält som ska uteslutas:

    >>> AuthorFormSet = modelformset_factory(Author, exclude=["birth_date"])

Detta kommer att skapa ett formulär som kan arbeta med data som är associerade med modellen `Author`. Det fungerar precis som ett vanligt formulär:

    >>> formset = AuthorFormSet()
    >>> print(formset)
    <input type="hidden" name="form-TOTAL_FORMS" value="1" id="id_form-TOTAL_FORMS"><input type="hidden" name="form-INITIAL_FORMS" value="0" id="id_form-INITIAL_FORMS"><input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS"><input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS">
    <div><label for="id_form-0-name">Name:</label><input id="id_form-0-name" type="text" name="form-0-name" maxlength="100"></div>
    <div><label for="id_form-0-title">Title:</label><select name="form-0-title" id="id_form-0-title">
    <option value="" selected>---------</option>
    <option value="MR">Mr.</option>
    <option value="MRS">Mrs.</option>
    <option value="MS">Ms.</option>
    </select><input type="hidden" name="form-0-id" id="id_form-0-id"></div>

Observera

`modelformset_factory()` använder `formset_factory()` för att generera formulär. Detta innebär att ett modellformulär är en förlängning av ett grundläggande formulär som vet hur man interagerar med en viss modell.

Observera

När du använder multi-table inheritance kommer formulär som genereras av en formulärfabrik att innehålla ett fält för föräldralänk (som standard `<parent_model_name>_ptr`) i stället för ett `id`-fält.

### Ändra queryset

När du skapar ett formulär från en modell kommer formuläret som standard att använda en queryset som innehåller alla objekt i modellen (t.ex. `Author.objects.all()`). Du kan åsidosätta detta beteende genom att använda argumentet `queryset`:

    >>> formset = AuthorFormSet(queryset=Author.objects.filter(name__startswith="O"))

Alternativt kan du skapa en subklass som ställer in `self.queryset` i `__init__`:

    from django.forms import BaseModelFormSet
    from myapp.models import Author

    class BaseAuthorFormSet(BaseModelFormSet):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.queryset = Author.objects.filter(name__startswith="O")

Sedan skickar du din `BaseAuthorFormSet`-klass till fabriksfunktionen:

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, fields=["name", "title"], formset=BaseAuthorFormSet
    ... )

Om du vill returnera en formuläruppsättning som inte innehåller några redan existerande instanser av modellen kan du ange en tom QuerySet:

    >>> AuthorFormSet(queryset=Author.objects.none())

### Ändring av formuläret

Som standard, när du använder `modelformset_factory`, kommer ett modellformulär att skapas med `modelform_factory()`. Ofta kan det vara användbart att ange ett anpassat modellformulär. Du kan till exempel skapa ett anpassat modellformulär som har anpassad validering:

    class AuthorForm(forms.ModelForm):
        class Meta:
            model = Author
            fields = ["name", "title"]

        def clean_name(self):
            # custom validation for the name field
            ...

Skicka sedan din modellblankett till fabriksfunktionen:

    AuthorFormSet = modelformset_factory(Author, form=AuthorForm)

Det är inte alltid nödvändigt att definiera ett eget modellformulär. Funktionen `modelformset_factory` har flera argument som skickas till `modelform_factory` och som beskrivs nedan.

### Ange widgets som ska användas i formuläret med `widgets`

Med hjälp av parametern `widgets` kan du ange en ordbok med värden för att anpassa `ModelForm`:s widgetklass för ett visst fält. Detta fungerar på samma sätt som `widgets`-ordlistan på den inre `Meta`-klassen i en `ModelForm` fungerar:

    >>> AuthorFormSet = modelformset_factory(
    ...     Author,
    ...     fields=["name", "title"],
    ...     widgets={"name": Textarea(attrs={"cols": 80, "rows": 20})},
    ... )

### Aktivera lokalisering för fält med `localized_fields`

Med hjälp av parametern `localized_fields` kan du aktivera lokalisering för fält i formuläret.

    >>> AuthorFormSet = modelformset_factory(
    ...     Author, fields=['name', 'title', 'birth_date'],
    ...     localized_fields=['birth_date'])

Om `localized_fields` är satt till specialvärdet `'__all__'`, kommer alla fält att lokaliseras.

### Tillhandahållande av initiala värden

Precis som med vanliga formuläruppsättningar är det möjligt att specificera initialdata för formulär i formuläruppsättningen genom att ange en `initial`-parameter när man instansierar klassen model formset som returneras av `modelformset_factory()`. Men med modellformsatser gäller de initiala värdena endast för extra formulär, de som inte är kopplade till en befintlig modellinstans. Om längden på `initial` överstiger antalet extra formulär ignoreras överskottet av initiala data. Om de extra formulären med initiala data inte ändras av användaren kommer de inte att valideras eller sparas.

### Spara objekt i formuläret

Precis som med en `ModelForm` kan du spara data som ett modellobjekt. Detta görs med formsetets metod `save()`:

    # Create a formset instance with POST data.
    >>> formset = AuthorFormSet(request.POST)

    # Assuming all is valid, save the data.
    >>> instances = formset.save()

Metoden `save()` returnerar de instanser som har sparats i databasen. Om data för en viss instans inte har ändrats i de bundna data sparas inte instansen i databasen och ingår inte i returvärdet (`instances`, i exemplet ovan).

Om fält saknas i formuläret (t.ex. för att de har uteslutits) kommer dessa fält inte att anges med metoden `save()`. Mer information om denna begränsning, som även gäller för vanliga modellformulär, finns i Välja vilka fält som ska användas.

Skicka `commit=False` för att returnera de osparade modellinstanserna:

    # don't save to the database
    >>> instances = formset.save(commit=False)
    >>> for instance in instances:
    ...     # do something with instance
    ...     instance.save()
    ...

Detta ger dig möjlighet att bifoga data till instanserna innan du sparar dem i databasen. Om ditt formulär innehåller en `ManyToManyField` måste du också anropa `formset.save_m2m()` för att säkerställa att många-till-många-relationerna sparas korrekt.

När du har anropat `save()` kommer din formulärmodell att ha tre nya attribut som innehåller formulärets ändringar:

models.BaseModelFormSet.changed_objects

models.BaseModelFormSet.deleted_objects

models.BaseModelFormSet.new_objects

### Begränsa antalet redigerbara objekt

Precis som med vanliga formuläruppsättningar kan du använda parametrarna `max_num` och `extra` till `modelformset_factory()` för att begränsa antalet extra formulär som visas.

`max_num` förhindrar inte att befintliga objekt visas:

    >>> Author.objects.order_by("name")
    <QuerySet [<Author: Charles Baudelaire>, <Author: Paul Verlaine>, <Author: Walt Whitman>]>

    >>> AuthorFormSet = modelformset_factory(Author, fields=["name"], max_num=1)
    >>> formset = AuthorFormSet(queryset=Author.objects.order_by("name"))
    >>> [x.name for x in formset.get_queryset()]
    ['Charles Baudelaire', 'Paul Verlaine', 'Walt Whitman']

Dessutom hindrar inte `extra=0` skapandet av nya modellinstanser eftersom du kan lägga till ytterligare formulär med JavaScript eller skicka ytterligare POST-data. Se Förhindrar att nya objekt skapas om hur man gör detta.

Om värdet för `max_num` är större än antalet befintliga relaterade objekt, kommer upp till `extra` ytterligare tomma formulär att läggas till i formuläruppsättningen, så länge det totala antalet formulär inte överstiger `max_num`:

    >>> AuthorFormSet = modelformset_factory(Author, fields=["name"], max_num=4, extra=2)
    >>> formset = AuthorFormSet(queryset=Author.objects.order_by("name"))
    >>> for form in formset:
    ...     print(form)
    ...
    <div><label for="id_form-0-name">Name:</label><input id="id_form-0-name" type="text" name="form-0-name" value="Charles Baudelaire" maxlength="100"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id"></div>
    <div><label for="id_form-1-name">Name:</label><input id="id_form-1-name" type="text" name="form-1-name" value="Paul Verlaine" maxlength="100"><input type="hidden" name="form-1-id" value="3" id="id_form-1-id"></div>
    <div><label for="id_form-2-name">Name:</label><input id="id_form-2-name" type="text" name="form-2-name" value="Walt Whitman" maxlength="100"><input type="hidden" name="form-2-id" value="2" id="id_form-2-id"></div>
    <div><label for="id_form-3-name">Name:</label><input id="id_form-3-name" type="text" name="form-3-name" maxlength="100"><input type="hidden" name="form-3-id" id="id_form-3-id"></div>

Ett värde på `max_num` på `None` (standard) sätter en hög gräns för antalet formulär som visas (1000). I praktiken är detta likvärdigt med ingen gräns.

### Förhindrar att nya objekt skapas

Med hjälp av parametern `edit_only` kan du förhindra att nya objekt skapas:

    >>> AuthorFormSet = modelformset_factory(
    ...     Author,
    ...     fields=["name", "title"],
    ...     edit_only=True,
    ... )

Här kommer formuläret endast att redigera befintliga `Author`-instanser. Inga andra objekt kommer att skapas eller redigeras.

### Använda en formulärmodell i en vy

Modellformulären är mycket lika formulären. Låt oss säga att vi vill presentera ett formulär för att redigera `Author` modellinstanser:

    from django.forms import modelformset_factory
    from django.shortcuts import render
    from myapp.models import Author

    def manage_authors(request):
        AuthorFormSet = modelformset_factory(Author, fields=["name", "title"])
        if request.method == "POST":
            formset = AuthorFormSet(request.POST, request.FILES)
            if formset.is_valid():
                formset.save()
                # do something.
        else:
            formset = AuthorFormSet()
        return render(request, "manage_authors.html", {"formset": formset})

Som du kan se är visningslogiken för ett modellformulär inte drastiskt annorlunda än för ett ”vanligt” formulär. Den enda skillnaden är att vi anropar `formset.save()` för att spara data i databasen. (Detta beskrevs ovan, i Spara objekt i formuläret.)

### Åsidosätta `clean()` på en `ModelFormSet`

Just like with a `ModelForm`, by default the `clean()` method of a `ModelFormSet` will validate that none of the items in the formset violate the unique constraints on your model (either `unique`, `unique_together` or `unique_for_date|month|year`). If you want to override the `clean()` method on a `ModelFormSet` and maintain this validation, you must call the parent class’s `clean` method:

    from django.forms import BaseModelFormSet

    class MyModelFormSet(BaseModelFormSet):
        def clean(self):
            super().clean()
            # example custom validation across forms in the formset
            for form in self.forms:
                # your custom formset validation
                ...

Observera också att när du kommer till det här steget har individuella modellinstanser redan skapats för varje `Form`. Att ändra ett värde i `form.cleaned_data` är inte tillräckligt för att påverka det sparade värdet. Om du vill ändra ett värde i `ModelFormSet.clean()` måste du ändra `form.instance`:

    from django.forms import BaseModelFormSet

    class MyModelFormSet(BaseModelFormSet):
        def clean(self):
            super().clean()

            for form in self.forms:
                name = form.cleaned_data["name"].upper()
                form.cleaned_data["name"] = name
                # update the instance value.
                form.instance.name = name

### Använda en anpassad queryset

Som tidigare nämnts kan du åsidosätta den förvalda queryset som används av modellen formset:

    from django.forms import modelformset_factory
    from django.shortcuts import render
    from myapp.models import Author

    def manage_authors(request):
        AuthorFormSet = modelformset_factory(Author, fields=["name", "title"])
        queryset = Author.objects.filter(name__startswith="O")
        if request.method == "POST":
            formset = AuthorFormSet(
                request.POST,
                request.FILES,
                queryset=queryset,
            )
            if formset.is_valid():
                formset.save()
                # Do something.
        else:
            formset = AuthorFormSet(queryset=queryset)
        return render(request, "manage_authors.html", {"formset": formset})

Observera att vi skickar argumentet `queryset` i både `POST` och `GET`-fallen i detta exempel.

### Använda formuläret i mallen

Det finns tre sätt att rendera en formuläruppsättning i en Django-mall.

För det första kan du låta formuläret göra det mesta av jobbet:

    <form method="post">
        {{ formset }}
    </form>

För det andra kan du manuellt rendera formuläruppsättningen, men låta formuläret sköta sig självt:

    <form method="post">
        {{ formset.management_form }}
        {% for form in formset %}
            {{ form }}
        {% endfor %}
    </form>

När du manuellt renderar formulären själv, se till att rendera förvaltningsformuläret enligt ovan. Se dokumentation för förvaltningsformulär.

För det tredje kan du göra en manuell rendering av varje fält:

    <form method="post">
        {{ formset.management_form }}
        {% for form in formset %}
            {% for field in form %}
                {{ field.label_tag }} {{ field }}
            {% endfor %}
        {% endfor %}
    </form>

Om du väljer att använda den här tredje metoden och inte itererar över fälten med en `{% feller %}`-loop, måste du rendera fältet för primärnyckeln. Om du till exempel skulle rendera fälten `namn` och `ålder` i en modell:

    <form method="post">
        {{ formset.management_form }}
        {% for form in formset %}
            {{ form.id }}
            <ul>
                <li>{{ form.name }}</li>
                <li>{{ form.age }}</li>
            </ul>
        {% endfor %}
    </form>

Lägg märke till hur vi uttryckligen måste rendera `{{ form.id }}`. Detta säkerställer att modellformuläret, i fallet `POST`, kommer att fungera korrekt. (I det här exemplet antas en primärnyckel med namnet `id`. Om du uttryckligen har definierat din egen primärnyckel som inte heter `id`, se till att den renderas)

## Inline-formulär

class models.BaseInlineFormSet

Inline-formulär är ett litet abstraktionslager ovanpå modellformulären. Dessa förenklar fallet med att arbeta med relaterade objekt via en främmande nyckel. Anta att du har dessa två modeller:

    from django.db import models

    class Author(models.Model):
        name = models.CharField(max_length=100)

    class Book(models.Model):
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
        title = models.CharField(max_length=100)

Om du vill skapa ett formulär som gör att du kan redigera böcker som tillhör en viss författare kan du göra så här:

    >>> from django.forms import inlineformset_factory
    >>> BookFormSet = inlineformset_factory(Author, Book, fields=["title"])
    >>> author = Author.objects.get(name="Mike Royko")
    >>> formset = BookFormSet(instance=author)

`BookFormSet` s prefix är `'book_set'` (`<model name>_set` ). Om `Book`’s `ForeignKey` till `Author` har en `related_name`, används den istället.

Observera

`inlineformset_factory()` använder `modelformset_factory()` och markerar `can_delete=True`.

Se även

Manuell rendering av can_delete och can_order.

### Åsidosätta metoder för en `InlineFormSet`

När du åsidosätter metoder på `InlineFormSet` bör du underordna dig `BaseInlineFormSet` snarare än `BaseModelFormSet`.

Till exempel, om du vill åsidosätta `clean()`:

    from django.forms import BaseInlineFormSet

    class CustomInlineFormSet(BaseInlineFormSet):
        def clean(self):
            super().clean()
            # example custom validation across forms in the formset
            for form in self.forms:
                # your custom formset validation
                ...

Se även Åsidosätta clean() på en ModelFormSet.

När du sedan skapar din inline-formulärsats skickar du in det valfria argumentet `formulärsats`:

    >>> from django.forms import inlineformset_factory
    >>> BookFormSet = inlineformset_factory(
    ...     Author, Book, fields=["title"], formset=CustomInlineFormSet
    ... )
    >>> author = Author.objects.get(name="Mike Royko")
    >>> formset = BookFormSet(instance=author)

### Mer än en främmande nyckel till samma modell

Om din modell innehåller mer än en främmande nyckel till samma modell måste du lösa tvetydigheten manuellt med hjälp av `fk_name`. Tänk till exempel på följande modell:

    class Friendship(models.Model):
        from_friend = models.ForeignKey(
            Friend,
            on_delete=models.CASCADE,
            related_name="from_friends",
        )
        to_friend = models.ForeignKey(
            Friend,
            on_delete=models.CASCADE,
            related_name="friends",
        )
        length_in_months = models.IntegerField()

För att lösa detta kan du använda `fk_name` till `inlineformset_factory()`:

    >>> FriendshipFormSet = inlineformset_factory(
    ...     Friend, Friendship, fk_name="from_friend", fields=["to_friend", "length_in_months"]
    ... )

### Använda en inline-formulärsats i en vy

Du kanske vill tillhandahålla en vy som gör det möjligt för en användare att redigera de relaterade objekten i en modell. Så här kan du göra det:

    def manage_books(request, author_id):
        author = Author.objects.get(pk=author_id)
        BookInlineFormSet = inlineformset_factory(Author, Book, fields=["title"])
        if request.method == "POST":
            formset = BookInlineFormSet(request.POST, request.FILES, instance=author)
            if formset.is_valid():
                formset.save()
                # Do something. Should generally end with a redirect. For example:
                return HttpResponseRedirect(author.get_absolute_url())
        else:
            formset = BookInlineFormSet(instance=author)
        return render(request, "manage_books.html", {"formset": formset})

Notera hur vi skickar `instance` i både `POST` och `GET` fallen.

### Ange widgetar som ska användas i inline-formuläret

`inlineformset_factory` använder `modelformset_factory` och skickar de flesta av sina argument till `modelformset_factory`. Detta innebär att du kan använda parametern `widgets` på ungefär samma sätt som när du skickar den till `modelformset_factory`. Se Specificera widgets som ska användas i formuläret med widgets ovan.