# Django 6.0.7 documentation

# Formtillgångar (klassen ”Media”)

För att skapa ett attraktivt och lättanvänt webbformulär krävs mer än bara HTML - det krävs också CSS-stilmallar, och om du vill använda snygga widgetar kan du också behöva inkludera lite JavaScript på varje sida. Den exakta kombinationen av CSS och JavaScript som krävs för en viss sida beror på vilka widgetar som används på den sidan.

Det är här tillgångsdefinitioner kommer in i bilden. Django låter dig associera olika filer - som stilmallar och skript - med de formulär och widgetar som kräver dessa tillgångar. Om du till exempel vill använda en kalender för att rendera DateFields kan du definiera en anpassad Calendar-widget. Denna widget kan sedan associeras med den CSS och JavaScript som krävs för att rendera kalendern. När kalenderwidgeten används i ett formulär kan Django identifiera de CSS- och JavaScript-filer som krävs och tillhandahålla listan med filnamn i ett formulär som är lämpligt att inkludera på din webbsida.

Tillgångar och Django Admin

Programmet Django Admin definierar ett antal anpassade widgetar för kalendrar, filtrerade val och så vidare. Dessa widgetar definierar tillgångskrav och Django Admin använder de anpassade widgetarna i stället för Djangos standardinställningar. Admin-mallarna innehåller endast de filer som krävs för att rendera widgetarna på en viss sida.

Om du gillar widgetarna som Django Admin-applikationen använder, känn dig fri att använda dem i din egen applikation! De är alla lagrade i `django.contrib.admin.widgets`.

Vilken JavaScript-verktygslåda?

Det finns många JavaScript-verktygslådor och många av dem innehåller widgets (t.ex. kalenderwidgets) som kan användas för att förbättra din applikation. Django har medvetet undvikit att välsigna någon JavaScript-verktygssats. Varje verktygslåda har sina egna relativa styrkor och svagheter - använd den verktygslåda som passar dina krav. Django kan integreras med vilken JavaScript-verktygslåda som helst.

## Tillgångar som en statisk definition

Det enklaste sättet att definiera tillgångar är som en statisk definition. Med den här metoden är deklarationen en inre klass av typen `Media`. Egenskaperna för den inre klassen definierar kraven.

Här är ett exempel:

    from django import forms

    class CalendarWidget(forms.TextInput):
        class Media:
            css = {
                "all": ["pretty.css"],
            }
            js = ["animations.js", "actions.js"]

Denna kod definierar en `CalendarWidget`, som kommer att baseras på `TextInput`. Varje gång CalendarWidget används i ett formulär kommer formuläret att instrueras att inkludera CSS-filen `pretty.css` och JavaScript-filerna `animations.js` och `actions.js`.

Denna statiska definition omvandlas vid körning till en widgetegenskap med namnet `media`. Listan över tillgångar för en `CalendarWidget`-instans kan hämtas via den här egenskapen:

    >>> w = CalendarWidget()
    >>> print(w.media)
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>

Här är en lista över alla möjliga `Media`-alternativ. Det finns inga obligatoriska alternativ.

### `css`

En ordbok som beskriver de CSS-filer som krävs för olika typer av utdatamedia.

Värdena i ordlistan bör vara en tupel/lista med filnamn. Se avsnittet om sökvägar för information om hur du anger sökvägar till dessa filer.

Nycklarna i ordlistan är mediatyperna för utdata. Dessa är samma typer som accepteras av CSS-filer i mediedeklarationer: ’all’, ’aural’, ’braille’, ’embossed’, ’handheld’, ’print’, ’projection’, ’screen’, ’tty’ och ’tv’. Om du behöver ha olika stilmallar för olika medietyper ska du ange en lista med CSS-filer för varje utdatamedium. Följande exempel skulle ge två CSS-alternativ - ett för skärmen och ett för utskrift:

    class Media:
        css = {
            "screen": ["pretty.css"],
            "print": ["newspaper.css"],
        }

