Representar un formulario web atractivo y fácil de usar requiere más que solo HTML; también requiere hojas de estilo CSS, y si desea utilizar widgets sofisticados “Web2.0”, es posible que también necesite incluir algo de JavaScript en cada página. La combinación exacta de CSS y JavaScript que se requiere para una página determinada dependerá de los widgets que se utilicen en esa página.

Aquí es donde entran las definiciones de activos. Django le permite asociar diferentes archivos, como hojas de estilo y scripts, con los formularios y widgets que requieren esos activos. Por ejemplo, si desea utilizar un calendario para representar DateFields, puede definir un widget de calendario personalizado. Este widget se puede asociar con CSS y JavaScript necesarios para representar el calendario. Cuando se utiliza el widget Calendario en un formulario, Django puede identificar los archivos CSS y JavaScript necesarios y proporcionar la lista de nombres de archivos en un formulario adecuado para su inclusión en su página web.

Administrador de activos y Django

La aplicación Django Admin define una serie de widgets personalizados para calendarios, selecciones filtradas, etc. Estos widgets definen los requisitos de los activos, y el administrador de Django usa los widgets personalizados en lugar de los valores predeterminados de Django. Las plantillas de administrador solo incluirán los archivos necesarios para representar los widgets en una página determinada.

Si le gustan los widgets que usa la aplicación Django Admin, ¡no dude en usarlos en su propia aplicación! Están todos almacenados en django.contrib.admin.widgets.

¿Qué kit de herramientas de JavaScript?

Existen muchos kits de herramientas de JavaScript, y muchos de ellos incluyen widgets (como widgets de calendario) que se pueden utilizar para mejorar su aplicación. Django ha evitado deliberadamente bendecir cualquier kit de herramientas de JavaScript. Cada conjunto de herramientas tiene sus propias fortalezas y debilidades relativas; utilice el conjunto de herramientas que se adapte a sus necesidades. Django puede integrarse con cualquier kit de herramientas de JavaScript.

Activos como definición estática

La forma más sencilla de definir activos es mediante una definición estática. Usando este método, la declaración es un interno Media clase. Las propiedades de la clase interna definen los requisitos.

He aquí un ejemplo:

from django import forms

classCalendarWidget(forms.TextInput):classMedia:
        css ='all':('pretty.css',)
        js =('animations.js','actions.js')

Este código define un CalendarWidget, que se basará en TextInput. Cada vez que se utiliza CalendarWidget en un formulario, ese formulario se dirigirá para incluir el archivo CSS pretty.cssy los archivos JavaScript animations.js y actions.js.

Esta definición estática se convierte en tiempo de ejecución en una propiedad de widget denominada media. La lista de activos de un CalendarWidget instancia se puede recuperar a través de esta propiedad:

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

Aquí hay una lista de todos los posibles Media opciones. No hay opciones obligatorias.

css

Un diccionario que describe los archivos CSS necesarios para varias formas de medios de salida.

Los valores del diccionario deben ser una tupla / lista de nombres de archivos. Ver la sección de caminos para obtener detalles sobre cómo especificar rutas a estos archivos.

Las claves del diccionario son los tipos de medios de salida. Estos son los mismos tipos aceptados por los archivos CSS en las declaraciones de medios: ‘todos’, ‘aural’, ‘braille’, ‘en relieve’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ y ‘ televisor’. Si necesita tener diferentes hojas de estilo para diferentes tipos de medios, proporcione una lista de archivos CSS para cada medio de salida. El siguiente ejemplo proporcionaría dos opciones de CSS: una para la pantalla y otra para imprimir:

classMedia:
    css ='screen':('pretty.css',),'print':('newspaper.css',)

Si un grupo de archivos CSS es apropiado para varios tipos de medios de salida, la clave del diccionario puede ser una lista separada por comas de los tipos de medios de salida. En el siguiente ejemplo, los televisores y proyectores tendrán los mismos requisitos de medios:

classMedia:
    css ='screen':('pretty.css',),'tv,projector':('lo_res.css',),'print':('newspaper.css',)