Om en grupp CSS-filer är lämpliga för flera olika typer av utdatamedier kan ordboksnyckeln vara en kommaseparerad lista över typerna av utdatamedier. I följande exempel kommer TV-apparater och projektorer att ha samma mediekrav:

    class Media:
        css = {
            "screen": ["pretty.css"],
            "tv,projector": ["lo_res.css"],
            "print": ["newspaper.css"],
        }

Om denna sista CSS-definition skulle renderas skulle den bli följande HTML:

    <link href="https://static.example.com/pretty.css" media="screen" rel="stylesheet">
    <link href="https://static.example.com/lo_res.css" media="tv,projector" rel="stylesheet">
    <link href="https://static.example.com/newspaper.css" media="print" rel="stylesheet">

#### `Stylesheet` objects

New in Django 6.1.

class Stylesheet(href, **attributes)

  Represents a stylesheet link. The `rel` attribute is set to `"stylesheet"`.

  The first parameter, `href`, is the string path to the stylesheet file. See the section on paths for details on how to specify paths to these files.

  The optional keyword arguments, `**attributes`, are additional HTML attributes set on the rendered `<link>` tag.

  Se Banor som objekt för användningsexempel.

### `js`

En tupel som beskriver de JavaScript-filer som krävs. Se avsnittet om sökvägar för information om hur du anger sökvägar till dessa filer.

#### `Script`-objekt

class Script(src, **attributes)

  Representerar en skriptfil.

  Den första parametern, `src`, är strängsökvägen till skriptfilen. Se avsnittet om sökvägar för mer information om hur du anger sökvägar till dessa filer.

  De valfria nyckelordsargumenten, `**attributes`, är HTML-attribut som ställs in på den återgivna `<script>`-taggen.

  Se Banor som objekt för användningsexempel.

### `förlänga`

En boolean som definierar arvsbeteendet för `Media`-deklarationer.

Som standard kommer alla objekt som använder en statisk `Media`-definition att ärva alla tillgångar som är associerade med den överordnade widgeten. Detta sker oavsett hur den överordnade widgeten definierar sina egna krav. Till exempel, om vi skulle utöka vår grundläggande kalenderwidget från exemplet ovan:

    >>> class FancyCalendarWidget(CalendarWidget):
    ...     class Media:
    ...         css = {
    ...             "all": ["fancy.css"],
    ...         }
    ...         js = ["whizbang.js"]
    ...

    >>> w = FancyCalendarWidget()
    >>> print(w.media)
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <link href="https://static.example.com/fancy.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>
    <script src="https://static.example.com/whizbang.js"></script>

FancyCalendar-widgeten ärver alla tillgångar från sin föräldrawidget. Om du inte vill att `Media` ska ärvas på detta sätt lägger du till en `extend=False`-deklaration i `Media`-deklarationen:

    >>> class FancyCalendarWidget(CalendarWidget):
    ...     class Media:
    ...         extend = False
    ...         css = {
    ...             "all": ["fancy.css"],
    ...         }
    ...         js = ["whizbang.js"]
    ...

    >>> w = FancyCalendarWidget()
    >>> print(w.media)
    <link href="https://static.example.com/fancy.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/whizbang.js"></script>

Om du vill ha ännu mer kontroll över arvet kan du definiera dina tillgångar med hjälp av en dynamisk egenskap. Dynamiska egenskaper ger dig fullständig kontroll över vilka filer som ärvs och vilka som inte ärvs.

## `Media` som en dynamisk egenskap

If you need to perform some more sophisticated manipulation of asset requirements, you can define the `media` property directly. This is done by defining a widget property that returns an instance of `forms.Media`. The constructor for `forms.Media` accepts `css` and `js` keyword arguments in the same format as that used in a static media definition.

Till exempel kan den statiska definitionen för vår Calendar Widget också definieras på ett dynamiskt sätt:

    class CalendarWidget(forms.TextInput):
        @property
        def media(self):
            return forms.Media(
                css={"all": ["pretty.css"]}, js=["animations.js", "actions.js"]
            )

Se avsnittet om Mediaobjekt för mer information om hur man konstruerar returvärden för dynamiska `media`-egenskaper.

## Vägar i tillgångsdefinitioner

### Banor som strängar

Strängsökvägar som används för att ange tillgångar kan vara antingen relativa eller absoluta. Om en sökväg börjar med `/`, `http://` eller `https://` kommer den att tolkas som en absolut sökväg och lämnas som den är. Alla andra sökvägar kommer att föregås av värdet på lämpligt prefix. Om appen `django.contrib.staticfiles` är installerad kommer den att användas för att servera tillgångar.

Oavsett om du använder `django.contrib.staticfiles` eller inte, krävs inställningarna `STATIC_URL` och `STATIC_ROOT` för att rendera en komplett webbsida.

För att hitta det lämpliga prefixet att använda kommer Django att kontrollera om inställningen `STATIC_URL` inte är `None` och automatiskt falla tillbaka till att använda `MEDIA_URL`. Till exempel, om `MEDIA_URL` för din webbplats var `'https://uploads.example.com/'` och `STATIC_URL` var `None`:

    >>> from django import forms
    >>> class CalendarWidget(forms.TextInput):
    ...     class Media:
    ...         css = {
    ...             "all": ["/css/pretty.css"],
    ...         }
    ...         js = ["animations.js", "https://othersite.com/actions.js"]
    ...

    >>> w = CalendarWidget()
    >>> print(w.media)
    <link href="/css/pretty.css" media="all" rel="stylesheet">
    <script src="https://uploads.example.com/animations.js"></script>
    <script src="https://othersite.com/actions.js"></script>

Men om `STATIC_URL` är `'https://static.example.com/'`:

    >>> w = CalendarWidget()
    >>> print(w.media)
    <link href="/css/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://othersite.com/actions.js"></script>

Eller om `staticfiles` konfigureras med hjälp av `ManifestStaticFilesStorage`:

    >>> w = CalendarWidget()
    >>> print(w.media)
    <link href="/css/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.27e20196a850.js"></script>
    <script src="https://othersite.com/actions.js"></script>

### Banor som objekt

Assets may also be object-based, using `Script` or `Stylesheet`. These allow you to pass custom HTML attributes:

    class Media:
        js = [
            Script(
                "https://cdn.example.com/something.min.js",
                **{
                    "crossorigin": "anonymous",
                    "async": True,
                },
            ),
        ]

Om denna Media-definition skulle renderas, skulle den bli följande HTML:

    <script src="https://cdn.example.com/something.min.js"
            crossorigin="anonymous"
            async>
    </script>

Similarly, a `Stylesheet` object can be used to add a stylesheet link with custom HTML attributes:

    class Media:
        css = {
            "all": [
                Stylesheet(
                    "https://cdn.example.com/print.css",
                    crossorigin="anonymous",
                    media="print",
                ),
            ]
        }

If this Media definition were to be rendered, it would become:

    <link href="https://cdn.example.com/print.css"
          crossorigin="anonymous"
          media="print"
          rel="stylesheet">

## `Media` objekt

class Media

  Represents a collection of media assets required by a widget or form.

När du frågar efter `media`-attributet för en widget eller ett formulär, returneras ett `forms.Media`-objekt. Som vi redan har sett är strängrepresentationen av ett `Media`-objekt den HTML som krävs för att inkludera de relevanta filerna i `<head>`-blocket på din HTML-sida.

Objekt av typen `Media` har dock några andra intressanta egenskaper.

### Delmängder av tillgångar

Om du bara vill ha filer av en viss typ kan du använda operatorn subscript för att filtrera ut ett medium av intresse. Till exempel:

    >>> w = CalendarWidget()
    >>> print(w.media)
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>

    >>> print(w.media["css"])
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">