Si se renderizara esta última definición de CSS, se convertiría en el siguiente HTML:

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

js

Una tupla que describe los archivos JavaScript necesarios. Ver la sección de caminos para obtener detalles sobre cómo especificar rutas a estos archivos.

extend

Un comportamiento de herencia de definición booleana para Media declaraciones.

De forma predeterminada, cualquier objeto que utilice una Media La definición heredará todos los activos asociados con el widget principal. Esto ocurre independientemente de cómo el padre defina sus propios requisitos. Por ejemplo, si tuviéramos que extender nuestro widget de Calendario básico del ejemplo anterior:

>>>classFancyCalendarWidget(CalendarWidget):...classMedia:...         css =...'all':('fancy.css',)......         js =('whizbang.js',)>>> w = FancyCalendarWidget()>>>print(w.media)<link href="http://static.example.com/pretty.css"type="text/css" media="all" rel="stylesheet"><link href="http://static.example.com/fancy.css"type="text/css" media="all" rel="stylesheet"><script src="http://static.example.com/animations.js"></script><script src="http://static.example.com/actions.js"></script><script src="http://static.example.com/whizbang.js"></script>

El widget FancyCalendar hereda todos los activos de su widget principal. Si no quieres Media para ser heredado de esta manera, agregue un extend=False declaración al Media declaración:

>>>classFancyCalendarWidget(CalendarWidget):...classMedia:...         extend =False...         css =...'all':('fancy.css',)......         js =('whizbang.js',)>>> w = FancyCalendarWidget()>>>print(w.media)<link href="http://static.example.com/fancy.css"type="text/css" media="all" rel="stylesheet"><script src="http://static.example.com/whizbang.js"></script>

Si necesita aún más control sobre la herencia, defina sus activos usando un propiedad dinámica. Las propiedades dinámicas le brindan un control completo sobre qué archivos se heredan y cuáles no.

Media como una propiedad dinámica

Si necesita realizar una manipulación más sofisticada de los requisitos de activos, puede definir la media propiedad directamente. Esto se hace definiendo una propiedad de widget que devuelve una instancia de forms.Media. El constructor de forms.Media acepta css y js argumentos de palabras clave en el mismo formato que el utilizado en una definición de medio estático.

Por ejemplo, la definición estática de nuestro widget de calendario también podría definirse de forma dinámica:

classCalendarWidget(forms.TextInput):@propertydefmedia(self):return forms.Media(css='all':('pretty.css',),
                           js=('animations.js','actions.js'))

Consulte la sección sobre objetos de medios para obtener más detalles sobre cómo construir valores de retorno para dinámicas media propiedades.

Rutas en las definiciones de activos

Las rutas utilizadas para especificar activos pueden ser relativas o absolutas. Si un camino comienza con /, http:// o https://, se interpretará como una ruta absoluta y se dejará como está. Todas las demás rutas se antepondrán con el valor del prefijo apropiado. Si el django.contrib.staticfiles La aplicación está instalada, se utilizará para publicar activos.

Ya sea que use o no django.contrib.staticfiles, los STATIC_URL y STATIC_ROOT Se requieren configuraciones para representar una página web completa.

Para encontrar el prefijo apropiado para usar, Django verificará si el STATIC_URL el ajuste no es None y volver a usar automáticamente MEDIA_URL. Por ejemplo, si el MEDIA_URL porque tu sitio era 'http://uploads.example.com/' y STATIC_URL era None:

>>>from django import forms
>>>classCalendarWidget(forms.TextInput):...classMedia:...         css =...'all':('/css/pretty.css',),......         js =('animations.js','http://othersite.com/actions.js')>>> w = CalendarWidget()>>>print(w.media)<link href="/css/pretty.css"type="text/css" media="all" rel="stylesheet"><script src="http://uploads.example.com/animations.js"></script><script src="http://othersite.com/actions.js"></script>

Pero si STATIC_URL es 'http://static.example.com/':

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

O si staticfiles se configura usando el ManifestStaticFilesStorage:

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

Media objetos

Cuando interrogas al media atributo de un widget o formulario, el valor que se devuelve es un forms.Media objeto. Como ya hemos visto, la representación en cadena de un Media objeto es el HTML requerido para incluir los archivos relevantes en el bloque de su página HTML.

Sin embargo, Media los objetos tienen otras propiedades interesantes.

Subconjuntos de activos

Si solo desea archivos de un tipo en particular, puede usar el operador de subíndice para filtrar un medio de interés. Por ejemplo:

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

Cuando usa el operador de subíndice, el valor que se devuelve es un nuevo Media objeto, pero que solo contiene los medios de interés.

Combinatorio Media objetos

Media los objetos también se pueden sumar. Cuando dos Media se añaden objetos, el resultado Media El objeto contiene la unión de los activos especificados por ambos:

>>>from django import forms
>>>classCalendarWidget(forms.TextInput):...classMedia:...         css =...'all':('pretty.css',)......         js =('animations.js','actions.js')>>>classOtherWidget(forms.TextInput):...classMedia:...         js =('whizbang.js',)>>> w1 = CalendarWidget()>>> w2 = OtherWidget()>>>print(w1.media + w2.media)<link href="http://static.example.com/pretty.css"type="text/css" media="all" rel="stylesheet"><script src="http://static.example.com/animations.js"></script><script src="http://static.example.com/actions.js"></script><script src="http://static.example.com/whizbang.js"></script>

Orden de activos

El orden en el que se insertan los activos en el DOM suele ser importante. Por ejemplo, puede tener un script que dependa de jQuery. Por lo tanto, combinando Media objetos intenta preservar el orden relativo en el que se definen los activos en cada Media clase.

Por ejemplo:

>>>from django import forms
>>>classCalendarWidget(forms.TextInput):...classMedia:...         js =('jQuery.js','calendar.js','noConflict.js')>>>classTimeWidget(forms.TextInput):...classMedia:...         js =('jQuery.js','time.js','noConflict.js')>>> w1 = CalendarWidget()>>> w2 = TimeWidget()>>>print(w1.media + w2.media)<script src="http://static.example.com/jQuery.js"></script><script src="http://static.example.com/calendar.js"></script><script src="http://static.example.com/time.js"></script><script src="http://static.example.com/noConflict.js"></script>

Combinatorio Media objetos con activos en un orden conflictivo da como resultado una MediaOrderConflictWarning.

Media en formularios

Los widgets no son los únicos objetos que pueden tener media definiciones – las formas también pueden definir media. Las reglas para media las definiciones de los formularios son las mismas que las reglas de los widgets: las declaraciones pueden ser estáticas o dinámicas; Las reglas de ruta y herencia para esas declaraciones son exactamente las mismas.

Independientemente de si define un media declaración, todos Los objetos de forma tienen un media propiedad. El valor predeterminado para esta propiedad es el resultado de agregar el media definiciones para todos los widgets que forman parte del formulario:

>>>from django import forms
>>>classContactForm(forms.Form):...     date = DateField(widget=CalendarWidget)...     name = CharField(max_length=40, widget=OtherWidget)>>> f = ContactForm()>>> f.media
<link href="http://static.example.com/pretty.css"type="text/css" media="all" rel="stylesheet"><script src="http://static.example.com/animations.js"></script><script src="http://static.example.com/actions.js"></script><script src="http://static.example.com/whizbang.js"></script>

Si desea asociar activos adicionales con un formulario, por ejemplo, CSS para el diseño del formulario, agregue un Media declaración al formulario:

>>>classContactForm(forms.Form):...     date = DateField(widget=CalendarWidget)...     name = CharField(max_length=40, widget=OtherWidget)......classMedia:...         css =...'all':('layout.css',)...>>> f = ContactForm()>>> f.media
<link href="http://static.example.com/pretty.css"type="text/css" media="all" rel="stylesheet"><link href="http://static.example.com/layout.css"type="text/css" media="all" rel="stylesheet"><script src="http://static.example.com/animations.js"></script><script src="http://static.example.com/actions.js"></script><script src="http://static.example.com/whizbang.js"></script>