När du använder subscript-operatorn returneras ett nytt `Media`-objekt - men ett som bara innehåller de medier som är av intresse.

### Kombinera `Media`-objekt

`Media`-objekt kan också läggas till tillsammans. När två `Media`-objekt läggs till innehåller det resulterande `Media`-objektet en sammanslagning av de tillgångar som anges av båda:

    >>> from django import forms
    >>> class CalendarWidget(forms.TextInput):
    ...     class Media:
    ...         css = {
    ...             "all": ["pretty.css"],
    ...         }
    ...         js = ["animations.js", "actions.js"]
    ...

    >>> class OtherWidget(forms.TextInput):
    ...     class Media:
    ...         js = ["whizbang.js"]
    ...

    >>> w1 = CalendarWidget()
    >>> w2 = OtherWidget()
    >>> print(w1.media + w2.media)
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>
    <script src="https://static.example.com/whizbang.js"></script>

### Tillgångarnas ordningsföljd

Den ordning i vilken tillgångar infogas i DOM är ofta viktig. Du kan t.ex. ha ett skript som är beroende av jQuery. Genom att kombinera `Media`-objekt försöker man därför bevara den relativa ordning i vilken tillgångarna definieras i varje `Media`-klass.

Till exempel:

    >>> from django import forms
    >>> class CalendarWidget(forms.TextInput):
    ...     class Media:
    ...         js = ["jQuery.js", "calendar.js", "noConflict.js"]
    ...
    >>> class TimeWidget(forms.TextInput):
    ...     class Media:
    ...         js = ["jQuery.js", "time.js", "noConflict.js"]
    ...
    >>> w1 = CalendarWidget()
    >>> w2 = TimeWidget()
    >>> print(w1.media + w2.media)
    <script src="https://static.example.com/jQuery.js"></script>
    <script src="https://static.example.com/calendar.js"></script>
    <script src="https://static.example.com/time.js"></script>
    <script src="https://static.example.com/noConflict.js"></script>

Om du kombinerar `Media`-objekt med tillgångar i en motstridig ordning resulterar det i en `MediaOrderConflictWarning`.

## `Media` på formulär

Widgets är inte de enda objekt som kan ha `media`-definitioner - även formulär kan definiera `media`. Reglerna för `media`-definitioner på formulär är desamma som för widgets: deklarationer kan vara statiska eller dynamiska; sökvägs- och arvsreglerna för dessa deklarationer är exakt desamma.

Oavsett om du definierar en `media`-deklaration har alla formulärobjekt en `media`-egenskap. Standardvärdet för den här egenskapen är resultatet av att lägga till `media`-definitionerna för alla widgetar som ingår i formuläret:

    >>> from django import forms
    >>> class ContactForm(forms.Form):
    ...     date = DateField(widget=CalendarWidget)
    ...     name = CharField(max_length=40, widget=OtherWidget)
    ...

    >>> f = ContactForm()
    >>> f.media
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>
    <script src="https://static.example.com/whizbang.js"></script>

Om du vill koppla ytterligare tillgångar till ett formulär, t.ex. CSS för formulärlayout, kan du lägga till en `Media`-deklaration i formuläret:

    >>> class ContactForm(forms.Form):
    ...     date = DateField(widget=CalendarWidget)
    ...     name = CharField(max_length=40, widget=OtherWidget)
    ...     class Media:
    ...         css = {
    ...             "all": ["layout.css"],
    ...         }
    ...

    >>> f = ContactForm()
    >>> f.media
    <link href="https://static.example.com/pretty.css" media="all" rel="stylesheet">
    <link href="https://static.example.com/layout.css" media="all" rel="stylesheet">
    <script src="https://static.example.com/animations.js"></script>
    <script src="https://static.example.com/actions.js"></script>
    <script src="https://static.example.com/whizbang.js"></script>