pdfcrowd.com open in browser PRO version Are you a developer?
Try out the HTML to PDF API
Escribiendo tu primer parche para Django Interesado en dar a la comunidad un poco? Tal vez encontraste un fallo en Django que te gustara corregir, o tal vez hay una pequea caracterstica que te gustara aadir. Las contribuciones son en s mismo la mejor manera de abordar y ver nuestras propias preocupaciones retribuidas a Django en s. Esto puede parecer un poco intimidante al principio, pero en realidad es bastante simple. Esta gua te guiara te llevara a travs de todo el proceso, por lo que puedes aprender con el ejemplo. Para este tutorial, esperamos que tengas por lo menos un conocimiento bsico de la forma en que funciona Django. Esto quiere decir que deves ir poco a poco aprendiendo de una forma cmoda sobre los tutoriales existentes: Tu primera aplicacion en Django. Adems, tambien necesitas poseer una buena comprensin de Python o al menos entender la forma en que funciona. Pero si no la tienes no te preocupes puedes leerDive Into Python que es un fantstico (y gratis) libro en lnea para comenzar a programar en Python. Aquellos de ustedes que no estn familiarizados con los sistemas de control de versiones tipo Trac, git 30 DEC Introduccin Qu esperamos de este tutorial? Plantilla Dynamic Views. Con la tecnologa de Blogger. Django Portada Tutoriales Classic Django, Todo lo que quieres saber y algo m buscar pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API encontrarn que este tutorial y sus vnculos incluyen informacin suficiente para empezar. Sin embargo, es probable que quieras leer un poco ms acerca de estas herramientas diferentes entre si, si es que vas a contribuir a Django con regularidad. En su mayor parte, este tutorial trata de explicar tanto como sea posible, de modo que pueda ser de utilidad en audiencias ms amplias. Dnde obtener ayuda: Si ests teniendo problemas a travs de este tutorial, por favor envia un mensaje a django-developers o a travs del chat #django-dev on irc.freenode.net para chatear con otros usuarios de Django que podrn resolver tus dudas y ayudarte. A lo largo de este tutorial cubriremos la forma de contribuir con un parche para Django por primera vez. Al final de este tutorial, debes tener un conocimiento bsico tanto de la las herramientas y los procesos involucrados en el proceso. En concreto, vamos a estar cubriendo los siguientes temas: La instalacin de Git. Cmo descargar una copia de desarrollo de Django. Ejecutar un paquete de pruebas en Django. Redactar una prueba para su revisin. Escribir el cdigo para una revisin. Testear un parche. Generacin de un archivo de revisin de cambios. Dnde buscar ms informacin?. Una vez que hayas terminado con el tutorial, puedes buscar a travs del resto de la documentacion:Django's documentation on contributing. Contiene gran cantidad de informacin y es Qu cubre este tutorial? pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API una lectura obligada para cualquier persona que quiera convertirse en un colaborador habitual de Django. Si tienes preguntas, es probablemente que alli estn las respuestas. Para este tutorial, necesitamos instalar Git para descargar la versin actual de desarrollo de Django y generar archivos de revisin para posteriormente hacer los cambios. Para comprobar si tienes o no instalado Git, introduce el siguiente comando en la terminal asi: git. Si recibes un mensajes diciendo que el comando no puede ser encontrado, tendrs primero que descargarlo e instalarlo, consulta la seccin Gits download page para mas informacin. Si no ests familiarizado con Git, siempre puedes encontrar ms informacin sobre su comandos (una vez instalado) escribiendo git help en la lnea de comandos. El primer paso para contribuir a Django es obtener una copia del cdigo fuente. Desde la lnea de comandos, utiliza el comando cd para navegar hasta el directorio donde quieras almacenar una copia local de Django. Descarga el cdigo fuente desde el repositorio de Django con el siguiente comando: git clone https://github.com/django/django.git Note Para los usuarios que deseen usar virtualenv, puede utilizar: pip install -e /path/to/your/local/clone/django/ Para asi enlazar el directorio clonado con el entorno virtual. Esta es un gran opcin, aislar Instalar Git Obtener una copia de la versin de desarrollo de Django pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API la copia de desarrollo de Django del resto de su sistema y evitar posibles conflictos entre paquetes. Para este tutorial, vamos a utilizar el ticket #17549 como caso de estudio, por lo que vamos a retroceder en la versin de git y en la historia de Django antes de de aplicar el ticket para el parche. Esto nos permitir pasar por todos los pasos necesarios para escribir ese parche desde cero, incluyendo la ejecucin de un conjunto de pruebas para Django. Ten en cuenta que, vamos a estar utilizando una versin del tronco de Django antigua para los efectos de este tutorial, siempre se debe utilizar la revisin de desarrollo actual de Django cuando se trabaja en un parche de un ticket! Note El parche para esta entrada fue escrita por Ulrich Petri, y se aplic a Django como commit ac2052ebc84c45709ab5f0f25e685bf656ce79bc. Por lo tanto, vamos a aprovechar la revisin de Django justo antes de aplicar el commit 39f5bc7fc3a4bb43ed8a1358b17fe0521a1a63ac. Navega a el directorio raz de Django (que es el que contiene django, docs, tests, AUTHORS, etc.). A continuacin, puedes checar la mayor parte de las revisiones de Django que vamos a utilizar a continuacin en el tutorial: git checkout 39f5bc7fc3a4bb43ed8a1358b17fe0521a1a63ac Al contribuir a Django es muy importante que los cambios en el cdigo no introduzcan mas errores en otras reas de Django. Una forma de comprobar que Django trabaja despus de realizar los cambios Retornar a una revisin previa de Django Ejecutando un conjunto de pruebas Django por primera vez pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API es mediante la ejecucin de una suite de pruebas. Si todas las pruebas pasan, entonces se puede estar razonablemente seguro de que los cambios no han roto completamente a Django. Si nunca has ejecutado una suite de pruebas de Django antes, es una buena idea ejecutarla una vez antes slo para familiarizarse con la forma en que se comporta y con la salida que aparece. Podemos ejecutar el conjunto de pruebas, simplemente situndonos con el comandocd `` en el directorio ``tests/, si ests usando GNU/Linux, Mac OS X o algn otro sabor de Unix, puedes ejecutar: PYTHONPATH=.. python runtests.py --settings=test_sqlite Si ests en Windows, lo anterior debera funcionar siempre y cuando ests utilizando Git Bash que es proporcionado por la instalacin Git por defecto. GitHub tiene un tutorial muy bueno en nice tutorial. Note Si utilizas virtualenv, puede omitir PYTHONPATH=.. cuando ejecutes las pruebas. Esto indica a Python que busque a Django en el directorio padre de pruebas tests. virtualenv pone su copia de Django en el PYTHONPATH automticamente. Ahora sintate y reljate un poco. Todo el conjunto de pruebas de Django cuenta con ms de 4800 diferentes pruebas, por lo que puede tardar entre 5 y 15 minutos en ejecutarse, en funcin de la velocidad de tu ordenador. Mientras la suite de pruebas de Django se est ejecutando, vers una secuencia de caracteres que representa el estado de cada prueba como es ejecutado. E indica que un error fue lanzado durante una prueba y F indica que una de las afirmaciones de prueba ha fallado. Ambos se consideran fallos de prueba. Mientras tanto, x y s indican fallas esperadas y las pruebas omitidas, respectivamente. Los puntos indican que se pasaron las pruebas. Las pruebas que suelen ser omitidos son debido a que faltan bibliotecas externas necesarias para ejecutar la prueba, puedes ver running-unit-tests-dependencies para obtener una lista de las pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API dependencias y asegurarte de instalar cualquiera de las bibliotecas faltantes para las pruebas relacionadas con los cambios que se est haciendo (que no necesitaremos ninguna para este tutorial). Una vez que se completan las pruebas, recibiremos un mensaje informndonos si el conjunto de pruebas aprob o no. Dado que an no se ha realizado ningn cambio a el cdigo de Django, la prueba de toda la suite debera aprobar. Si obtienes fallas o errores asegurarte de que has seguido todos los pasos anteriores correctamente. Puedes ver running-unit-tests para ms informacin. Ten en cuenta que el tronco (trunk) de Django puede no ser estable siempre. Cuando desarrollamos en el tronco, podemos comprobar en Djangos continuous integration builds y determinar si los errores son especficos de la mquina en que estamos trabajando o si tambin estn presenten en las versiones oficiales de Django. Si das clic en una vista en particular, se puede ver la Matriz de configuracin, que muestra las fallas desglosados por el tipo de versin de Python y la base de datos back-end usada. Note Para este tutorial y ticket en que estamos trabajando, las pruebas son usando como base de datos SQLite, sin embargo, es posible (y, a veces es necesario) para run the tests using a different database usar diferentes bases de datos. En la mayora de los casos, para ser aceptado un parche en Django este tiene que incluir pruebas. Para parches de correccin de errores, esto significa escribir una prueba de regresin para asegurar que el bug no vuelva a ser reintroducido en Django mas adelante. Una prueba de regresin debera ser escrita de tal manera que produzca un error, mientras que todava existe el error y pasar una vez que el error se halla corregido. Para los parches con nuevas caractersticas, debern ser incluidas pruebas que garanticen que las nuevas caractersticas funcionan correctamente. Ellos tambin deberan fallar cuando la nueva caracterstica no est presente, y luego pase una vez que se halla aplicado el parche. Escribir algunas pruebas para el ticket pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Una buena manera de hacer esto es escribir las nuevas pruebas en primer lugar, antes de hacer cualquier cambio en el cdigo. Este estilo de desarrollo es llamado test-driven development y se puede aplicar tanto en proyectos completos y parches individuales. Despus de escribir las pruebas, a continuacin, las ejecutamos para asegurarnos que de no se han hecho cambios (ya que no se han fijado ese error o aadido todava esa caracterstica). Si las nuevas pruebas no fallan, tendrs que arreglarlas para que lo hagan. Despus de todo, un anlisis de regresin que pasa sin importar si un error est presente no es muy til en la prevencin de estos errores si se repita en el futuro. Ahora, para nuestro ejemplo prctico. El Ticket #17549 describe la suma de la siguiente, pequea caracterstica: Es til para un campo URLField para darle una forma de abrir la direccin URL, de lo contra rio puede ser que tambin se utilice un CharField. Con el fin de resolver este ticket, vamos a aadir un mtodo render para el widget AdminURLFieldWidgetcon el fin de mostrar un vnculo al hacer clic encima de la entrada del widget. Antes de realizar estos cambios, sin embargo, vamos a escribir un par de ensayos para comprobar que nuestras funciones de modificacin funcionan correctamente y que continuara funcionando correctamente en el futuro. Navega hasta el directorio de Django tests/regressiontests/admin_widgets/ y abre el archivo test.py. Agrega el siguiente cdigo justo en la lnea 269 antes de la clase AdminFileWidgetTest class AdminURLWidgetTest(DjangoTestCase): def test_render(self): w = widgets.AdminURLFieldWidget() self.assertHTMLEqual( conditional_escape(w.render('test', '')), '<input class="vURLField" name="test" type="text" />' Escribiendo algunas pruebas para el ticket #17549 pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API ) self.assertHTMLEqual( conditional_escape(w.render('test', 'http://example.com')), '<p class="url">Currently:<a href="http://example.com">http://example.com</a><b r />Change:<input class="vURLField" name="test" type="text" value="http://example.com" /></ p>' ) def test_render_idn(self): w = widgets.AdminURLFieldWidget() self.assertHTMLEqual( conditional_escape(w.render('test', 'http://example-.com')), '<p class="url">Currently:<a href="http://xn--example--7za4pnc.com">http://exam ple-.com</a><br />Change:<input class="vURLField" name="test" type="text" value="http:// example-.com" /></p>' ) def test_render_quoting(self): w = widgets.AdminURLFieldWidget() self.assertHTMLEqual( conditional_escape(w.render('test', 'http://example.com/<sometag>some text</som etag>')), '<p class="url">Currently:<a href="http://example.com/%3Csometag%3Esome%20text% 3C/sometag%3E">http://example.com/<sometag>some text</sometag></a><br />Change: <input class="vURLField" name="test" type="text" value="http://example.com/<sometag>some te xt</sometag>" /></p>' ) self.assertHTMLEqual( conditional_escape(w.render('test', 'http://example-.com/<sometag>some text< /sometag>')), '<p class="url">Currently:<a href="http://xn--example--7za4pnc.com/%3Csometag%3 Esome%20text%3C/sometag%3E">http://example-.com/<sometag>some text</sometag> </a><br />Change:<input class="vURLField" name="test" type="text" value="http://example- .com/<sometag>some text</sometag>" /></p>' ) Las nuevas pruebas verifican que el mtodo render vaya agregando los nuevos trabajos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API correctamente en algunas situaciones diferentes. Pero esto parece una prueba un poco difcil... Si nunca has tenido que lidiar con las pruebas antes, pueden parecer un poco duro escribir una prueba o test a primera vista. Afortunadamente, la pruebas son un tema muy recurrente en programacin de ordenadores, as que hay mucha informacin por ah: Para escribir pruebas para Django, como primer vistazo se puede encontrar en la misma documentacin en Testing Django applications. Inmersin en Python (un libro gratis en lnea para desarrolladores principiantes de Python) incluye un gran introduccin a pruebas unitarias: introduction to Unit Testing. Despus de leer esto, si quieres algo un poco ms sustancioso puedes hundirle siempre el diente a la documentacion de Python, en la seccin de: Python unittest documentation. Recuerda que no se han realizado modificaciones en AdminURLFieldWidget todava, as que nuestras pruebas van a fallar. Vamos a correr todo el conjunto de pruebas en la carpeta model_forms_regress para asegurarnos de que es lo que realmente sucede. Desde la lnea de comandos, nos cambiamos de directorio con cd ala carpeta tests/ y ejecutamos PYTHONPATH=.. python runtests.py --settings=test_sqlite admin_widgets Si las pruebas se han ejecutado correctamente, deberas ver tres fallos correspondientes a cada uno de los mtodos de ensayo que hemos aadido. Si todas las pruebas pasaron, entonces tambin querrs asegurarte de que se han agregado las nuevas pruebas que se muestran arriba en la clase y carpeta correspondiente. Ejecuando la nueva prueba pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API A continuacin vamos a aadir la funcionalidad descrita en ticket #17549 a Django. Navegamos haste el directorio django/django/contrib/admin/ y abrimos el archivo widgets.py. Buscamos la clase AdminURLFieldWidget en la lnea 302 y aadimos el siguiente mtodo render despus de el existente mtodo __init__ def render(self, name, value, attrs=None): html = super(AdminURLFieldWidget, self).render(name, value, attrs) if value: value = force_text(self._format_value(value)) final_attrs = {'href': mark_safe(smart_urlquote(value))} html = format_html( '<p class="url">{0} <a {1}>{2}</a><br />{3} {4}</p>', _('Currently:'), flatatt(final_attrs), value, _('Change:'), html ) return html Una vez que hayas terminado las modificacin de Django, es necesario asegurarse de que las pruebas que escribimos antes pasen correctamente, para que podamos ver si el cdigo que escribimos arriba est trabajando correctamente. Para ejecutar las pruebas nos cambiamos ala carpeta admin_widgets con el comando cd nos situamos en el directorio tests/ y ejecutamos la prueba PYTHONPATH=.. python runtests.py --settings=test_sqlite admin_widgets Oops, menos mal que escribimos esta prueba! An tenemos 3 fallos con la excepcin siguiente NameError: global name 'smart_urlquote' is not defined Escribir el cdigo para su ticket Escribir el cdigo para el ticket #17549 Verificando que la prueba pasa ahora pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Nos hemos olvidado de importar el mtodo smart_urlquote. Seguimos adelante y aadimos el mtodo de importacin smart_urlquote al final de la lnea 13 del archivo django/contrib/admin/widgets.py de la siguiente forma: from django.utils.html import escape, format_html, format_html_join, smart_urlquote Volvemos a ejecutar las pruebas y debera pasarlas todas. Si no lo hace, devemos asegurarnos de que hemos modificado correctamente la clase AdminURLFieldWidget como se muestra arriba y que hemos copiado las nuevas pruebas correctamente. Una vez que hayas verificado que el parche y la prueba est funcionando correctamente, es una buena idea ejecutar toda la suite de pruebas Django slo para comprobar que el cambio no ha introducido ningn otro bug en otras reas de Django. Aunque paso con xito todo el conjunto de pruebas esto no garantiza que el cdigo esta libre de errores, lo que hace es ayudar a identificar muchos errores y regresiones que de otro modo podran pasar desapercibidas. Para ejecutar la totalidad del conjunto de pruebas de Django nos cambiamos al directorio tests/ con cd y ejecutamos PYTHONPATH=.. python runtests.py --settings=test_sqlite Siempre y cuando no se vea ningn fallo, esto esta bien por el momento. Ten en cuenta que esta revisin Tambin hizo un pequeo cambio al dar formato al widget small CSS change . Puedes hacer el cambiar si lo deseas, pero lo vamos a omitir por el momento, en aras de la brevedad. Esta es una nueva caracterstica, por lo que debe ser documentada. Agregamos lo siguiente en la lnea 925 de django/docs/ref/models/fields.txt debajo de la actual documentacin para URLField: Ejecutando el paquete de pruebas Django por segunda vez Escribir Documentacin pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API .. versionadded:: 1.5 El valor actual del campo se mostrar como un enlace al dar clic encima de la entrada del widget. Para obtener ms informacin sobre escribir documentacin, incluyendo una explicacin acerca deversionadded , puedes consultar /internals/contributing/writing-documentation. Esta pgina incluye tambin una explicacin acerca de cmo construir una copia de la documentacin a nivel local, para poder tener una vista previa del HTML que se generar. Ahora es el momento para generar un archivo de revisin que se pueden cargar en Trac o pueda ser aplicado a otra copia de Django. Para echar un vistazo a los contenidos de el parche, ejecutamos el el siguiente comando git diff Este comando mostrar las diferencias entre la copia actual de Django (con los cambios) y la revisin que checamos inicialmente a principios de este tutorial. Una vez que hayas terminado de ver el parche, pulse la tecla q para salir de nuevo a la lnea de comandos. Si el contenido del parche es correcto, puedes ejecutar el siguiente comando para guardar el archivo de parche en el directorio de trabajo actual git diff> 17549.diff Ahora debes tener un archivo en el directorio raz de Django llamado 17549.diff. Este parche contiene todos los cambios que haz hecho y debe verse asi: diff --git a/django/contrib/admin/widgets.py b/django/contrib/admin/widgets.py index 1e0bc2d..9e43a10 100644 --- a/django/contrib/admin/widgets.py Generacin del parche para los cambios pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API +++ b/django/contrib/admin/widgets.py @@ -10,7 +10,7 @@ from django.contrib.admin.templatetags.admin_static import static from django.core.urlresolvers import reverse from django.forms.widgets import RadioFieldRenderer from django.forms.util import flatatt -from django.utils.html import escape, format_html, format_html_join +from django.utils.html import escape, format_html, format_html_join, smart_urlquote from django.utils.text import Truncator from django.utils.translation import ugettext as _ from django.utils.safestring import mark_safe @@ -306,6 +306,18 @@ class AdminURLFieldWidget(forms.TextInput): final_attrs.update(attrs) super(AdminURLFieldWidget, self).__init__(attrs=final_attrs) + def render(self, name, value, attrs=None): + html = super(AdminURLFieldWidget, self).render(name, value, attrs) + if value: + value = force_text(self._format_value(value)) + final_attrs = {'href': mark_safe(smart_urlquote(value))} + html = format_html( + '<p class="url">{0} <a {1}>{2}</a><br />{3} {4}</p>', + _('Currently:'), flatatt(final_attrs), value, + _('Change:'), html + ) + return html + class AdminIntegerFieldWidget(forms.TextInput): class_name = 'vIntegerField' diff --git a/docs/ref/models/fields.txt b/docs/ref/models/fields.txt index 809d56e..d44f85f 100644 --- a/docs/ref/models/fields.txt +++ b/docs/ref/models/fields.txt @@ -922,6 +922,10 @@ Like all :class:`CharField` subclasses, :class:`URLField` takes the op tional :attr:`~CharField.max_length`argument. If you don't specify :attr:`~CharField.max_length`, a default of 200 is used. pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API +.. versionadded:: 1.5 + +The current value of the field will be displayed as a clickable link above the +input widget. Relationship fields =================== diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_wid gets/tests.py index 4b11543..94acc6d 100644 --- a/tests/regressiontests/admin_widgets/tests.py +++ b/tests/regressiontests/admin_widgets/tests.py @@ -265,6 +265,35 @@ class AdminSplitDateTimeWidgetTest(DjangoTestCase): '<p class="datetime">Datum: <input value="01.12.2007" type="text" clas s="vDateField" name="test_0" size="10" /><br />Zeit: <input value="09:30:00" type="text" cl ass="vTimeField" name="test_1" size="8" /></p>', ) +class AdminURLWidgetTest(DjangoTestCase): + def test_render(self): + w = widgets.AdminURLFieldWidget() + self.assertHTMLEqual( + conditional_escape(w.render('test', '')), + '<input class="vURLField" name="test" type="text" />' + ) + self.assertHTMLEqual( + conditional_escape(w.render('test', 'http://example.com')), + '<p class="url">Currently:<a href="http://example.com">http://example.com</a>< br />Change:<input class="vURLField" name="test" type="text" value="http://example.com" />< /p>' + ) + + def test_render_idn(self): + w = widgets.AdminURLFieldWidget() + self.assertHTMLEqual( + conditional_escape(w.render('test', 'http://example-.com')), + '<p class="url">Currently:<a href="http://xn--example--7za4pnc.com">http://exa pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API mple-.com</a><br />Change:<input class="vURLField" name="test" type="text" value="http:/ /example-.com" /></p>' + ) + + def test_render_quoting(self): + w = widgets.AdminURLFieldWidget() + self.assertHTMLEqual( + conditional_escape(w.render('test', 'http://example.com/<sometag>some text</so metag>')), + '<p class="url">Currently:<a href="http://example.com/%3Csometag%3Esome%20text %3C/sometag%3E">http://example.com/<sometag>some text</sometag></a><br />Change :<input class="vURLField" name="test" type="text" value="http://example.com/<sometag>some t ext</sometag>" /></p>' + ) + self.assertHTMLEqual( + conditional_escape(w.render('test', 'http://example-.com/<sometag>some text </sometag>')), + '<p class="url">Currently:<a href="http://xn--example--7za4pnc.com/%3Csometag% 3Esome%20text%3C/sometag%3E">http://example-.com/<sometag>some text</sometag> ;</a><br />Change:<input class="vURLField" name="test" type="text" value="http://example- .com/<sometag>some text</sometag>" /></p>' + ) class AdminFileWidgetTest(DjangoTestCase): def test_render(self): Felicidades, has generado tu primer parche Django! Ahora que haz aprendido com hacerlo, puedes usar esas habilidades para ayudar a mejorar la base de cdigo de Django. La generacin de parches y tickets para adjuntarlos a Trac es til, sin embargo, ya que estamos usando git - (Recientemente adoptado como versin de control) git oriented workflow es recomendado. Ya que nunca hemos subido (committed) nuestros cambios a nivel local, necesitamos hecer lo siguiente para obtener una nueva rama de git como punto de partida Entonces, qu debo hacer ahora? pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API git reset - cabeza dura git checkout master Antes de que puedas escribir parches para Django, hay un poco ms de informacin sobre las contribuciones que probablemente deberas echar un vistazo: Debes asegurarse de leer la documentacin de Django enclaiming tickets and submitting patches. Cubre etiquetas en Trac, cmo reclamar tickets para s mismo, como se espera el estilo de codificacin para parches, y muchos detalles importantes. Si eres por primera vez un contribuyente tambin puedes leerdocumentation for first time contributors. Tiene un montn de buenos consejos para aquellos de nosotros que son nuevos para ayudar con Django. Despus de todo esto, si todava tienes ganas de obtener ms informacin acerca de la forma de contribuir a Django, siempre puedes navegar por el resto deDjango's documentation on contributing. Contiene un montn de informacin til y debera ser tu primera fuente de informacin para responder a cualquier pregunta que te pueda surgir. Una vez que hemos revisado alguna de esta informacin, podemos estar listos para salir y encontrar un ticket por nuestra cuenta y para escribir un parche para este. Presta especial atencin a las entradas marcadas con el criterio easy pickings. Estos tickets son a menudo mucho mas simples en la naturaleza y son ideales para los contribuyentes primerizos. Una vez que ests familiarizado con la forma de contribuir a Django, puedes pasar a escribir parches para entradas ms difciles y complicadas. Si lo que desea es empezar ya (y nadie te culpara de ello!), Prueba echar un vistazo a la lista de easy tickets that need patches (tickets que necesitan parches) y a la de easy tickets that have patches which need improvement. Si est familiarizado con la escritura de pruebas, tambin puede consultar la lista deeasy Ms informacin para los nuevos contribuyentes Encontrar el primer Ticket pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API tickets that need tests. Slo recuerda seguir las directrices sobre entradas que se mencionan en el enlace a la documentacin de Django en claiming tickets and submitting patches. Despus de que un ticket tiene un parche, tiene que ser revisado por un segundo par de de ojos. Despus de cargar un parche o se presente una solicitud de extraccin, asegurarte de actualizar los metadatos del ticket mediante el establecimiento de las banderas correspondientes a el ticket que diga has patch, doesnt need tests, etc. (tiene parche, no necesita pruebas), para que otros puedan encontrarlos para su revisin. Contribuyendo no necesariamente significa escribir un parche desde cero. La revisin de parches existentes es tambin una contribucin muy til. Ver/internals/contributing/triaging-tickets para mas detalles. Publicado 30th December 2012 por Saul Garcia Etiquetas: Django, intro, Tutorial
Qu sigue?
0 Aadir un comentario Agregacin La gua de temas sobre Djangos database-abstraction API describe las formas en que podemos usar las 29 NOV Agregacin pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API consultas en Django para crear, recuperar, actualizar y eliminar objetos individualmente. Sin embargo, a veces se tiene la necesidad de obtener valores derivados de una suma o una agregacion de una coleccin de objetos. Esta gua temtica describe las maneras en que los valores agregados se pueden generar y devolver usando consultas o querys en Django. A lo largo de esta gua, nos referiremos a los siguientes modelos. Estos modelos son utilizados para realizar el seguimiento del inventario de una serie de libreras en lnea: class Author(models.Model): name = models.CharField(max_length=100) age = models.IntegerField() friends = models.ManyToManyField('self', blank=True) class Publisher(models.Model): name = models.CharField(max_length=300) num_awards = models.IntegerField() class Book(models.Model): isbn = models.CharField(max_length=9) name = models.CharField(max_length=300) pages = models.IntegerField() price = models.DecimalField(max_digits=10, decimal_places=2) rating = models.FloatField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) pubdate = models.DateField() class Store(models.Model): name = models.CharField(max_length=300) books = models.ManyToManyField(Book) En una apuracion? Esta es la forma mas comn de hacer consultas de agregados, asumiendo los modelos arriba mencionados: Cheat Sheet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API # Numero total de libros. >>> Book.objects.count() 2452 # El numero total de libros con un publisher=BaloneyPress >>> Book.objects.filter(publisher__name='BaloneyPress').count() 73 # Precio medio de los libros. >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} # Maximo precio de todos los libros. >>> from django.db.models import Max >>> Book.objects.all().aggregate(Max('price')) {'price__max': Decimal('81.20')} # Cada publisher, con un contador de libros con un atributo "num_books". >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs [<Publisher BaloneyPress>, <Publisher SalamiPress>, ...] >>> pubs[0].num_books 73 # El top 5 de publishers, en orden de numero de libros. >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5] >>> pubs[0].num_books 1323 Django proporciona dos maneras de generar agregados. La primera manera es generar los valores Agregados que generan ms de un QuerySet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API sumarios sobre un QuerySet entero. Por ejemplo, digamos que queremos calcular el precio medio de todos los libros disponibles para la venta. Los querys en Django proporcionan una sintaxis para describir el conjunto de todos los libros: >>> Book.objects.all() Lo que necesitamos es una manera de calcular la suma del valor de los objetos que pertenecen a esteQuerySet. Esto lo hacemos aadiendo una clausula aggregate() a el QuerySet de esta forma: >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} El metodo all() es redundante en este ejemplo, por lo se podra simplificar a: >>> Book.objects.aggregate(Avg('price')) {'price__avg': 34.35} El argumento para la clusula aggregate() describe el valor agregado que queremos calcular - en este caso, el promedio de los campos price en el modelo Book - . Una lista de las funciones agregadas est disponibles en la QuerySet reference. aggregate() es una clusula terminal para un QuerySet que, cuando se invoca, devuelve un diccionario de pares de nombre-valor. El nombre es un identificador para el valor agregado, el valor es la suma calculada. El nombre es generado automticamente a partir del nombre del campo y la funcin de agregado. Si se desea especificar manualmente un nombre para el valor agregado, puede hacerce proporcionando ese nombre cuando se especifica la clusula agregada: >>> Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} Si se desea generar ms de un agregado, solo devemos agregar otro argumento ala clusula aggregate(). Por lo tanto, si tambin queremos saber el precio mximo y mnimo de todos los libros, podramos emitir la consulta asi: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> from django.db.models import Avg, Max, Min, Count >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} La segunda manera de generar sumas de valores es el de generar sumas independientes de cada objeto en un QuerySet. Por ejemplo, si vamos a recuperar una lista de libros, podriamos querer saber cuntos autores contribuyeron a cada libro. Cada libro tiene una relacin de muchos a muchos con el autor, si queremos resumir esta relacin para cada libro del QuerySet La suma de pre-objetos se pueden generar utilizando la clusula annotate(). Cuando una clusulaannotate() se especifica, cada objeto del QuerySet ser anotada con los valores especificados. La sintaxis de estas anotaciones es idntica a la utilizada por la clusula aggregate() . Cada argumento aannotate() describe un agregado que sera calculado. Por ejemplo, para anotar los libros por el nmero de autores podemos usar: # construye un queryset anotado >>> q = Book.objects.annotate(Count('authors')) # preguntamos por el primer objeto del queryset >>> q[0] <Book: The Definitive Guide to Django> >>> q[0].authors__count 2 # preguntamos por el segundo objeto del queryset >>> q[1] <Book: Practical Django Projects> >>> q[1].authors__count 1 Al igual que con aggregate(), el nombre de la anotacin se deriva automticamente a partir del nombre de la funcin de agregado y el nombre del campo que se ha agregado. Se puede sustituir este Generacin de agregados para cada elemento de un QuerySet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API nombre por defecto al proporcionar un alias cuando se especifique la anotacin: >>> q = Book.objects.annotate(num_authors=Count('authors')) >>> q[0].num_authors 2 >>> q[1].num_authors 1 Tal como aggregate(), annotate() no es una clusula terminal. La salida de la clusula annotate() es unQuerySet; este QuerySet puede ser modificado como cualquier otro QuerySet con operaciones, incluyendofilter(), order_by, o incluso con llamadas adicionales a annotate(). Hasta ahora, nos hemos ocupado de los agregados sobre los campos que pertenecen a los modelos que se est consultando. Sin embargo, a veces el valor que se desea agregar pertenecer a un modelo que tiene que ver con el modelo que se est consultando. Al especificar el campo para ser agregados en una funcin de agregado, Django nos permitir utilizar la mismo double underscore notation (doble guion bajo) que utiliza para referirse a los campos relacionados en filtros. Django manejara las uniones de las tablas que son requeridas y agregara el valor reacionado. Por ejemplo, para encontrar el rango de precios de los libros que se ofrecen en cada tienda, se puede utilizar la anotacin: >>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price')) Esto le indica a Django que recupere el modelo Store, junto (a travs de la relacion muchos-a-muchos) con el modelo book, y agregue el precio de campo del modelo de libro para producir un valor mnimo y mximo. Las mismas reglas se aplican a clusula aggregate(). Si quisieramos saber el precio ms bajo y ms Juntar y Agregar pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API alto de todos los libros que estn disponibles para la venta en la tienda(Store), podramos utilizar elaggregate() siguiente: >>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price')) Juntar cadenas pueden ser tan profundo como sea necesario. Por ejemplo, para extraer la edad de la autora ms joven de todos los libros disponibles para la venta, se podra emitir la consulta: >>> Store.objects.aggregate(youngest_age=Min('books__authors__age')) Los agregados tambin pueden participar en filtros. Cualquier filter() (o exclude()) aplicado a los campos normales del modelo tendr el efecto de restringir los objetos que se consideran para la agregacin. Cuando se utilizan con un clusula annotate(), un filtro tiene el efecto de restringir los objetos para los que se calcula una anotacin. Por ejemplo, se puede generar una lista anotada de todos los libros que tienen un ttulo que empieza con Django utilizando la consulta: >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors')) Cuando se utiliza con una clusula aggregate(), un filtro tiene un efecto limitador de objetos sobre los cuales se calcula el agregado. Por ejemplo, se puede generar el precio medio de todos los libros con un ttulo que comience con Django utilizando la consulta: >>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price')) Agregaciones y otras clusulas de un QuerySet filter() y exclude() Filtros o anotaciones pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Los valores anotados tambin se puede filtrar. Los alias de la anotacin puede ser utilizados en clausulasfilter() y exclude() de la misma manera que cualquier otro modelo de campo. Por ejemplo, para generar una lista de libros que tienen ms de un autor, podemos ejecutar la siguiente consulta: >>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1) Esta consulta genera un conjunto de resultados anotados, a continuacin, genera un filtro basado en que la anotacin. Cuando se desarrolla una consulta compleja que involucra tanto una clusula annotate() si como unafilter(), se debe prestar especial atencin al orden en el que se aplican las clusulas del QuerySet. Cuando un clusula annotate() es aplicada a una consulta, la anotacin es calculada sobre el estado de la consulta hasta el punto en que la anotacin se solicita. La implicacin prctica de esto es que filter() yannotate() no son operaciones conmutativas - es decir, hay una diferencia entre la consulta -: >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) y la consulta: >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) Ambas consultas devolver una lista de editores que tienen por lo menos un buen libro (es decir, un libro con una calificacin superior a 3.0). Sin embargo, la anotacin en la primera consulta proporcionar el nmero total de todos los libros publicados por la editorial, la segunda consulta incluir solamente los buenos libros en el contador de la anotacin. En la primera consulta, la anotacin precede al filtro, por lo que el filtro no tiene efecto en la anotacin. En la segunda consulta, Ordenar clausulas annotate() y filter() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API el filtro precede a la anotacin, y como resultado, el filtro restringe los objetos considerados cuando se hace la anotacin. Las anotaciones se pueden utilizar basicamenente para ordenar. Cuando se define una clausulaorder_by (), los agregados suministrados pueden hacer referencia a cualquier alias definido como parte de una clusula annotate() en la consulta. Por ejemplo, para ordenar un QuerySet de libros por el nmero de autores que han colaborado en el libro, se puede utilizar la siguiente consulta: >>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors') Por lo general, las anotaciones se generan en funcin de cada objeto - una anotacion QuerySet devolver un resultado para cada objeto en el original QuerySet -. Sin embargo, cuando una clusula values() es utilizada para restringir las columnas que se devuelven en el conjunto de resultados, el mtodo de evaluacin de anotaciones es ligeramente diferente. En lugar de devolver un resultado anotado para cada resultado en el QuerySet, los resultados originales son agrupados de acuerdo con las combinaciones particulares de los campos especificados en la clusula values(). Una anotacin se proporciona entonces para cada grupo nico; la anotacin se calcula sobre todos los miembros del grupo. Por ejemplo, consideremos una consulta de un autor que intenta averiguar el promedio de valoracin de los libros escritos por cada autor: >>> Author.objects.annotate(average_rating=Avg('book__rating')) Esto devolver un resultado por cada autor en la base de datos, con la anotacin, y su clasificacin promedio contable. order_by() values() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Sin embargo, el resultado ser un poco diferente si se utiliza un clusula values(): >>> Author.objects.values('name').annotate(average_rating=Avg('book__rating')) En este ejemplo, los autores se agruparn por su nombre, por lo que se obtendr slo un resultado anotado para cada un Nombre nico autor. Esto significa que tenemos Dos autores con el mismo nombre, los resultados se fusionarn en una sola salida de consulta; el promedio se calcula como el promedio de los libros escritos por ambos autores. Al igual que con la clusula filter(), el orden en el cual las clausulas``annotate()`` y values() se aplican a una consulta es significativo. Si la clusula values() precede ala clausula annotate(), la anotacin ser calculada utilizando la agrupacin descrita por la clusula values(). Sin embargo, si la clusula annotate() precede a la clusula values(), las anotaciones se genera sobre el conjunto completo de la consulta. En este caso, la clusula values() slo limita los campos que se generan en la salida. Por ejemplo, si invertimos el orden de los valores de las clausulas values() y annotate() de nuestro ejemplo anterior: >>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rat ing') Esto ahora producira un resultado nico para cada autor, sin embargo, slo el nombre del autor y la anotacin average_rating ser devuelto en los datos de salida. Tambin debemos tener en cuenta que average_rating se ha incluido explcitamente en la lista de valores que se devuelven. Esto es necesario debido a la orden de los valores de las clusulas values() yannotate(). Si la clusula values() precede ala clusula annotate(), las anotaciones se aaden automticamente El order de clusulas annotate() y values() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API a la hoja de resultados. Sin embargo, si la clusula values() se aplica despus de la clusula annotate(), se debe explcitamente incluir la columna agregada. Los campos que se mencionan en el metodo order_by() por parte de un queryset (o que se utilizan en el orden predeterminado de un modelo) se usan cuando se selecciona los datos de salida, incluso si no se especifique otra cosa en la llamada a values(). Estos campos adicionales se utilizan para agrupar y juntar resultados similares entre s y que pueden tener otros resultados en filas idnticas, pero de un modo separado. Esto se manifiesta, en particular, al contar cosas. A modo de ejemplo, supongamos que se tiene un modelo como este: class Item(models.Model): name = models.CharField(max_length=10) data = models.IntegerField() class Meta: ordering = ["name"] La parte importante aqu es el orden predeterminado en el campo name. Si deseamos contar cuntas veces cada valor data distinto aparece, es posible que intentemos esto: # Advertencia: No del todo correcto! Item.objects.values("data").annotate(Count("id")) ... Que agrupar los objetos Item por su valor comn data y luego contara el nmero de valores id en cada grupo. Slo que no terminara de funcionar. El valor por defecto name tambin jugar un papel importante en la agrupacin, por lo que si queremos una consulta de grupos de pares de distintos(data, name) , que no es lo que queremos. En su lugar, devemos construir este queryset: Item.objects.values("data").annotate(Count("id")).order_by() ...limpiamos y ordenamos la consulta. Tambin podriamos ordenar, por decir, date sin ningn efecto Interaccin con un orden predeterminado o order_by() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API perjudicial, puesto que ya est jugando un papel en la consulta. Este comportamiento es el mismo que se indica en la documentacin para el distinct() y la regla general es la misma: normalmente no querremos columnas extra que juegan un papel importante en el resultado, por lo que limpiar el orden, o al menos asegurarse de que se est restringiendo al menos esos campos que tambien son seleccionados en la llamada a values(). Note Es razonable preguntar por qu Django no elimina las columnas extraas por nosotros. La razn principal es por mantener la coherencia con distinc () y otros lugares: Django nuncaeliminara el orden de retriccion que hayamos especificado (y no podemos cambiar el comportamiento de los otros mtodos, ya que esto violara nuestro: /misc/api-stabilitypolicy). Tambin se puede generar un agregado en el resultado de una anotacin. Cuando definimos una clausulaaggregate(), los agregados suministrados pueden hacer referencia a cualquier alias definido como parte de una clusula annotate() de la consulta. Por ejemplo, si desea calcular el nmero promedio de autores por el conjunto de libros con el recuento autor, entonces el agregado que cuenta el autor, haciendo referencia al campo de anotaciones: >>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')) {'num_authors__avg': 1.66} Publicado 29th November 2012 por Saul Garcia Etiquetas: base de datos, Django
Agregacin de anotaciones pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API
1 Ver comentarios Vistas genricas basadas en clase Changed in Django 1.3: Please see the release notes Note A partir de Django 1.3, las vistas genricas basadas en funciones han quedado en desuso en favor de un enfoque basado en clases, que se describe aqu. Para detalles sobre implementaciones previas puedes ver el documento topic guide y la detailed reference. Escribir aplicaciones web pueden ser montono, ya que repetimos ciertos patrones una y otra vez. Django intenta quitar algo de esa monotona en el modelo y en la capa de plantillas, pero los desarrolladores web tambin experimentan ese aburrimiento a nivel de vistas. Las Visitas genricas en Django fueron desarrolladas para aliviar ese dolor. Toman ciertas expresiones y patrones comunes encontrados en el desarrollo de vista y lo abstraen de modo que podamos escribir vistas comunes de datos sin tener que escribir demasiado cdigo. Podemos reconocer ciertas tareas comunes, como mostrar una lista de objetos y escribir el cdigo que muestra una lista de objetos cualquiera. El modelo en cuestin puede ser pasado como un argumento adicional a travs de la URLconf. Django viene con vistas genricas que pueden hacer lo siguiente: 29 NOV Vistas genricas basadas en clase pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Django viene con vistas genricas que pueden hacer lo siguiente: Realizar tareas simples y comunes: redirigir a una pgina diferente y renderizar una plantilla dada. Mostrar paginas de listado y detalles para un nico objeto. Si estuviramos creando un aplicacin para gestionar conferencias tendramos una vista talk_list y tambin una registered_user_listestas vista seran ejemplos de ListView (listado). Una simple pgina de discusin es un ejemplo de lo que llamamos una vista de DetailView (detalle). Presentar objetos basados en datos en paginas del tipo fecha, ao/mes/da y su detalle asociado, y las paginas nuevas. Los archivo del blog web de Django (https://www.djangoproject.com/weblog/) son archivos del tipo ao, mes y da y se construyen de esta forma, como sera un tpico archivo de un peridico Permitir a los usuarios crear, actualizar y borrar objetos -con o sin autorizacin-. Tomados en conjunto, estas vistas proporcionan interfaces fciles para realizar los trabajos ms comunes que puedan encontrar los desarrolladores. Las vistas basados en clases genricas (y cualquier vista basada en clases heredaran los atributos de las clases base que proporcionan Django) se puede configurar de dos maneras: creando una subclase y/o pasando directamente los argumentos en la URLconf. Cuando sobreescribimos algunos atributos en una subclase de una vista basada en (Tal como eltemplate_name) o algun mtodo (tal como get_context_data) en la subclase para proporcionar nuevos valores o mtodos. Consideremos, por ejemplo, una vista que slo muestra una plantilla about.html. Django posee una vista genrica para hacer esto - TemplateView - para que podamos simplemente pasarla como una subclase y sobreescribir el nombre de la plantilla: # alguna_app/views.py from django.views.generic import TemplateView Simple uso pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API class AboutView(TemplateView): template_name = "about.html" Luego, slo tenemos que aadir esta nueva vista a nuestra URLconf. Como las clases basadas en vistas son en en s mismo clases, necesitamos apuntar el mtodo as_view ala URL de la clase en su lugar, que es el punto de entrada para las vistas basadas en clases: # urls.py from django.conf.urls import patterns, url, include from some_app.views import AboutView urlpatterns = patterns('', (r'^about/', AboutView.as_view()), ) Alternativamente, si slo est cambiando algunos pequeos atributos en un vista basada en clases, slo necesitamos pasar los nuevos atributos en la llamada al mtodo as_view en si mismo: from django.conf.urls import patterns, url, include from django.views.generic import TemplateView urlpatterns = patterns('', (r'^about/', TemplateView.as_view(template_name="about.html")), ) Un patrn predominantemente similar se puede utilizar para usar un atributo en la url en la claseRedirectView, otra sencilla vista genrica. El mtodo TemplateView es ciertamente til, pero las vistas genricas de Django realmente brillan cuando se trata de presentar vistas sobre el contenido de tu base de datos. Porque Es una tarea comn, Django viene con un puado de vistas genricas incorporadas que hacen la generacin de vistas de listado y detalle de objetos increblemente fcil. Vistas genricas de objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Echemos un vistazo a una de estas vistas genricas: la vista object list. Vamos a usar estos modelos: # models.py from django.db import models class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharField(max_length=50) city = models.CharField(max_length=60) state_province = models.CharField(max_length=30) country = models.CharField(max_length=50) website = models.URLField() class Meta: ordering = ["-name"] def __unicode__(self): return self.name class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField('Author') publisher = models.ForeignKey(Publisher) publication_date = models.DateField() Para crear una pagina de lista o un listado de todos los publishers, usaremos la URLconf bajo estas lineas: from django.conf.urls import patterns, url, include from django.views.generic import ListView from books.models import Publisher urlpatterns = patterns('', (r'^publishers/$', ListView.as_view( model=Publisher, pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API )), ) Este es todo el cdigo Python que necesitamos escribir. Sin embargo, todava tenemos que escribir una plantilla. Sin embargo podramos decirle explcitamente ala vista que plantilla debe utilizar mediante la inclusin de un argumento template_name en el mtodo as_view, pero en la ausencia de una plantilla explcita Django inferir una del nombre del objeto. En este caso, la plantilla inferida sera"books/publisher_list.html" - la parte books proviene del nombre de la aplicacin que define el modelo, mientras que el publisher es solo la versin del nombre del modelo en minsculas. Note Por lo tanto, cuando (por ejemplo) django.template.loaders.app_directories.Loader el cargador de plantillas este habilitado en TEMPLATE_LOADERS, la ubicacin de la plantilla sera: /path/to/project/books/templates/books/publisher_list.html Esta plantilla ser renderizada en un contexto que contiene una variable llamada object_list la cual contiene todos los objetos publisher. Una plantilla muy simple podra verse como la siguiente: {% extends "base.html" %} {% block content %} <h2>Publishers</h2> <ul> {% for publisher in object_list %} <li>{{ publisher.name }}</li> {% endfor %} </ul> {% endblock %} Eso es realmente todo en lo referente al tema. Todas las geniales caractersticas de las vistas pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API genricas provienen de cambiar el diccionario info pasado a la vista genrica. El documentogeneric views reference describe todas las vistas genricas y todas sus opciones en detalle; el resto de este captulo considerar algunas de las formas comunes en que t puedes personalizar y extender las vistas genricas. No hay duda de que el uso de las vistas genricas puede acelerar el desarrollo sustancialmente. En la mayora de los proyectos, sin embargo, llega un momento en el que las vistas genrica no son suficientes. De hecho, la pregunta ms comn que se hacen los desarrolladores de Django es cmo hacer que las vistas genricas manejen un rango ms amplio de situaciones. Esta es una de las razones del por que las vistas genricas fueron rediseadas para el lanzamiento de la versin 1,3 - anteriormente, solo eran funciones con una desconcertante variedad de opciones; Ahora, en lugar de pasar una gran cantidad de configuraciones en la URLconf, el mtodo recomendado para extender las vistas genricas es crear una subclase de ellos, y anular y sobreescribir sus atributos o mtodos. Tal vez hayas notado que el ejemplo de la plantilla publisher list almacena todos los books en una variable llamada object_list. Aunque que esto funciona bien, no es una forma amistosa para los autores de plantillas: ellos slo tienen que saber aqu que estn trabajando con books. Un nombre mejor para esa variable sera publisher_list ; el contenido de esa variable es bastante obvio. Si Bien, si estamos tratando con un objeto de modelo, esto ya est hecho por nosotros. Cuando se trata de un objeto o queryset, Django es capaz de rellenar el contexto con el nombre verbose, en el caso la lista de objetos) del objeto que sera mostrado. Esto sera proporcionado por defecto como object_list, pero contiene exactamente los mismos datos. Si el nombre verbose no concuerda todava, se puede configurar manualmente el nombre de la variable de contexto. El atributo context_object_name de una vista genrica especifica la variable de Extender las vistas genricas Haciendo contextos de plantilla amigables pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API contexto de su uso. En este ejemplo, vamos a reemplazar el de la URLconf, con un simple cambio: urlpatterns = patterns('', (r'^publishers/$', ListView.as_view( model=Publisher, context_object_name="publisher_list", )), ) Proporcionar un til context_object_name es siempre una buena idea. Podemos cambiar el nombre de esa variable fcilmente con el argumento template_object_name: Tus compaeros de trabajo que disean las plantillas te lo agradecern. A menudo simplemente necesitamos presentar alguna informacin extra aparte de la proporcionada por la vista genrica. Por ejemplo, piensa en mostrar una lista de todos los otros publisher en cada pgina de detalle de un publisher. La vista genrica DetailView provee a el publisher el contexto, pero parece que no hay forma de obtener una lista de todos los publishers en esa plantilla. Pero s la hay: esta la proporciona la subclase DetailView , extra_context. Este es un diccionario de objetos extra que sern agregados y provee una implementacin del mtodo get_context_data .La implementacin por viene con la clase DetailView simplemente agregamos el objeto que vamos a mostrar en la plantilla, pero podemos sobrescribir mas: from django.views.generic import DetailView from books.models import Publisher, Book class PublisherDetailView(DetailView): context_object_name = "publisher" model = Publisher def get_context_data(self, **kwargs): Agregar un contexto extra pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API # Llamamos ala implementacion para traer un primer context context = super(PublisherDetailView, self).get_context_data(**kwargs) # Agregamos un QuerySet de todos los books context['book_list'] = Book.objects.all() return context Ahora echemos un vistazo ms de cerca el argumento model que hemos estado usando todo el tiempo. El argumento model, que especifica el modelo de la base de datos sobre la que la vista operar, est disponible en todos los vistas genricas que operan en un solo objeto o en una coleccin de objetos. Sin embargo, el argumento model no es la nica manera de especificar los objetos que la vista que operan - tambin se pueden especificar la lista de objetos utilizando el argumento QuerySet from django.views.generic import DetailView from books.models import Publisher, Book class PublisherDetailView(DetailView): context_object_name = "publisher" queryset = Publisher.objects.all() Especificando model = Publisher en realidad es una atajo para decirqueryset = Publisher.objects.all(). Sin embargo, mediante el uso de queryset para definir una lista filtrada de objetos que pueden ser ms especfico sobre la objetos que sern visibles en la vista (verRealizando consultas Para obtener ms informacin acerca de los objetos QuerySet, y puedes verclass-based views reference para detalles completos. Para escoger un ejemplo sencillo, queremos ordenar una lista de libros por su fecha de publicacin, con el ms reciente al principio usaramos la siguiente forma en el archivo URLconf: urlpatterns = patterns('', Mostrar subconjuntos de objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API (r'^publishers/$', ListView.as_view( queryset=Publisher.objects.all(), context_object_name="publisher_list", )), (r'^books/$', ListView.as_view( queryset=Book.objects.order_by("-publication_date"), context_object_name="book_list", )), ) Este es un ejemplo bastante simple, pero ilustra muy bien la idea. Por supuesto, t usualmente querrs hacer ms que slo reordenar objetos. Si quieres presentar una lista de books de un publisher en particular, puedes usar la misma tcnica (en este caso, lo ilustramos mediante la creacin de una subclase en lugar pasar los argumentos en la URLconf)): from django.views.generic import ListView from books.models import Book class AcmeBookListView(ListView): context_object_name = "book_list" queryset = Book.objects.filter(publisher__name="Acme Publishing") template_name = "books/acme_list.html" Nota que tambin estamos filtrando un queryset , y estamos usando un nombre de plantilla personalizado. Si no lo hiciramos, la vista genrica usara la misma plantilla que la lista de objetos genrica, que puede no ser lo que queremos. Tambin nota que sta no es una forma muy elegante de encontrar los publisher-specific books. Si queremos agregar otra pgina publisher, necesitamos otro puado de lneas en la URLconf, y ms de unos pocos publishers no ser razonable. Enfrentaremos este problema en la siguiente seccin. Note Si obtienes un error 404 cuando solicitas /books/acme/, para estar seguro, verifica que en pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API realidad tienes un Publisher con el nombre ACME Publishing. Las vistas genricas tienen un parmetro allow_empty para estos casos. Mira en class-based-views reference para mas detalles. Otra necesidad comn es filtrar los objetos que se muestran en una pgina listado por alguna clave en la URLconf. Anteriormente codificamos el nombre del publisher en la URLconf, pero qu pasa si queremos escribir una vista que muestre todos los books por algn publisher arbitrario?. Convenientemente tenemos una vista ListView que tiene un mtodo get_queryset() que podemos sobreescribir. Anteriormente, solo retornamos los atributos del valor del queryset , pero ahora podemos aadir ms lgica. La parte clave para hacer este trabajo es que cuando vistas basadas en clases son llamadas se almacenas varias cosas tiles self; si bien la peticin (self.request) que incluye la posicin (self.args) y los nombres basados en argumentos (self.kwargs) capturados de acuerdo ala URLconf. Aqu tenemos una URLconf con un simple grupo capturado: from books.views import PublisherBookListView urlpatterns = patterns('', (r'^books/(\w+)/$', PublisherBookListView.as_view()), ) A continuacin, escribiremos la vista PublisherBookListView from django.shortcuts import get_object_or_404 from django.views.generic import ListView from books.models import Book, Publisher class PublisherBookListView(ListView): Filtrado dinmico pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API context_object_name = "book_list" template_name = "books/books_by_publisher.html" def get_queryset(self): publisher = get_object_or_404(Publisher, name__iexact=self.args[0]) return Book.objects.filter(publisher=publisher) Como se puede ver, es muy fcil agregar ms lgica al queryset seleccionado; si quisiramos, podramos usar self.request.user para filtrar el usuario actual , o podemos usar alguna lgica un poco ms compleja. Tambin podemos aadir el publisher en el mismo contexto, para poder utilizarlo en la plantilla: class PublisherBookListView(ListView): context_object_name = "book_list" template_name = "books/books_by_publisher.html" def get_queryset(self): self.publisher = get_object_or_404(Publisher, name__iexact=self.args[0]) return Book.objects.filter(publisher=self.publisher) def get_context_data(self, **kwargs): # Llamamos ala implementacion primero del context context = super(PublisherBookListView, self).get_context_data(**kwargs) # Agregamos el publisher context['publisher'] = self.publisher return context El ltimo patrn comn que veremos involucra realizar algn trabajo extra antes o despus de llamar a la vista genrica. Imagina que tenemos un campo last_accessed en nuestro objeto Author que estuvimos usando para tener un registro de la ltima vez que alguien vio ese author: Realizar trabajo extra pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API # models.py class Author(models.Model): salutation = models.CharField(max_length=10) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=40) email = models.EmailField() headshot = models.ImageField(upload_to='/tmp') last_accessed = models.DateTimeField() La vista genrica object_detail, por supuesto, no sabra nada sobre este campo, pero una vez ms podramos fcilmente escribir una vista personalizada para mantener ese campo actualizado: from books.views import AuthorDetailView urlpatterns = patterns('', #... (r'^authors/(?P<pk>\d+)/$', AuthorDetailView.as_view()), ) La clase genrica DetailView, por supuesto, no sabe nada de este campo, pero una vez ms, fcilmente podramos escribir una vista personalizada para mantener ese campo actualizado. En primer lugar, tendramos que aadir los detalles del autor en la URLconf para que apunte a una vista personalizada: from books.views import AuthorDetailView urlpatterns = patterns('', #... (r'^authors/(?P<pk>\d+)/$', AuthorDetailView.as_view()), ) A continuacin, necesitamos escribir la funcin - get_object que es el mtodo que recupera un objeto - por lo que slo tenemos que sobrescribir y envolver la llamada: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API import datetime from books.models import Author from django.views.generic import DetailView from django.shortcuts import get_object_or_404 class AuthorDetailView(DetailView): queryset = Author.objects.all() def get_object(self): # Llamamos ala superclase object = super(AuthorDetailView, self).get_object() # Grabamos el ultimo acceso ala base de datos object.last_accessed = datetime.datetime.now() object.save() # Retornamos el objeto return object Note Este cdigo en realidad no funcionar a menos que escribamos la plantilla books/author_detail.html Note La URLconf aqu usa el nombre del grupo pk este nombre es el valor por defecto que usaDetailView para encontrar el valor primario que se usa para filtrar el queryset. Si deseamos cambiarlo, necesitamos crear una llamada a el mtodo``get()`` en un self.querysetusando el nuevo nombre del parmetro de self.kwargs. Mas que solo HTML pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Hasta ahora, nos hemos centrado en renderizar plantillas para generar respuestas html. Sin embargo, eso no es todo lo que las vistas genricas puede hacer. Cada vista genrica esta compuesta de una una serie de mixins, y cada uno de esos mixin contribuye con una pequea parte a toda la vista. Algunos de estos mixins - Son tales como TemplateResponseMixin son especficamente diseado para representar el contenido de una respuesta HTML usando una plantilla. Sin embargo, podemos escribir nuestros propios mixins para que devuelvan un contenido diferente. Por ejemplo, un simple mixin JSON podra ser algo como esto: from django import http from django.utils import simplejson as json class JSONResponseMixin(object): def render_to_response(self, context): "Returns a JSON response containing 'context' as payload" return self.get_json_response(self.convert_context_to_json(context)) def get_json_response(self, content, **httpresponse_kwargs): "Construct an `HttpResponse` object." return http.HttpResponse(content, content_type='application/json', **httpresponse_kwargs) def convert_context_to_json(self, context): "Convert the context dictionary into a JSON object" # Note: This is *EXTREMELY* naive; in reality, you'll need # to do much more complex handling to ensure that arbitrary # objects -- such as Django model instances or querysets # -- can be serialized as JSON. return json.dumps(context) Entonces podramos escribir una vista que nos retorne una respuesta JSON DetailView con los tipos de mixing JSONResponseMixin con la BaseDetailView (la DetailView antes de que la plantilla sea renderizada con el mixin ): pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API renderizada con el mixin ): class JSONDetailView(JSONResponseMixin, BaseDetailView): pass Este tipo de vista se puede implementar de igual forma que las otras vista DetailView con el mismo comportamiento exepto el formato de respuesta Si somos realmente aventureros podemos usar una mezcla de la clase DetailView para que sea capaz de de devolver ambos contenidos HTML y JSON dependiendo de alguna propiedad de la solicitud HTTP tal como un argumento o una cabecera HTTP.Solamente mezclando la clase JSONResponseMixin y la claseSingleObjectTemplateResponseMixin, sobreescribiendo la implementacion ala funcinrender_to_response() para aplazar ala subclase apropiada dependiendo del tipo de respuesta que el usuario pidi: class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView ): def render_to_response(self, context): # Look for a 'format=json' GET argument if self.request.GET.get('format','html') == 'json': return JSONResponseMixin.render_to_response(self, context) else: return SingleObjectTemplateResponseMixin.render_to_response(self, context) Devido ala forma en que python resuelve el mtodo de sobrecarga, la implementacion local del mtodorender_to_response() sobrescribe la versin proporcionada por la clase JSONResponseMixin y la claseSingleObjectTemplateResponseMixin. Para extender el uso de clases genricas no estamos limitado solamente a el uso de mixins.Tambin podemos usar decoradores. Decorando clases basadas en vistas Decorando una URLconf pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API La forma mas simple de decorar una clase genrica es decorando el resultado del mtodo as_view() El mejor lugar para utilizar un decorador es en la clase del mtodo en si mismo dispatch(). Un mtodo en una clase no es lo mismo que una funcin independiente, por lo que no se puede simplemente aplicar un decorador ala funcin del mtodo - es necesario transformarlo primero en un mtodo decorado. El mtodo decorador method_decorator transforma una funcin en un mtodo decorado que se puede utilizar en un mtodo de una de instancia. Por ejemplo: from django.contrib.auth.decorators import login_required from django.utils.decorators import method_decorator from django.views.generic import TemplateView class ProtectedView(TemplateView): template_name = 'secret.html' @method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs) En este ejemplo, cada instancia de ProtectedView tendr proteccin de login, con tan solo licarle el decorador. Note El mtodo method_decorator pasa *args y **kwargs como parmetros al mtodo representativo de la clase. Si el mtodo no acepta un conjunto compatible de parmetros sera lanzada una excepcin del tipo TypeError. Publicado 29th November 2012 por Saul Garcia Etiquetas: Django, vistas
pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API
0 Aadir un comentario Relaciones One-to-one Para definir una relacin uno a uno, utilizamos ref-onetoone. En este ejemplo, Place opcionalmente puede ser un Restaurant: from django.db import models, transaction, IntegrityError class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) def __unicode__(self): return u"%s the place" % self.name class Restaurant(models.Model): place = models.OneToOneField(Place, primary_key=True) serves_hot_dogs = models.BooleanField() serves_pizza = models.BooleanField() def __unicode__(self): return u"%s the restaurant" % self.place.name class Waiter(models.Model): restaurant = models.ForeignKey(Restaurant) 28 NOV Relaciones One-to-one pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API name = models.CharField(max_length=50) def __unicode__(self): return u"%s the waiter at %s" % (self.name, self.restaurant) Los ejemplos que siguen son una muestra de las operaciones que se pueden realizar usando la API interactiva python. Primero creamos un par de lugares (Places): >>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton') >>> p1.save() >>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland') >>> p2.save() Creamos un restaurant. Pasamos la identificacin del objeto ID padre como ID de este objeto: >>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False) >>> r.save() Un restaurante puede tener acceso a un lugar: >>> r.place <Place: Demon Dogs the place> Un lugar puede tener acceso a un restaurante, si est disponible: >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> p2 no tiene un restaurante asociado por lo que lanza un error: >>> p2.restaurant Traceback (most recent call last): ... pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API DoesNotExist: Restaurant matching query does not exist. Establecemos place usando la notacin de asignacin. Porque place es la clave primaria de el restaurant, al guardar esto creamos un nuevo restaurant: >>> r.place = p2 >>> r.save() >>> p2.restaurant <Restaurant: Ace Hardware the restaurant> >>> r.place <Place: Ace Hardware the place> Establecemos place detrs otra vez, usando la asignacin en la direccin opuesta: >>> p1.restaurant = r >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> Restaurant.objects.all() devuelve todos los restaurantes, no los lugares.Nota que hay dos restaurantes - Ace Hardware the Restaurant - fue creado en la llamada a r.place = p2: >>> Place.objects.order_by('name') [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>] Place.objects.all() devuelve todos los lugares, sin importar si tienen Restaurantes: >>> Place.objects.order_by ("nombre" ") [<Place: Hardware del as el place>, <Place: El demonio persigue el place>] Podemos hacer un query a los modelos usando: lookups across relationships: >>> Restaurant.objects.get(place=p1) <Restaurant: Demon Dogs the restaurant> >>> Restaurant.objects.get(place__pk=1) <Restaurant: Demon Dogs the restaurant> pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Restaurant.objects.filter(place__name__startswith="Demon") [<Restaurant: Demon Dogs the restaurant>] >>> Restaurant.objects.exclude(place__address__contains="Ashland") [<Restaurant: Demon Dogs the restaurant>] Esto por supuesto trabaja en forma inversa: >>> Place.objects.get(pk=1) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant__place__exact=p1) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant=r) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant__place__name__startswith="Demon") <Place: Demon Dogs the place> Podemos agregar un camarero al restaurante: >>> w = r.waiter_set.create(name='Joe') >>> w.save() >>> w <Waiter: Joe the waiter at Demon Dogs the restaurant> Podemos obtener los camareros: >>> Waiter.objects.filter(restaurant__place=p1) [<Waiter: Joe the waiter at Demon Dogs the restaurant>] >>> Waiter.objects.filter(restaurant__place__name__startswith="Demon") [<Waiter: Joe the waiter at Demon Dogs the restaurant>] Publicado 28th November 2012 por Saul Garcia Etiquetas: base de datos, Django
pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API
0 Aadir un comentario Relaciones Many-to-Many Para definir una relacin muchos a muchos, utilizamos la relacin ref-manytomany. En este ejemplo, un objeto Article puede ser publicado en mltiples objetos Publication y unaPublication tiene mltiples objetos Articles : from django.db import models class Publication(models.Model): title = models.CharField(max_length=30) def __unicode__(self): return self.title class Meta: ordering = ('title',) class Article(models.Model): headline = models.CharField(max_length=100) publications = models.ManyToManyField(Publication) def __unicode__(self): return self.headline 28 NOV Relaciones Many-to-Many pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API class Meta: ordering = ('headline',) Estos ejemplos que siguen son operaciones que se pueden realizar usando la API interactiva que nos facilita python. python manage.py shell Creamos un par de publicaciones: >>> p1 = Publication(title='The Python Journal') >>> p1.save() >>> p2 = Publication(title='Science News') >>> p2.save() >>> p3 = Publication(title='Science Weekly') >>> p3.save() Creamos un artculo: >>> a1 = Article(headline='Django lets you build Web apps easily') No podemos asociar una publicacin hasta que esta se haya guardado: >>> a1.publications.add(p1) Traceback (most recent call last): ... ValueError: 'Article' instance needs to have a primary key value before a many-to-many rela tionship can be used. La guardamos primeramente: >>> a1.save () Ahora ya podemos asociar un Articulo con una Publicacion: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> a1.publications.add(p1) Creamos otro artculo y lo guardamos para que aparezca en ambas publicaciones: >>> a2 = Article(headline='NASA uses Python') >>> a2.save() >>> a2.publications.add(p1, p2) >>> a2.publications.add(p3) Agregar una segunda vez es ACEPTABLE: >>> a2.publications.add (p3) Agregar un objeto de tipo incorrecto levantara un error del tipo TypeError: >>> a2.publications.add(a1) Traceback (most recent call last): ... TypeError: 'Publication' instance expected Agregamos una publicacin directamente va publications.add usando los argumentos clave: >>> new_publication = a2.publications.create(title='Highlights for Children') Los objetos del artculo tienen acceso a las relaciones de sus objetos publication: >>> a1.publications.all() [<Publication: The Python Journal>] >>> a2.publications.all() [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] Los objetos de la publicacin tienen acceso a los objetos relacionados del artculo: >>> p2.article_set.all() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API [<Article: NASA uses Python>] >>> p1.article_set.all() [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Publication.objects.get(id=4).article_set.all() [<Article: NASA uses Python>] Las relaciones Many-to-many (muchos a muchos) pueden ser obtenidas a travez de la lookups across relationships >>> Article.objects.filter(publications__id__exact=1) [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Article.objects.filter(publications__pk=1) [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Article.objects.filter(publications=1) [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Article.objects.filter(publications=p1) [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Article.objects.filter(publications__title__startswith="Science") [<Article: NASA uses Python>, <Article: NASA uses Python>] >>> Article.objects.filter(publications__title__startswith="Science").distinct() [<Article: NASA uses Python>] La funcin count() respecto a distinct() tambin funcionan: >>> Article.objects.filter(publications__title__startswith="Science").count() 2 >>> Article.objects.filter(publications__title__startswith="Science").distinct().count() 1 >>> Article.objects.filter(publications__in=[1,2]).distinct() [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] >>> Article.objects.filter(publications__in=[p1,p2]).distinct() [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>] pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Las relaciones inversas m2m son soportadas (es decir, comenzando en la tabla que no tiene un ManyToManyField): >>> Publication.objects.filter(id__exact=1) [<Publication: The Python Journal>] >>> Publication.objects.filter(pk=1) [<Publication: The Python Journal>] >>> Publication.objects.filter(article__headline__startswith="NASA") [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] >>> Publication.objects.filter(article__id__exact=1) [<Publication: The Python Journal>] >>> Publication.objects.filter(article__pk=1) [<Publication: The Python Journal>] >>> Publication.objects.filter(article=1) [<Publication: The Python Journal>] >>> Publication.objects.filter(article=a1) [<Publication: The Python Journal>] >>> Publication.objects.filter(article__in=[1,2]).distinct() [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] >>> Publication.objects.filter(article__in=[a1,a2]).distinct() [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>] Excluir algun item de un artculo relacionado trabaja tambin como se esperara,(aunque el SQL implicado es un poco mas complejo): >>> Article.objects.exclude(publications=p2) [<Article: Django lets you build Web apps easily>] Si borramos una publicacin, los objetos artculos no podrn tener acceso a el: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> p1.delete() >>> Publication.objects.all() [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>] >>> a1 = Article.objects.get(pk=1) >>> a1.publications.all() [] Si borramos un artculo, sus publicaciones no podrn tener acceso a el: >>> a2.delete() >>> Article.objects.all() [<Article: Django lets you build Web apps easily>] >>> p2.article_set.all() [] Agregando va el otro extremo de un m2m: >>> a4 = Article(headline='NASA finds intelligent life on Earth') >>> a4.save() >>> p2.article_set.add(a4) >>> p2.article_set.all() [<Article: NASA finds intelligent life on Earth>] >>> a4.publications.all() [<Publication: Science News>] Agregando va el otro extremo usando palabras claves: >>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders') >>> p2.article_set.all() [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders> ] >>> a5 = p2.article_set.all()[1] >>> a5.publications.all() [<Publication: Science News>] pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Eliminando publicaciones de un artculo: >>> a4.publications.remove(p2) >>> p2.article_set.all() [<Article: Oxygen-free diet works wonders>] >>> a4.publications.all() [] Y del otro extremo: >>> p2.article_set.remove(a5) >>> p2.article_set.all() [] >>> a5.publications.all() [] Las relaciones pueden ser asignados. La asignacin borra cualquier miembro determinado existente: >>> a4.publications.all() [<Publication: Science News>] >>> a4.publications = [p3] >>> a4.publications.all() [<Publication: Science Weekly>] Las relaciones de un conjunto se pueden limpiar: >>> p2.article_set.clear () >>> p2.article_set.all () [] Y podemos borrar el otro extremo: >>> p2.article_set.add(a4, a5) >>> p2.article_set.all() [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders> ] pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> a4.publications.all() [<Publication: Science News>, <Publication: Science Weekly>] >>> a4.publications.clear() >>> a4.publications.all() [] >>> p2.article_set.all() [<Article: Oxygen-free diet works wonders>] Volvemos a crear los artculos y las publicacin que hemos borrado: >>> p1 = Publication(title='The Python Journal') >>> p1.save() >>> a2 = Article(headline='NASA uses Python') >>> a2.save() >>> a2.publications.add(p1, p2, p3) Borramos alguna publicaciones en grupo - las referencias a las publicaciones deben ir: >>> Publication.objects.filter(title__startswith='Science').delete() >>> Publication.objects.all() [<Publication: Highlights for Children>, <Publication: The Python Journal>] >>> Article.objects.all() [<Article: Django lets you build Web apps easily>, <Article: NASA finds intelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free diet works wonders>] >>> a2.publications.all() [<Publication: The Python Journal>] Borramos un grupo de artculos - las referencias a los objetos suprimidos deben ir: >>> q = Article.objects.filter(headline__startswith='Django') >>> print q [<Article: Django lets you build Web apps easily>] >>> q.delete() Despus de que borramos, el cache de un QuerySet necesita ser limpiado y la referencia a los objetos deben de ir: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> print q [] >>> p1.article_set.all() [<Article: NASA uses Python>] Un modo alternativo de llamar a clear() es asignar un conjunto vaco: >>> p1.article_set = [] >>> p1.article_set.all() [] >>> a2.publications = [p1, new_publication] >>> a2.publications.all() [<Publication: Highlights for Children>, <Publication: The Python Journal>] >>> a2.publications = [] >>> a2.publications.all() [] Publicado 28th November 2012 por Saul Garcia Etiquetas: base de datos, Django
0 Aadir un comentario Filtros que hacen referencia a campos de un modelo 28 NOV pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API En los ejemplos dados hasta ahora, hemos construido filtros que comparan el valor de un campo con un modelo constante. Pero si lo que deseamos es comparar el valor de un campo de un modelo con otro campo en el mismo modelo? Django proporciona un F() expressions para permitir tales comparaciones. Las instancias de F() actan como una referencia a un campo dentro de un modelo de consulta. Estas referencias se pueden usar en filtros de consulta para comparar los valores de dos campos diferentes en la misma instancia del modelo. Por ejemplo, para encontrar una lista de todas las entradas que han tenido ms comentarios que pingbacks, construimos un objeto F() para hacer una referencia al contador de pingbacks, y usamos el objeto para hacer la consulta F() >>> from django.db.models import F >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks')) Django soporta el uso de la suma, resta, multiplicacin,la divisin y el modulo aritmtico, con un objetoF(), tanto para constantes como para otros objetos F(). Para encontrar todas las entradas de blog con ms de Dos comentarios como pingbacks, modificamos la consulta as: >>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2) Para encontrar todas las entradas que tengan un rating menor que la suma del conteo de pingbacks y el recuento de comentarios, modificamos la consulta: >>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks')) Tambin podemos utilizar la notacin de guin doble bajo doble para abarcar las relaciones en un objetoF(). Un objeto F() con un guin doble bajo introducir una unin necesaria para acceder al objeto relacionado. Por ejemplo, para recuperar todas las entradas en las que el nombre del autor es el mismo que el nombre del blog, podramos emitir la consulta as: Filtros que hacen referencia a campos de un modelo pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Entry.objects.filter(authors__name=F('blog__name')) New in Django 1.3: Please see the release notes Para los campos de fecha/hora, podemos aadir o restar un objeto timedelta. El siguiente ejemplo mostrar todas las entradas que se modificaron 3 das despus de su publicacin: >>> from datetime import timedelta >>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3)) Por conveniencia, Django proporciona un atajo de bsqueda pk, que significa Clave primaria(por primary key en ingles). En el modelo de ejemplo Blog, la clave principal es el campo id , por lo que estas tres afirmaciones son equivalentes >>> Blog.objects.get(id__exact=14) # Forma Explicita >>> Blog.objects.get(id=14) # __exact esta implcito >>> Blog.objects.get(pk=14) # pk implica que es id__exact El uso de claves primarias pk no se limita a consultas __exact - cualquier trmino de consulta se puede combinar con ``pk` - para realizar una consulta en la clave principal de un modelo -: # Get blogs entries with id 1, 4 and 7 >>> Blog.objects.filter(pk__in=[1,4,7]) # Get all blog entries with id > 14 >>> Blog.objects.filter(pk__gt=14) Las bsquedas pk tambin trabajan a travs de uniones. Por ejemplo, estos tres declaraciones son equivalentes: >>> Entry.objects.filter(blog__id__exact=3) # Explicita forma El atajo de bsqueda pk pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Entry.objects.filter(blog__id=3) # __exact esta implcito >>> Entry.objects.filter(blog__pk=3) # __pk implica __id__exact Los patrones de bsqueda que equivalen a una declaracin SQL LIKE , (iexact, contains, icontains,startswith, istartswith, endswith y iendswith) automticamente escapan los dos caracteres especiales utilizados en las declaraciones LIKE - El signo de porcentaje y el guin bajo. (En una declaracin LIKE , el signo de porcentaje significa un comodn de varios caracteres y el guin bajo significa un comodn de un solo carcter.) Esto significa que las cosas deben trabajar de manera intuitiva, por lo que la abstraccin no se escapa. Por ejemplo, para recuperar todos los registros que contienen un signo de porcentaje, slo se tiene que utilizar el signo de porcentaje como cualquier otro carcter: >>> Entry.objects.filter(headline__contains='%') Django se encarga de escapar estos caracteres por nosotros; El cdigo SQL resultante tendr un aspecto parecido a este: SELECT ... WHERE headline LIKE '%\%%'; Lo mismo sucede con los guiones bajos. Los dos signos de porcentaje y guiones bajos son manejados de forma transparente. Cada QuerySet contiene un cach, para reducir al mnimo el acceso a la base de datos. Es importante entender cmo funciona, para escribir cdigo ms eficientemente. En un QuerySet recin creado , la cach esta vaca. La primera vez que el QuerySet es evaluado - Y por lo tanto la consulta ala base de datos sucede - Django guarda los resultados de la consulta en el cache delQuerySets y devuelve los resultados que han sido explcitamente solicitados (por ejemplo, el Escapando signos de porcentaje y guiones bajos en declaraciones LIKE Cacheando Consultas pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API elemento siguiente, sobre el que esta iterando el QuerySet) Las evaluaciones siguientes del QuerySet reusan los resultados de la cach. Ten en cuenta este comportamiento de la cach, porque puede morderte si no utilizas de manera correcta los QuerySets. Por ejemplo, el siguiente ejemplo crear dos QuerySets, los evaluara y los descartara: >>> print [e.headline for e in Entry.objects.all()] >>> print [e.pub_date for e in Entry.objects.all()] Eso significa que la misma consulta ala base de datos se ejecuta dos veces, duplicando la carga de la base de datos. Adems, existe la posibilidad de que las dos listas no puedan ser incluidas en los registros de la misma base, ya que una nueva entry puede haber sido aadida o eliminada, entre las dos peticiones. Para evitar este problema, simplemente guardamos el QuerySet y lo reutilizamos as: >>> queryset = Entry.objects.all() >>> print [p.headline for p in queryset] # Evaluate the query set. >>> print [p.pub_date for p in queryset] # Re-use the cache from the evaluation. Consultas de argumentos clave en mtodos filter(), etc. - son unidos a AND -. Si necesitamos ejecutar consultas ms complejas (por ejemplo, consultas con clausulas OR), podemos usar objetos Q. Un objeto Q (django.db.models.Q) es un objeto utilizado para encapsular una coleccin de argumentos de palabras clave. Estos argumentos de palabras clave se especifican en las consultas sobrepatrones de bsqueda. Por ejemplo, este objeto Q encapsula una nica consulta LIKE: from django.db.models import Q Bsquedas complejas con objetos Q pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Q(question__startswith='What') Los objetos Q pueden ser combinados con los operadores & and |. Cuando un operador es utilizado en dos objetos Q , se produce un nuevo objeto Q. Por ejemplo, esta declaracin produce un nico objeto Q que representa el OR de dos consultas"question__startswith": Q(question__startswith='Who') | Q(question__startswith='What') Esto es equivalente a la siguiente clusula SQL WHERE WHERE question LIKE 'Who%' OR question LIKE 'What%' Se pueden redactar declaraciones de complejidad arbitraria mediante la combinacin de objetos Q con los operadores & y | y el uso de la agrupacin entre parntesis. Adems, los objetos Q pueden ser anulados mediante el operador ~, lo que permite bsquedas combinadas que combinan una consulta normal y una negativa (NOT) Q(question__startswith='Who') | ~Q(pub_date__year=2005) Cada funcin de bsqueda que toma argumentos clave (Por ejemplo filter(), exclude(), get()) puede recibir uno o ms objetos Q como argumentos posicionales (sin nombre). Si proporcionamos mltiples argumentos de objetos Q a una funcin de bsqueda, los argumentos sern unidos con AND. Por ejemplo: Poll.objects.get( Q(question__startswith='Who'), Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)) ) ... se traduce aproximadamente en SQL SELECT * from polls WHERE question LIKE 'Who%' pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06') Las Funciones de bsqueda puede mezclar el uso de objetos y argumento de palabras clave Q. Todos los argumentos provistos a la funcin de bsqueda (sean estos argumentos de palabra clave u objetos Q) son unidos a AND. Sin embargo, si un objeto Q se proporciona, se debe preceder a la definicin de los argumentos de palabras clave. Por ejemplo: Poll.objects.get( Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)), question__startswith='Who') ... sera una consulta vlida, equivalente al ejemplo anterior, pero # INVALID QUERY Poll.objects.get( question__startswith='Who', Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))) ... no sera vlido. See also Las OR lookups examples pruebas unitarias de Django muestran algunos usos posibles de Q. Para comparar dos instancias de un modelo, slo tenemos que utilizar el operador estndar de comparacin de Python, el signo doble de igualdad: ==. detrs de escena compara la clave primaria de dos models. Usando el ejemplo anterior Entry las siguientes dos declaraciones son equivalentes: >>> some_entry == other_entry >>> some_entry.id == other_entry.id Comparando objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Si la clave primaria del modelo no es llamada id, no hay problema, las comparaciones utilizan siempre la clave principal siempre que son llamadas. Por ejemplo si una clave primaria de un campo de modelo es llamada name estas dos declaraciones son equivalentes: >>> some_obj == other_obj >>> some_obj.name == other_obj.name El mtodo para borrar, convenientemente, se llama delete(). Este mtodo elimina inmediatamente el objeto y no devuelve ningn valor. Ejemplo: e.delete() Tambin se pueden eliminar objetos de forma masiva. Cada QuerySet tiene un mtodo delete(), que elimina todos los miembros del QuerySet. Por ejemplo, esto elimina todos los objetos Entry con un campo pub_date de el ao 2005: Entry.objects.filter(pub_date__year=2005).delete() Devemos tener en cuenta que esto, es siempre posible, porque estamos ejecutando exclusivamente SQL, el mtodo delete() en instancias de objetos individuales no necesariamente sera llamado durante el proceso. Si se ha ha proporcionado un mtodo propio delete() en una clase del modelo y queremos asegurarnos de que se le llama, tendremos que hacerlo de forma Manual eliminando las instancias de ese modelo (por ejemplo, iterando sobre un QuerySet y llamando al mtodo delete() en cada objeto individualmente) en lugar de utilizar masivamente el mtodo delete() en un QuerySet. Cuando se elimina un objeto, por defecto Django emula el comportamiento SQL ON DELETE CASCADE - es decir, los objetos que tenan claves forneas o foreign keys que apunta al objeto que se desea borrar se elimina junto con ella. Por ejemplo: Borrando objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API b = Blog.objects.get(pk=1) # Esto borra el Blog y todos los objetos Entry. b.delete() New in Django 1.3: Este comportamiento de cascada es personalizable a travs del argumentoon_delete y el argumento ForeignKey. Ten en cuenta que el mtodo delete() es el nico mtodo QuerySet que no esta expuesto a una Manageren s mismo. Este es un mecanismo de seguridad para evitar que accidentalmente solicitandoEntry.objects.delete() borremos todas las entradas. Sin embargo si queremos borrar todas las entradas tenemos que solicitar explcitamente una consulta completa e invocar a el mtodo: Entry.objects.all().delete() Aunque no existe un mtodo integrado para la copia de instancias de modelo, es posible crear fcilmente nuevas instancia con los valores de todos los campos copiado. En el caso ms sencillo, basta con establecerpk a None. Usando nuestro ejemplo blog: blog = Blog(name='My blog', tagline='Blogging is easy') blog.save() # post.pk == 1 blog.pk = None blog.save() # post.pk == 2 Las cosas se complican ms si se utiliza la herencia. Consideremos una subclase de Blog class ThemeBlog(Blog): theme = models.CharField(max_length=200) django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme = 'python') django_blog.save() # django_blog.pk == 3 Copiando una instancia de un modelo pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Debido a cmo funciona la herencia, se tiene que especificar tanto pk e id a None: django_blog.pk = None django_blog.id = None django_blog.save() # django_blog.pk == 4 Este proceso no copia las relaciones entre objetos. Si deseas copiar las relaciones, tienes que escribir un poco ms cdigo. En nuestro ejemplo, Entry tiene un campo muchos a muchos relacionado a un campoauthor entry = Entry.objects.all()[0] # some previous entry old_authors = entry.authors.all() entry.pk = None entry.save() entry.authors = old_authors # saves new many2many relations Algunas veces lo que deseamos es establecer un valor en particular de un campo para todos los objetos de un QuerySet. Podemos hacer hacer esto con el mtodo update(). Por ejemplo: # Update all the headlines with pub_date in 2007. Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same') Lo nico que no podemos establecer es una relacin de campos ForeignKey utilizando este mtodo. Para actualizar un campo no-relacionado, proveemos el nuevo valor como una constante. Para actualizar un campo ForeignKey, establesemos el nuevo valor a la instancia del nuevo modelo al que deseamos apuntar. Por ejemplo: >>> b = Blog.objects.get(pk=1) # Cambiamos la entrada para que pertenesca al Blog. >>> Entry.objects.all().update(blog=b) Actualizando varios objetos a la vez pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API El mtodo update() se aplica inmediatamente y devuelve el nmero de filas que concuerdan con la consulta (que puede no ser igual al nmero de filas actualizadas si algunas filas ya tienen el nuevo valor). La nica restriccin en un QuerySet que se actualiza es que slo se puede acceder a una tabla de base de datos, la tabla principal del modelo. Podemos filtrar basados en la relacin de campos, pero slo se pueden actualizar columnas principales del modelo. Ejemplo: >>> b = Blog.objects.get(pk=1) # Actualiza todos los ttulos del blog. >>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same') Ten en cuenta que el mtodo update() es convertido directamente en una sentencia de SQL . Se trata de una operacin masiva de actualizaciones directas. No se ejecuta ningn mtodo save() en los modelos, o se emiten seales pre_save o un post_save (que son una consecuencia de la llamada save()), en honor de la opcin de campo auto_now.Si deseas guardar cada elemento en de un QuerySet deves asegurarte que el mtodo save() sea llamado en cada caso, No necesitas ninguna funcin especial para manejar esto. Slo un bucle que llame sobre cada uno de ellos y llame al mtodo save(): for item in my_queryset: item.save() Las llamadas a actualizar tambin pueden utilizar F() objects para actualizar un campo basndose en el valor de otro campo en el modelo. Esto es especialmente til para incrementar los contadores basados en los valores actuales. Por ejemplo, para incrementar el contador de pingbacks por cada entrada en el blog: >>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1) Sin embargo, a diferencia de los objetos F() en filtros y clusulas exclude, no podr introducir uniones al usar objetos F() en una actualizacin - slo se puede referenciar campos locales al modelo que se esta actualizando. Si deseas intentar introducir una unin con un objeto F(), un pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API error ``FieldError``sera lanzado: # THIS WILL RAISE A FieldError >>> Entry.objects.update(headline=F('blog__name')) Cuando se define una relacin en un modelo (es decir, un ForeignKey, OneToOneField, oManyToManyField), las instancias de ese modelo tendrn acceso a una conveniente API para acceder alas relaciones de los objeto(s). Utilizando el modelos que definimos en la parte superior de esta pgina, por ejemplo, un objeto e de unaEntry pueden ser asociado al objeto Blog accediendo al objeto blog mediante su atributo: e.blog. (Detrs de escena, esta funcionalidad se implementa mediante Python descriptors. Esto no es realmente importarte, lo sealamos aqu solo para los curiosos). Django tambin crea un acceso ala API para el otro lado de la relacin - el enlace de la relacin del modelo relacionado con el modelo que define la relacin -. Por ejemplo, un objeto b del Blog tiene acceso a una lista de todas las relaciones de objetos Entry mediante el atributo entry_set : b.entry_set.all(). Todos los ejemplos de esta seccin utilizan el mismo modelo Blog, Author y Entry que definimos en la parte superior de esta pgina. Si un modelo tiene una clase ForeignKey, las instancias de ese modelo tendr acceso a la relacin del objeto forneo a travs de un simple atributo del modelo. Ejemplo: Relaciones de objetos Relaciones One-to-many Adelante pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Ejemplo: >>> e = Entry.objects.get(id=2) >>> e.blog # Devuelve el objeto relacionado. Podemos obtener y asignar a travs de un atributo la clave fornea. Como se pueden esperar, los cambios en la clave fornea no se guardan en la base de datos hasta que se llama explcitamente al mtodo save(). Por ejemplo >>> e = Entry.objects.get(id=2) >>> e.blog = some_blog >>> e.save() Si una clase ForeignKey tiene un campo null=True (es decir, permite valores NULL), se le puede asignarNone como en este ejemplo: >>> e = Entry.objects.get(id=2) >>> e.blog = None >>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;" Para tener acceso a una relacin one-to-many esta debe ser cacheada la primera vez que el objeto relacionado sea accedido. Accesos posteriores a la clave fornea para la misma instancia del objeto estn almacenados en cach. Ejemplo: >>> e = Entry.objects.get(id=2) >>> print e.blog # Hits the database to retrieve the associated Blog. >>> print e.blog # Doesn't hit the database; uses cached versin. Nota que el mtodo del QuerySet select_related() recursivamente carga en la cache inmediatamente todos los objetos de relaciones uno-a-muchos de la instancia: >>> e = Entry.objects.select_related().get(id=2) >>> print e.blog # Doesn't hit the database; uses cached versin. >>> print e.blog # Doesn't hit the database; uses cached versin. pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Si un modelo tiene una ForeignKey, las instancias del modelo de clave fornea tendrn acceso a unManager que devuelve todas las instancias del primer modelo. Por defecto, este Manager es llamadoFOO_set, donde FOO es el nombre de origen del modelo, en minsculas. El Manager retorna QuerySets , que pueden ser filtrados y manipulados como se describe en la seccin recuperando objetos mas arriba. Ejemplo: >>> b = Blog.objects.get(id=1) >>> b.entry_set.all() # Returns all Entry objects related to Blog. # b.entry_set is a Manager that returns QuerySets. >>> b.entry_set.filter(headline__contains='Lennon') >>> b.entry_set.count() Podemos sustituir el nombre FOO_set cambiando la configuracin de los parmetros related_name en la definicin del ForeignKey() . Por ejemplo, si el modelo Entry fuera alterado ablog = ForeignKey(Blog, related_name='entries'), el cdigo de ejemplo anterior se vera as: >>> b = Blog.objects.get(id=1) >>> b.entries.all() # Returns all Entry objects related to Blog. # b.entries is a Manager that returns QuerySets. >>> b.entries.filter(headline__contains='Lennon') >>> b.entries.count() No se puede acceder a una relacin inversa ForeignKey Manager de la clase, sino que estos deben de tener acceso desde una instancia: >>> Blog.entry_set Traceback: ... AttributeError:"Manager debe acceder a travs de instancia". Adems de los mtodos QuerySet definidos anteriormente en Recuperacin de Siguiendo relaciones inversa pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API objetos ForeignKeyManager tienen mtodos adicionales que se utilizan para manejar un conjunto de objetos relacionados. Una sinopsis de cada uno es descrita mas abajo y se pueden obtener ms detalles enrelated objects reference. add(obj1, obj2, ...) Agrega los objetos del modelo especificados para el conjunto de objetos relacionados. create(**kwargs) Crea un nuevo objeto, lo guarda y lo coloca en el conjunto de objetos relacionados. Devuelve el objeto recin creado. remove(obj1, obj2, ...) Elimina los objetos del modelo especificado en el conjunto de objetos relacionados. clear() Elimina todos los objetos del conjunto de objetos relacionados. Para asignar los miembros de un conjunto relacionado de un solo golpe, podemos asignarle cualquier objeto iterable. El iterable puede contener instancias de objetos o simplemente una lista de valores de la clave principal. Por ejemplo: b = Blog.objects.get(id=1) b.entry_set = [e1, e2] En este ejemplo, e1 y e2 pueden tener instancias completas o valores enteros, de claves primarias. Si el mtodo clear() est definido, los objetos pre-existentes sern removidos de el entry_set antes que todos los objetos en el iterable (en este caso, una lista) se aade al conjunto. Si el mtodo clear() no esta disponible, todos los objetos en el iterable sern agregados sin ningn elemento existente . Cada operacin inversa descrita en esta seccin tiene un efecto inmediato en la base de datos. Cada adicin, creacin y eliminacin es inmediata y se guarda automticamente en la base de datos. pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Ambos extremos de las relaciones muchos a muchos,obtienen acceso automtico a la API. La API funciona igual que las relaciones inversas uno-a-muchos, descritas anteriormente. La nica diferencia est en el nombre del atributo: El modelo que define el ManyToManyField usa el nombre del atributo del campo en s mismo, mientras que el modelo inverso utiliza el nombre del modelo original en minsculas, adems de un sufijo '_set' (Justo en modo inverso a como lo hacen las relacin one-to-many). Un ejemplo lo hace ms fcil de entender: e = Entry.objects.get(id=3) e.authors.all() # Returns all Author objects for this Entry. e.authors.count() e.authors.filter(name__contains='John') a = Author.objects.get(id=5) a.entry_set.all() # Returns all Entry objects for this Author. Como ForeignKey, ManyToManyField se puede especificar un related_name. En el ejemplo anterior, si laManyToManyField en Entry se hubiera especificado related_name='entries' , entonces cada instancia deAuthor tendra un atributo entries en lugar de entry_set. La relaciones Uno-a-uno son muy parecidas alas relaciones many-to-one.Si definimos una OneToOneFielden nuestro modelo .Las instancias de este modelo tienen acceso al objeto relacionado a travs de un simple atributo del modelo. Por ejemplo: class EntryDetail(models.Model): entry = models.OneToOneField(Entry) details = models.TextField() Relaciones Many-to-many Relaciones One-to-one pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API ed = EntryDetail.objects.get(id=2) ed.entry # Returns the related Entry object. La diferencia est en las consultas inversas. El modelo relacionado en una relacin uno-a-uno tambin tiene acceso a un objeto Manager, pero el Manager representa un objeto nico, en lugar de una coleccin de objetos: e = Entry.objects.get(id=2) e.entrydetail # returns the related EntryDetail object Si ningn objeto ha sido asignado a la relacin, Django lanzara una excepcin DoesNotExist. Las instancias pueden ser asignados en relaciones inversas de la misma manera como asignaramos un relacin hacia adelante: e.entrydetail = ed Otros mapeadores objeto-relacional requieren que definamos las relaciones en ambos lados. Los desarrolladores de Django creen que esto es una violacin al principio DRY (no te repitas), as que Django slo requiere que se defina la relacin en un extremo. Pero, cmo es esto posible, dado que una clase modelo no sabe qu otras clases modelo estn relacionados con ella hasta que las clases de otros modelos se cargan? La respuesta est en los ajustes del archivo de configuracin INSTALLED_APPS . La primera vez que cualquier modelo se carga, Django itera sobre cada modelo en INSTALLED_APPS y crea las relaciones inversas en la memoria cuando sea necesario. Esencialmente, una de las funciones de INSTALLED_APPS es decirle a Django sobre todos los modelos del dominio que utiliza. Cmo son posibles las relaciones inversas? Consultas sobre relaciones de objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Las consultas que involucran relaciones de objetos siguen las mismas reglas que las consultas que implican los campos de valores normales. Al especificar el valor de una consulta que que coincide con una bsqueda, es posible que utilizemos cualquiera de las instancias del objeto en s, o el valor de la clave principal del el objeto. Por ejemplo, si tenemos un objeto Blog b con id=5, las siguientes tres consultas seran idnticas: Entry.objects.filter(blog=b) # Query using object instance Entry.objects.filter(blog=b.id) # Query using id from instance Entry.objects.filter(blog=5) # Query using id directly Si lo que necesitas para escribir una consulta SQL es demasiado complejo para el mapeador de la base de datos de Django, podemos escribir el SQL a mano. Django tiene un par de opciones para escribir consultas SQL , vase /topics/db/sql. Finalmente, es importante sealar que la capa de base de datos de Django es meramente una interfaz a la base de datos. Puedes acceder a ala base de datos a utilizando otras herramientas, lenguajes de programacin o frameworks de bases de datos, no hay nada especfico de Django sobre las base de datos. Publicado 28th November 2012 por Saul Garcia Etiquetas: base de datos, Django
Creando SQL Crudo
0 Aadir un comentario pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Para definir una relacion muchos a uno, utilizamos la clase ForeignKey. from django.db import models class Reporter(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField() def __unicode__(self): return u"%s %s" % (self.first_name, self.last_name) class Article(models.Model): headline = models.CharField(max_length=100) pub_date = models.DateField() reporter = models.ForeignKey(Reporter) def __unicode__(self): return self.headline class Meta: ordering = ('headline',) Estos ejemplos que siguen son operaciones que se pueden realizar usando la API interactiva que nos facilita python. Creamos algunos reporteros: >>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com') >>> r.save() 27 NOV Relaciones Many-to-one pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com') >>> r2.save() Creamos un artculo: >>> from datetime import datetime >>> a = Article(id=None, headline="This is a test", pub_date=datetime(2005, 7, 27), reporte r=r) >>> a.save() >>> a.reporter.id 1 >>> a.reporter <Reporter: John Smith> Los objetos artculo tienen acceso a sus objetos relacionados reportero: >>> r = a.reporter stas son cadenas en vez de las cadenas unicode, porque eso es lo que fue utilizada dentro la creacin de este reportero (y nosotros no hemos refrescado los datos de la base de datos, por lo que nos devuelve siempre las cadenas unicode): >>> r.first_name, r.last_name ('John', 'Smith') Creamos un artculo va el objeto reportero: >>> new_article = r.article_set.create(headline="John's second story", pub_date=datetime(20 05, 7, 29)) >>> new_article <Article: John's second story> >>> new_article.reporter <Reporter: John Smith> pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> new_article.reporter.id 1 Creamos un nuevo artculo y lo agregamos al artculo anterior: >>> new_article2 = Article(headline="Paul's story", pub_date=datetime(2006, 1, 17)) >>> r.article_set.add(new_article2) >>> new_article2.reporter <Reporter: John Smith> >>> new_article2.reporter.id 1 >>> r.article_set.all() [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] Agregamos el mismo artculo a un diferente artculo - comprobamos que se mueve -: >>> r2.article_set.add(new_article2) >>> new_article2.reporter.id 2 >>> new_article2.reporter <Reporter: Paul Jones> Si agregamos un objeto del tipo incorrecto django levanta una excepcin del tipo TypeError: >>> r.article_set.add(r2) Traceback (most recent call last): ... TypeError: 'Article' instance expected >>> r.article_set.all() [<Article: John's second story>, <Article: This is a test>] >>> r2.article_set.all() [<Article: Paul's story>] >>> r.article_set.count() 2 pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> r2.article_set.count() 1 Observamos que en el ejemplo anterior el artculo se ha movido desde John a Paul. El manejador de relaciones soporta las operaciones de bsqueda tambin en el campo. El API sigue automticamente las relaciones por lo que no se necesita, utilizar los guiones bajos para separar las relaciones.Esto trabaja tan profundamente en tantos niveles como queramos. No hay lmite. Por ejemplo: >>> r.article_set.filter(headline__startswith='This') [<Article: This is a test>] # Find all Articles for any Reporter whose first name is "John". >>> Article.objects.filter(reporter__first_name__exact='John') [<Article: John's second story>, <Article: This is a test>] El mismo caso esta implicado aqui: >>> Article.objects.filter(reporter__first_name='John') [<Article: John's second story>, <Article: This is a test>] Podemos hacer un query dos veces sobre el campo relacionado. Trasladamos la condicin AND y la clausula WHERE: >>> Article.objects.filter(reporter__first_name__exact='John', reporter__last_name__exact=' Smith') [<Article: John's second story>, <Article: This is a test>] Para las operaciones de relaciones y bsqueda podemos suministrar un valor primario o pasar el objeto relacionado explcitamente: >>> Article.objects.filter(reporter__pk=1) [<Article: John's second story>, <Article: This is a test>] >>> Article.objects.filter(reporter=1) [<Article: John's second story>, <Article: This is a test>] pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Article.objects.filter(reporter=r) [<Article: John's second story>, <Article: This is a test>] >>> Article.objects.filter(reporter__in=[1,2]).distinct() [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] >>> Article.objects.filter(reporter__in=[r,r2]).distinct() [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] Podemos utilizar un queryset en vez de una lista literal de instancias: >>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinc t() [<Article: John's second story>, <Article: This is a test>] Podemos hacer una consulta en la direccin opuesta: >>> Reporter.objects.filter(article__pk=1) [<Reporter: John Smith>] >>> Reporter.objects.filter(article=1) [<Reporter: John Smith>] >>> Reporter.objects.filter(article=a) [<Reporter: John Smith>] >>> Reporter.objects.filter(article__headline__startswith='This') [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>] >>> Reporter.objects.filter(article__headline__startswith='This').distinct() [<Reporter: John Smith>] El mtodo Counting trabaja en la direccin opuesta conjuntamente con el mtodo distinct(): >>> Reporter.objects.filter(article__headline__startswith='This').count() 3 >>> Reporter.objects.filter(article__headline__startswith='This').distinct().count() 1 Los Queries pueden trabajar en crculos: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Reporter.objects.filter (article__reporter__first_name__startswith='John') [<Reporter: Juan Smith>, <Reporter: Juan Smith>, <Reporter: Juan Smith>, <Reporter: >>> Rep orter.objects.filter (article__reporter__first_name__startswith='John').distinct de Juan Sm ith>] () [<Reporter: Juan Smith>] >>> Reporter.objects.filter (article__reporter__exact=r).distinct () [<Reporter: Juan Smith>] Si borramos un reportero, sus artculos sern borrados (asumiendo que el campo ForeignKey fue definido con el atributo django.db.models.ForeignKey.on_delete lo seteamos a ``CASCADE`, que es el que usa por defecto): >>> Article.objects.all() [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>] >>> Reporter.objects.order_by('first_name') [<Reporter: John Smith>, <Reporter: Paul Jones>] >>> r2.delete() >>> Article.objects.all() [<Article: John's second story>, <Article: This is a test>] >>> Reporter.objects.order_by('first_name') [<Reporter: John Smith>] Podemos borrar usando JOIN en un query: >>> Reporter.objects.filter(article__headline__startswith='This').delete() >>> Reporter.objects.all() [] >>> Article.objects.all() [] Publicado 27th November 2012 por Saul Garcia Etiquetas: base de datos, Django
pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API
0 Aadir un comentario Una vez que hayas creado tus data models Django automticamente proporciona a tu API de base de datos abstraccin que te permite crear, recuperar, actualizar y eliminar objetos. Este documento explica cmo utilizar esta API. Consulta la data model reference para una referencia completa y detallada de todos los modelos y las diversas opciones de bsqueda. A lo largo de esta gua (y en la de referencia), nos referiremos a los siguientes modelos, que incluyen una aplicacin web blog: class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def __unicode__(self): return self.name class Author(models.Model): name = models.CharField(max_length=50) email = models.EmailField() def __unicode__(self): return self.name class Entry(models.Model): 27 NOV Realizando consultas pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API blog = models.ForeignKey(Blog) headline = models.CharField(max_length=255) body_text = models.TextField() pub_date = models.DateTimeField() mod_date = models.DateTimeField() authors = models.ManyToManyField(Author) n_comments = models.IntegerField() n_pingbacks = models.IntegerField() rating = models.IntegerField() def __unicode__(self): return self.headline Para representar una tabla en una base de datos con objetos Python, Django utiliza un intuitivo sistema: Una clase de modelo representa una tabla de base de datos y una instancia de esta clase representa un registro en particular en la tabla de base de datos. Para crear un objeto, lo instanciamos utilizando argumentos clave a la clase del modelo, a continuacin, llamamos al mtodo save() para guardarlo en la base de datos. Importamos la clase del modelo del camino de bsqueda de Python o path, como se podra esperar. (Sealamos esto aqu porque en versiones anteriores de Django se requera importar el modelo de una forma no muy fina.) Suponiendo que nuestro modelo viva en el archivo mysite/blog/models.py, he aqu un ejemplo: >>> from blog.models import Blog >>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.') >>> b.save() Esto, detrs de escena, ejecuta una sentencia SQL INSERT. Django no accede a la base de datos hasta que explcitamente llamemos a el mtodo save(). Creando de objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API El mtodo save() no devuelve ningn valor. See also El mtodo save() contiene una serie de opciones avanzadas que no se describen aqu. Consulta la documentacin del mtodo save() para ms detalles. Para crear y guardar un objeto en un solo paso, utilizamos el mtodo create(). Para guardar los cambios realizados en un objeto que ya est en la base de datos, utilizamos el mtodosave(). Dado una instancia Blog que tiene un objeto b5 que ya se ha guardado en la base de datos, este ejemplo, cambia su nombre y actualiza su registro en la base de datos: >> b5.name = 'New name' >> b5.save() Detrs de escena, esto ejecuta una sentencia SQL UPDATE. Django no accede a la base de datos hasta que se llama explcitamente a el mtodo save(). La actualizacin de un campo ForeignKey funciona exactamente de la misma forma en que funciona guardar un campo normal - simplemente asignamos un objeto del tipo adecuado para el campo en cuestin . Este ejemplo actualiza blog y los atributos Entry con una instancia entry: >>> from blog.models import Entry >>> entry = Entry.objects.get(pk=1) >>> cheese_blog = Blog.objects.get(name="Cheddar Talk") >>> entry.blog = cheese_blog Grabando cambios en objetos Guardar un campo ForeignKey y ManyToManyField pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> entry.save() La actualizacin de un campo ManyToManyField funciona un poco diferente - utilizamos el mtodo add()en el campo para agregar un registro a la relacin. En este ejemplo agregamos a Author una instancia joedel objeto entry: >>> from blog.models import Author >>> joe = Author.objects.create(name="Joe") >>> entry.authors.add(joe) Para agregar varias grabaciones ManyToManyField en una sola llamada usamos el mtodo add() de esta forma: >>> john = Author.objects.create(name="John") >>> paul = Author.objects.create(name="Paul") >>> george = Author.objects.create(name="George") >>> ringo = Author.objects.create(name="Ringo") >>> entry.authors.add(john, paul, george, ringo) Django se quejar si se intenta asignar o aadir un objeto del tipo incorrecto. Para recuperar objetos de la base de datos, construimos un QuerySet o sea una consulta a travs de una clase Manager. Un QuerySet representa una coleccin de objetos a partir de la base de datos. Que pueden tener cero, uno o muchos filtros (filters) - criterios que pueden reducir la coleccin basndose en parmetros dados -. En trminos SQL, un QuerySet equivale a una declaracin SELECT y un filtro es una clusula de limitacinWHERE o LIMIT. Podemos traer un QuerySet usando el Manager de su modelo. Cada modelo tiene al menos uno Manager, y este es llamado objects por default. Podemos acceder a l directamente a travs de la Recuperando objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API clase del modelo, as >>> Blog.objects <django.db.models.manager.Manager object at ...> >>> b = Blog(name='Foo', tagline='Bar') >>> b.objects Traceback: ... AttributeError: "Manager isn't accessible via Blog instances." Note Los Managers son accesibles nicamente a travs de las clases del modelo, en vez que desde una instancia, para aplicar una separacin entre las operaciones a nivel de tabla y las operaciones A nivel de registro. El Manager es la principal fuente de QuerySets de un modelo. Acta como una clase raz de QuerySetque describe todos los objetos de la tabla de base de datos del modelo. Por ejemplo, Blog.objects es elQuerySet inicial que contiene todos los objetos Blog de la base de datos. La forma ms sencilla de recuperar objetos de una tabla es conseguir todos juntos de una vez. Para hacer esto, usamos el mtodo all() en un Manager as: >>> all_entries = Entry.objects.all() El mtodo all() devuelve un QuerySet de todos los objetos de la base de datos. (Si Entry.objects es una clase QuerySet, Por qu no podemos usar simplemente Entry.objects ? Esto es porque la clase raz Entry.objects , es un caso especial que no puede ser evaluado. El mtodo all()devuelve un QuerySet que puede ser evaluado). Recuperando todos los objetos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API La clase raz QuerySet proporcionada por el Manager describe todos los objetos de la base de datos. Por lo general, solo necesitaremos seleccionar un subconjunto del conjunto completo de objetos. Para crear un subconjunto, necesitamos refinar el QuerySet inicial agregando condiciones con filtros. Las dos formas ms comunes para refinar un QuerySet son: filter(**kwargs) Devuelve un nuevo QuerySet conteniendo los objetos que coinciden con los parmetros de bsqueda indicados. exclude(**kwargs) Devuelve un nuevo QuerySet conteniendo los objetos que que no coinciden con los parmetros de bsqueda indicados. Los parmetros de bsqueda (**kwargs en las definiciones de las funciones anteriores) debern estar en el formato descrito en las Bsquedas en campos mas abajo. Por ejemplo, para obtener un QuerySet de las entradas del blog desde el ao 2006, usamos el mtodofilter() as: Entry.objects.filter(pub_date__year=2006) No es necesario agregar un mtodo all() Entry.objects.all().filter(...) . Este mtodo funciona todava as, pero slo se necesita el all() cuando se quieran todos los objetos de la clase raz QuerySet. El resultado de refinar un QuerySet es en s mismo un QuerySet, as que es posible juntar y encadenar refinamientos. Por ejemplo: Recuperando objetos especficos mediante filtros Encadenando filtros pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Entry.objects.filter( ... headline__startswith='What' ... ).exclude( ... pub_date__gte=datetime.now() ... ).filter( ... pub_date__gte=datetime(2005, 1, 1) ... ) Tomamos el inicial QuerySet de todas las entradas de la base de datos, aadimos un filtro, luego una exclusin y a continuacin otro filtro. El resultado final es un QuerySet que contiene todas las entradas con un ttulo que empieza con What, que se publicaron entre 01 de enero del 2005 y el da actual. Cada vez que se modifica un QuerySet, se obtiene un nuevo QuerySet que no es de ninguna manera el anterior QuerySet. Cada refinamiento crea distintos y separados QuerySet que pueden ser almacenados, utilizados y reutilizados. Ejemplo >> q1 = Entry.objects.filter(headline__startswith="What") >> q2 = q1.exclude(pub_date__gte=datetime.now()) >> q3 = q1.filter(pub_date__gte=datetime.now()) Estos tres QuerySets son distintos entre si. El primer es un QuerySet que contiene todas las entradas que contengan un titulo que comienza con What. El segundo es un subconjunto del primero, con unos criterios adicionales que excluyen los registros cuyopub_date sea mayor que ahora. El tercero es un subconjunto de la primera, con un criterio adicional que selecciona slo los registros cuyopub_date sea mayor que ahora. El inicial QuerySet (q1) no se ve afectado por el refinamiento del proceso. Los QuerySets filtrados son nicos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Los QuerySets son perezosos - el acto de crear un QuerySet no involucra ninguna actividad en la base de datos. Se pueden aplicar filtros todo el da y Django no ejecutara las consultas hasta que el QuerySet seaEvaluado. Echa un vistazo a este ejemplo >>> q = Entry.objects.filter(headline__startswith="What") >>> q = q.filter(pub_date__lte=datetime.now()) >>> q = q.exclude(body_text__icontains="food") >>> print q Aunque en este ejemplos parezca que hemos echo tres consultas a la bases de datos, de hecho, solo llego una vez a la base de datos, en la ltima lnea en que llamamos a (print q). En general, los resultados de un QuerySet no se obtienen de la base de datos hasta que preguntamos por ellos. Cuando lo hacemos, elQuerySet es evaluado accediendo a la base de datos. Para ms detalles sobre como exactamente se lleva a cabo la evaluacin puedes ver when-querysets-are-evaluated. El mtodo filter() siempre retornara un QuerySet, aunque sea solo un objeto el que coincida con la consulta en este caso, ser un QuerySet que contiene un solo elemento . Si conocemos que hay un slo objeto que coincida con la consulta, se puede utilizar el el mtodo get() en un Manager para que devuelva el objeto directamente: >>> one_entry = Entry.objects.get(pk=1) Podemos utilizar cualquier expresin de consulta con el mtodo get(), al igual que con el mtodo filter()- de nuevo, puedes consultar la seccin Bsquedas en campos a continuacin. Ten en cuenta que existe una diferencia entre el uso del mtodo get() y el uso de el mtodo filter()cuando un slice retorna [0]. Si no hay resultados que coincidan con la consulta del mtodo, get() sera lanzada una excepcin DoesNotExist. Esta excepcin es un atributo de la clase del modelo que la consulta esta realizando - por lo que en el cdigo anterior, si no hay ningn Los QuerySets son perezosos Recuperando un solo objeto con get pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API objeto Entry con una clave primaria 1, Django levantar una excepcin Entry.DoesNotExist. Del mismo modo, Django se quejar si ms de un elemento coincide con la consulta del get() . En este caso, lanzara una excepcin MultipleObjectsReturned, que a su vez es un atributo de la clase del modelo en s mismo. La mayor parte de las veces usaremos el mtodo all(), get(), filter() y exclude() cuando necesitemos buscar objetos de la base de datos. Sin embargo, esto es solo una parte de la QuerySet API Reference para mas mtodos puedes obtener una lista completa de todos los mtodos QuerySet . Podemos utilizar la sintaxis de python array-slicing o rebanado de matrices para limitar un QuerySetcon un cierto nmero de resultados. Esta es el equivalente a las clausulas SQL LIMIT y a OFFSET. Por ejemplo, este devuelve los 5 primeros objetos (LIMIT 5): >>> Entry.objects.all()[:5] Esto devuelve los objetos del sexto al dcimo (OFFSET 5 LIMIT 5): >>> Entry.objects.all()[5:10] La Indexacin negativa (por ejemplo, Entry.objects.all()[-1] ) no esta permitida. Por lo general, rebanar QuerySet devuelve un nuevo QuerySet - Este no evala la consulta. Una excepcin es si se utilizamos los parmetro de la sintaxis de rebanado python. Por ejemplo, esto ejecutara la consulta para devolver una lista de cada dos objetos en los primeros 10: >>> Entry.objects.all()[:10:2] Otros mtodos de los QuerySet Limitando QuerySets pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Para recuperar un solo objeto en lugar de una lista (por ejemplo SELECT foo FROM bar LIMIT 1 ), utilizamos un simple ndice en lugar de una rebanada. Por ejemplo, esto retornara la primera entradaEntry de la base de datos, despus de ordenar las entradas en orden alfabtico por ttulo >>> Entry.objects.order_by('headline')[0] Esto es aproximadamente equivalente a: >>> Entry.objects.order_by('headline')[0:1].get() Nota, sin embargo, que el primero de estos lanzara un error IndexError mientras que el segundo lanzara un DoesNotExist si no hay objetos que coinciden con los criterios dados. Puedes ver el mtodo get() para ms detalles. Las bsquedas en los campos son la forma de especificar la carne a una clausula SQL WHERE. Estas consisten en argumentos clave tales como QuerySet, mtodos filter(), exclude() y get(). Los argumentos clave y parmetros bsicos que aceptan las bsquedas toman la formafield__lookuptype=value (Esto es un guin doble bajo). Por ejemplo: >>> Entry.objects.filter(pub_date__lte='2006-01-01') traducido(mas o menos) al comando SQL siguiente: SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01'; Como es esto posible? Python tiene la capacidad de definir las funciones que aceptan nombres y valores arbitrarios cuyos nombres, argumentos y valores se evalan en tiempos de ejecucin. Para obtener ms informacin, consulta la seccin Keyword Arguments en el tutorial oficial Bsquedas en campos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API de Python. Changed in Django 1.4: Please see the release notes El campo especificado en una bsqueda tiene que ser el nombre de un campo de un modelo. Sin embargo hay una excepcin, en caso de un ForeignKey se puede especificar el nombre del campo con el sufijo _id . En este caso, el parmetro de valor que se espera para contener el valor en bruto de la clave primaria del modelo ForeignKey . Por ejemplo: >>> Entry.objects.filter(blog_id__exact=4) Si se le pasa un argumento o una palabra clave no vlida, la funcin levantara una excepcin del tipo:TypeError. La API de base de datos admite unas dos docenas de tipos de bsqueda, una completa referencia se pueden encontrar en la field lookup reference. Para que te des una idea de las opciones disponibles, aqu estn algunas de las bsquedas ms comunes que probablemente utilizaras: exact Realiza una bsqueda exacta. Por ejemplo: >>> Entry.objects.get(headline__exact="Man bites dog") Lo cual generara un SQL con estas lneas: SELECT ... WHERE headline = 'Man bites dog'; Si no proporcionamos un tipo de bsqueda - es decir, si el argumento de la palabra clave no contiene el doble guin bajo - el tipo de bsqueda se asume que es exact. Por ejemplo, las dos sentencias siguientes son equivalentes: pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Blog.objects.get(id__exact=14) # De forma Explicita >>> Blog.objects.get(id=14) # __exact esta implcito Esto es conveniente, porque las bsquedas exact son las mas comunes. iexact Realiza bsquedas sin distinguir entre maysculas y minsculas. As, la consulta: >>> Blog.objects.get(name__iexact="beatles blog") La bsqueda coincidir con Beatles Blog, blog beatles, o incluso BeAtlES blOG. contains Realiza bsquedas distinguiendo maysculas y minsculas en cadenas. Por ejemplo: >>>Entry.objects.get(headline__contains='Lennon') Se podra traducir a SQL as: SELECT ... WHERE headline LIKE '%Lennon%'; Esto coincidir con el titulo 'Today Lennon honored' pero no con 'today lennon honored'. Tambin hay una versin que no distingue maysculas y minsculas, icontains. startswith endswith Realiza bsquedas que comienza con y terminan con, respectivamente. Tambin hay una versin que no distingue maysculas y minsculas llamada istartswith y iendswith. De nuevo, esto slo roza la superficie. Una referencia completa se puede encontrar en la field lookup reference. pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Django ofrece una forma potente e intuitiva para seguir las relaciones en las bsquedas, hacindose cargo de los JOINs de SQL de manera automtica. Detrs de escena. Para cruzar una relacin, slo se tiene que utilizar el nombre de campo de los campos relacionados a travs de modelos, separados por dos guiones bajos, hasta llegar al campo que se desee. En este ejemplo se recuperan todos los objetos Entry de el Blog cuyo nombre name sea 'Beatles Blog'de esta forma: >>>Entry.objects.filter(blog__name__exact='Beatles Blog') Esta expansin puede ser tan profunda como lo desees. Tambin funciona en forma inversa. Para hacer referencia a una relacin inversa, slo se tiene que utilizar en minsculas el nombre del modelo. En este ejemplo se recuperan todos los objetos Blog que tienen por lo menos una entrada Entry que contiene en el headline la palabra 'Lennon': >>>Blog.objects.filter(entry__headline__contains='Lennon') Si vamos a filtrar a travs de mltiples relaciones y uno de los intermediarios del modelos no tienen un valor que cumple la condicin del filtro, Django tratar esto como si hubiera un valor vaco (todos los valores son NULL), pero vlido, el objeto all. Todo esto significa que ningn error sera lanzado. Por ejemplo, en este filtro: Blog.objects.filter(entry__authors__name='Lennon') (Si haba un modelo relacionado Author ) y si no hay un author asociado con una entrada, sera tratado como si no tuviera un name adjunto, en lugar de generar un error debido a la falta de un author. Por lo general, esto es exactamente lo que queremos que suceda. El nico caso donde esto es confuso es que si estamos usando isnull As: Consultas Que Cruzan Relaciones pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Blog.objects.filter(entry__authors__name__isnull=True) Si queremos retornar los objetos del Blog que tienen un name de un author vaci y estos tambin tienen un author de una entry vaci. Si no queremos estos ltimos objetos, podemos usar: Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True) Cuando hayamos filtrado un objeto basado en una clase ManyToManyField o una inversa ForeignKey, hay dos diferentes tipos de filtros que te puede interesar, considerando la relacin Blog/Entry (Blog a Entry es una relacin uno-a-muchos). Podramos estar interesados en la bsqueda de blogs que tengan una entrada que tenga tanto Lennon en el ttulo y que fue publicado en 2008. O es posible que deseemos encontrar una entrada con Lennon en el ttulo, as como una entrada que se public en 2008. Puesto que hay varias entradas asociadas a un nico Blog, muchas de de estas consultas son posibles y tienen sentido en algunas situaciones. El mismo tipo de situacin se presenta con una relacin ManyToManyField. Por ejemplo, si una entradaEntry tiene un campo ManyToManyField llamado tags, si queremos encontrar entradas relacionadas con etiquetas llamadas msic y bands o si queremos posiblemente una entrada que contenga una etiqueta con el nombre de msica y con el estatus de pblic. Para hacer frente a estas dos situaciones, Django tiene una forma coherente de procesar mtodosexclude() y filter() . Todo dentro de un simple llamada al mtodo filter() la cual es aplicada simultneamente para filtrar los elementos que coinciden con todos esos requisitos. Sucesivamente la llamada a el mtodo filter() restringen el conjunto de los objetos, pero para las relaciones de varios valores, se aplica a cualquier objeto relacionado con el modelo principal, no necesariamente a aquellos objetos que fueron seleccionados por la primera llamada al mtodo filter(). Esto puede sonar un poco confuso, as que espero que este ejemplo lo aclarar. Al seleccionar todos los blogs que contienen entradas con ambos ttulos Lennon y que se publicaron en 2008 (la misma Abarcando varias relaciones multi-valor pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API entrada puede satisfacer ambas condiciones), podramos escribir: Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008) Para seleccionar todos los blogs que contienen una entrada con Lennon en el ttulo y una entrada que se public en 2008, escribiramos: Blog.objects.filter(entry__headline__contains='Lennon').filter( entry__pub_date__year=2008) En este segundo ejemplo, el primer filtro restringe el queryset a todos los blogs relacionados con ese tipo de entrada. El segundo filtro restringe el conjunto de blogs en respuesta a los que tambin se relacionan con el segundo tipo de entrada. Las entradas seleccionadas por el segundo filtro puede o no ser el mismo que las entradas en el primer filtro. Estamos filtrado de los objetos Blog con cada filtro que declaramos, no los elementos Entry. Todos estos comportamiento tambin se aplica a los exclude(): todas las condiciones de un nicoexclude() se aplican a un instancia nica (si estas condiciones estn hablando de los mismos valores de la relacin). Las condiciones subsecuentes filter() o exclude() las llamadas que se refieren a la misma relacin puede terminar el filtrado en diferentes objetos vinculados. Publicado 27th November 2012 por Saul Garcia Etiquetas: base de datos, Django
0 Aadir un comentario pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API La gua de temas sobre Djangos database-abstraction API describe las formas en que podemos usar las consultas en Django para crear, recuperar, actualizar y eliminar objetos individualmente. Sin embargo, a veces se tiene la necesidad de obtener valores derivados de una suma o una agregacion de una coleccin de objetos. Esta gua temtica describe las maneras en que los valores agregados se pueden generar y devolver usando consultas o querys en Django. A lo largo de esta gua, nos referiremos a los siguientes modelos. Estos modelos son utilizados para realizar el seguimiento del inventario de una serie de libreras en lnea: class Author(models.Model): name = models.CharField(max_length=100) age = models.IntegerField() friends = models.ManyToManyField('self', blank=True) class Publisher(models.Model): name = models.CharField(max_length=300) num_awards = models.IntegerField() class Book(models.Model): isbn = models.CharField(max_length=9) name = models.CharField(max_length=300) pages = models.IntegerField() price = models.DecimalField(max_digits=10, decimal_places=2) rating = models.FloatField() authors = models.ManyToManyField(Author) publisher = models.ForeignKey(Publisher) pubdate = models.DateField() class Store(models.Model): name = models.CharField(max_length=300) 27 NOV Agregacin pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API books = models.ManyToManyField(Book) En una apuracion? Esta es la forma mas comn de hacer consultas de agregados, asumiendo los modelos arriba mencionados: # Numero total de libros. >>> Book.objects.count() 2452 # El numero total de libros con un publisher=BaloneyPress >>> Book.objects.filter(publisher__name='BaloneyPress').count() 73 # Precio medio de los libros. >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} # Maximo precio de todos los libros. >>> from django.db.models import Max >>> Book.objects.all().aggregate(Max('price')) {'price__max': Decimal('81.20')} # Cada publisher, con un contador de libros con un atributo "num_books". >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')) >>> pubs [<Publisher BaloneyPress>, <Publisher SalamiPress>, ...] >>> pubs[0].num_books 73 # El top 5 de publishers, en orden de numero de libros. >>> from django.db.models import Count >>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5] Cheat Sheet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> pubs[0].num_books 1323 Django proporciona dos maneras de generar agregados. La primera manera es generar los valores sumarios sobre un QuerySet entero. Por ejemplo, digamos que queremos calcular el precio medio de todos los libros disponibles para la venta. Los querys en Django proporcionan una sintaxis para describir el conjunto de todos los libros: >>> Book.objects.all() Lo que necesitamos es una manera de calcular la suma del valor de los objetos que pertenecen a esteQuerySet. Esto lo hacemos aadiendo una clausula aggregate() a el QuerySet de esta forma: >>> from django.db.models import Avg >>> Book.objects.all().aggregate(Avg('price')) {'price__avg': 34.35} El metodo all() es redundante en este ejemplo, por lo se podra simplificar a: >>> Book.objects.aggregate(Avg('price')) {'price__avg': 34.35} El argumento para la clusula aggregate() describe el valor agregado que queremos calcular - en este caso, el promedio de los campos price en el modelo Book - . Una lista de las funciones agregadas est disponibles en la QuerySet reference. aggregate() es una clusula terminal para un QuerySet que, cuando se invoca, devuelve un diccionario de pares de nombre-valor. El nombre es un identificador para el valor agregado, el valor es la suma calculada. El nombre es generado automticamente a partir del nombre del campo y la funcin de agregado. Si se desea especificar manualmente un nombre para el valor agregado, puede hacerce proporcionando ese nombre cuando se especifica la clusula agregada: Agregados que generan ms de un QuerySet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Book.objects.aggregate(average_price=Avg('price')) {'average_price': 34.35} Si se desea generar ms de un agregado, solo devemos agregar otro argumento ala clusula aggregate(). Por lo tanto, si tambin queremos saber el precio mximo y mnimo de todos los libros, podramos emitir la consulta asi: >>> from django.db.models import Avg, Max, Min, Count >>> Book.objects.aggregate(Avg('price'), Max('price'), Min('price')) {'price__avg': 34.35, 'price__max': Decimal('81.20'), 'price__min': Decimal('12.99')} La segunda manera de generar sumas de valores es el de generar sumas independientes de cada objeto en un QuerySet. Por ejemplo, si vamos a recuperar una lista de libros, podriamos querer saber cuntos autores contribuyeron a cada libro. Cada libro tiene una relacin de muchos a muchos con el autor, si queremos resumir esta relacin para cada libro del QuerySet La suma de pre-objetos se pueden generar utilizando la clusula annotate(). Cuando una clusulaannotate() se especifica, cada objeto del QuerySet ser anotada con los valores especificados. La sintaxis de estas anotaciones es idntica a la utilizada por la clusula aggregate() . Cada argumento aannotate() describe un agregado que sera calculado. Por ejemplo, para anotar los libros por el nmero de autores podemos usar: # construye un queryset anotado >>> q = Book.objects.annotate(Count('authors')) # preguntamos por el primer objeto del queryset >>> q[0] <Book: The Definitive Guide to Django> >>> q[0].authors__count 2 # preguntamos por el segundo objeto del queryset Generacin de agregados para cada elemento de un QuerySet pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> q[1] <Book: Practical Django Projects> >>> q[1].authors__count 1 Al igual que con aggregate(), el nombre de la anotacin se deriva automticamente a partir del nombre de la funcin de agregado y el nombre del campo que se ha agregado. Se puede sustituir este nombre por defecto al proporcionar un alias cuando se especifique la anotacin: >>> q = Book.objects.annotate(num_authors=Count('authors')) >>> q[0].num_authors 2 >>> q[1].num_authors 1 Tal como aggregate(), annotate() no es una clusula terminal. La salida de la clusula annotate() es unQuerySet; este QuerySet puede ser modificado como cualquier otro QuerySet con operaciones, incluyendofilter(), order_by, o incluso con llamadas adicionales a annotate(). Hasta ahora, nos hemos ocupado de los agregados sobre los campos que pertenecen a los modelos que se est consultando. Sin embargo, a veces el valor que se desea agregar pertenecer a un modelo que tiene que ver con el modelo que se est consultando. Al especificar el campo para ser agregados en una funcin de agregado, Django nos permitir utilizar la mismo double underscore notation (doble guion bajo) que utiliza para referirse a los campos relacionados en filtros. Django manejara las uniones de las tablas que son requeridas y agregara el valor reacionado. Por ejemplo, para encontrar el rango de precios de los libros que se ofrecen en cada tienda, se puede utilizar la anotacin: Juntar y Agregar pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Store.objects.annotate(min_price=Min('books__price'), max_price=Max('books__price')) Esto le indica a Django que recupere el modelo Store, junto (a travs de la relacion muchos-a-muchos) con el modelo book, y agregue el precio de campo del modelo de libro para producir un valor mnimo y mximo. Las mismas reglas se aplican a clusula aggregate(). Si quisieramos saber el precio ms bajo y ms alto de todos los libros que estn disponibles para la venta en la tienda(Store), podramos utilizar elaggregate() siguiente: >>> Store.objects.aggregate(min_price=Min('books__price'), max_price=Max('books__price')) Juntar cadenas pueden ser tan profundo como sea necesario. Por ejemplo, para extraer la edad de la autora ms joven de todos los libros disponibles para la venta, se podra emitir la consulta: >>> Store.objects.aggregate(youngest_age=Min('books__authors__age')) Los agregados tambin pueden participar en filtros. Cualquier filter() (o exclude()) aplicado a los campos normales del modelo tendr el efecto de restringir los objetos que se consideran para la agregacin. Cuando se utilizan con un clusula annotate(), un filtro tiene el efecto de restringir los objetos para los que se calcula una anotacin. Por ejemplo, se puede generar una lista anotada de todos los libros que tienen un ttulo que empieza con Django utilizando la consulta: >>> Book.objects.filter(name__startswith="Django").annotate(num_authors=Count('authors')) Cuando se utiliza con una clusula aggregate(), un filtro tiene un efecto limitador de objetos sobre los cuales se calcula el agregado. Por ejemplo, se puede generar el precio medio de todos los libros con Agregaciones y otras clusulas de un QuerySet filter() y exclude() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API un ttulo que comience con Django utilizando la consulta: >>> Book.objects.filter(name__startswith="Django").aggregate(Avg('price')) Los valores anotados tambin se puede filtrar. Los alias de la anotacin puede ser utilizados en clausulasfilter() y exclude() de la misma manera que cualquier otro modelo de campo. Por ejemplo, para generar una lista de libros que tienen ms de un autor, podemos ejecutar la siguiente consulta: >>> Book.objects.annotate(num_authors=Count('authors')).filter(num_authors__gt=1) Esta consulta genera un conjunto de resultados anotados, a continuacin, genera un filtro basado en que la anotacin. Cuando se desarrolla una consulta compleja que involucra tanto una clusula annotate() si como unafilter(), se debe prestar especial atencin al orden en el que se aplican las clusulas del QuerySet. Cuando un clusula annotate() es aplicada a una consulta, la anotacin es calculada sobre el estado de la consulta hasta el punto en que la anotacin se solicita. La implicacin prctica de esto es que filter() yannotate() no son operaciones conmutativas - es decir, hay una diferencia entre la consulta -: >>> Publisher.objects.annotate(num_books=Count('book')).filter(book__rating__gt=3.0) y la consulta: >>> Publisher.objects.filter(book__rating__gt=3.0).annotate(num_books=Count('book')) Filtros o anotaciones Ordenar clausulas annotate() y filter() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Ambas consultas devolver una lista de editores que tienen por lo menos un buen libro (es decir, un libro con una calificacin superior a 3.0). Sin embargo, la anotacin en la primera consulta proporcionar el nmero total de todos los libros publicados por la editorial, la segunda consulta incluir solamente los buenos libros en el contador de la anotacin. En la primera consulta, la anotacin precede al filtro, por lo que el filtro no tiene efecto en la anotacin. En la segunda consulta, el filtro precede a la anotacin, y como resultado, el filtro restringe los objetos considerados cuando se hace la anotacin. Las anotaciones se pueden utilizar basicamenente para ordenar. Cuando se define una clausulaorder_by (), los agregados suministrados pueden hacer referencia a cualquier alias definido como parte de una clusula annotate() en la consulta. Por ejemplo, para ordenar un QuerySet de libros por el nmero de autores que han colaborado en el libro, se puede utilizar la siguiente consulta: >>> Book.objects.annotate(num_authors=Count('authors')).order_by('num_authors') Por lo general, las anotaciones se generan en funcin de cada objeto - una anotacion QuerySet devolver un resultado para cada objeto en el original QuerySet -. Sin embargo, cuando una clusula values() es utilizada para restringir las columnas que se devuelven en el conjunto de resultados, el mtodo de evaluacin de anotaciones es ligeramente diferente. En lugar de devolver un resultado anotado para cada resultado en el QuerySet, los resultados originales son agrupados de acuerdo con las combinaciones particulares de los campos especificados en la clusula values(). Una anotacin se proporciona entonces para cada grupo nico; la anotacin se calcula sobre todos los miembros del grupo. Por ejemplo, consideremos una consulta de un autor que intenta averiguar el promedio de valoracin de los libros escritos por cada autor: order_by() values() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> Author.objects.annotate(average_rating=Avg('book__rating')) Esto devolver un resultado por cada autor en la base de datos, con la anotacin, y su clasificacin promedio contable. Sin embargo, el resultado ser un poco diferente si se utiliza un clusula values(): >>> Author.objects.values('name').annotate(average_rating=Avg('book__rating')) En este ejemplo, los autores se agruparn por su nombre, por lo que se obtendr slo un resultado anotado para cada un Nombre nico autor. Esto significa que tenemos Dos autores con el mismo nombre, los resultados se fusionarn en una sola salida de consulta; el promedio se calcula como el promedio de los libros escritos por ambos autores. Al igual que con la clusula filter(), el orden en el cual las clausulas``annotate()`` y values() se aplican a una consulta es significativo. Si la clusula values() precede ala clausula annotate(), la anotacin ser calculada utilizando la agrupacin descrita por la clusula values(). Sin embargo, si la clusula annotate() precede a la clusula values(), las anotaciones se genera sobre el conjunto completo de la consulta. En este caso, la clusula values() slo limita los campos que se generan en la salida. Por ejemplo, si invertimos el orden de los valores de las clausulas values() y annotate() de nuestro ejemplo anterior: >>> Author.objects.annotate(average_rating=Avg('book__rating')).values('name', 'average_rat ing') Esto ahora producira un resultado nico para cada autor, sin embargo, slo el nombre del autor y la anotacin average_rating ser devuelto en los datos de salida. El order de clusulas annotate() y values() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Tambin debemos tener en cuenta que average_rating se ha incluido explcitamente en la lista de valores que se devuelven. Esto es necesario debido a la orden de los valores de las clusulas values() yannotate(). Si la clusula values() precede ala clusula annotate(), las anotaciones se aaden automticamente a la hoja de resultados. Sin embargo, si la clusula values() se aplica despus de la clusula annotate(), se debe explcitamente incluir la columna agregada. Los campos que se mencionan en el metodo order_by() por parte de un queryset (o que se utilizan en el orden predeterminado de un modelo) se usan cuando se selecciona los datos de salida, incluso si no se especifique otra cosa en la llamada a values(). Estos campos adicionales se utilizan para agrupar y juntar resultados similares entre s y que pueden tener otros resultados en filas idnticas, pero de un modo separado. Esto se manifiesta, en particular, al contar cosas. A modo de ejemplo, supongamos que se tiene un modelo como este: class Item(models.Model): name = models.CharField(max_length=10) data = models.IntegerField() class Meta: ordering = ["name"] La parte importante aqu es el orden predeterminado en el campo name. Si deseamos contar cuntas veces cada valor data distinto aparece, es posible que intentemos esto: # Advertencia: No del todo correcto! Item.objects.values("data").annotate(Count("id")) ... Que agrupar los objetos Item por su valor comn data y luego contara el nmero de valores id en cada grupo. Slo que no terminara de funcionar. El valor por defecto name tambin jugar un papel importante en la agrupacin, por lo que si queremos una consulta de grupos de pares de Interaccin con un orden predeterminado o order_by() pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API distintos(data, name) , que no es lo que queremos. En su lugar, devemos construir este queryset: Item.objects.values("data").annotate(Count("id")).order_by() ...limpiamos y ordenamos la consulta. Tambin podriamos ordenar, por decir, date sin ningn efecto perjudicial, puesto que ya est jugando un papel en la consulta. Este comportamiento es el mismo que se indica en la documentacin para el distinct() y la regla general es la misma: normalmente no querremos columnas extra que juegan un papel importante en el resultado, por lo que limpiar el orden, o al menos asegurarse de que se est restringiendo al menos esos campos que tambien son seleccionados en la llamada a values(). Note Es razonable preguntar por qu Django no elimina las columnas extraas por nosotros. La razn principal es por mantener la coherencia con distinc () y otros lugares: Django nuncaeliminara el orden de retriccion que hayamos especificado (y no podemos cambiar el comportamiento de los otros mtodos, ya que esto violara nuestro: /misc/api-stabilitypolicy). Tambin se puede generar un agregado en el resultado de una anotacin. Cuando definimos una clausulaaggregate(), los agregados suministrados pueden hacer referencia a cualquier alias definido como parte de una clusula annotate() de la consulta. Por ejemplo, si desea calcular el nmero promedio de autores por el conjunto de libros con el recuento autor, entonces el agregado que cuenta el autor, haciendo referencia al campo de anotaciones: >>> Book.objects.annotate(num_authors=Count('authors')).aggregate(Avg('num_authors')) {'num_authors__avg': 1.66} Publicado 27th November 2012 por Saul Garcia Agregacin de anotaciones pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Etiquetas: Django
0 Aadir un comentario Definir mtodos personalizados en un modelo para agregar funcionalidad a nivel de fila a los objetos. Considerando que el mtodo Manager est destinados a trabajar del lado de las tablas en toda las cosas, los mtodos de un modelo debe actuar en un caso de modelo en particular. Esta es una tcnica valiosa para mantener la lgica de negocio en un solo lugar - el modelo -. Por ejemplo, este modelo tiene un par de mtodos personalizados: class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() address = models.CharField(max_length=100) city = models.CharField(max_length=50) state = USStateField() # Yes, this is America-centric... def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime 27 NOV Mtodos de los modelos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API import datetime if datetime.date(1945, 8, 1) <= self.birth_date <= datetime.date(1964, 12, 31): return "Baby boomer" if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" return "Post-boomer" def is_midwestern(self): "Returns True if this person is from the Midwest." return self.state in ('IL', 'WI', 'MI', 'IN', 'OH', 'IA', 'MO') def _get_full_name(self): "Returns the person's full name." return '%s %s' % (self.first_name, self.last_name) full_name = property(_get_full_name) El ltimo mtodo en este ejemplo es una property. La referencia model instance reference contiene una lista completa de methods automatically given to each model. que puede ser sobrescritos la mayor parte de ellos puedes ver sobrescribiendo mtodos de un modelo mas adelante, pero hay un par de cosas que siempre querremos definir. __unicode__() Un mtodo mgico que devuelve una representacin unicode de cualquier objeto. Esto es lo que Python y Django usarn cada vez que una instancia de un modelo necesita ser coaccionada y se muestra como una simple cadena. En particular, esto ocurre cuando se muestra un objeto en una consola interactiva o en la interfaz de administracin. Siempre debemos definir este mtodo, el valor predeterminado no es muy til ni amigable. get_absolute_url() Esto le indica a Django cmo calcular la URL de un objeto. Django usa esto en su interfaz de administracin y en cualquier tiempo que necesita para encontrar una direccin URL de un objeto. Cualquier objeto que tenga una URL que identifica de forma exclusiva debe definir este mtodo. pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Hay otro conjunto de mtodos de un modelo que encapsulan un montn de comportamientos de la base de datos que tal vez quieras personalizar. En particular, a menudo se desea cambiar la forma en que elsave() y delete() trabajan. Eres libre para reemplazar estos mtodos (y cualquier otro mtodo de algn modelo) para alterar su comportamiento. Un clsico uso de estos casos puede ser para reemplazar algunos mtodos integrados, es decir que si quieres que algo suceda cada vez que guardas un objeto. Por ejemplo (save() para documentarte sobre los parmetros que acepta) Puedes usar: class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): do_something() super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. do_something_else() O puedes prevenir que algo se guarde: class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): if self.name == "Yoko Ono's blog": return # Yoko shall never have her own blog! else: super(Blog, self).save(*args, **kwargs) # Call the "real" save() method. Sobreescribiendo mtodos predefinidos de un modelo pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Es importante recordar que devemos llamar al mtodo de la superclasesuper(Blog, self).save(*args, **kwargs) - para asegurarse de que el objeto se guardo en la base de datos. Si se te olvida llamar al mtodo de la superclase, el comportamiento predeterminado no va a suceder y la base de datos no se tocara. Tambin es importante que se pasen los argumentos a travs de los mtodos del modelo - que es lo que los *args, **kwargs hacen, Django de vez en cuando, amplia las capacidades de los mtodos de los modelos incorporados, agregando nuevos argumentos. Si utilizamos *args, **kwargs en las definiciones de los mtodo, garantizamos que el cdigo pueda automticamente dar soporte a los argumentos cuando estos sean agregados. Los mtodos reemplazados en un modelo no se llaman en operaciones masivas. Tenga en cuenta que el mtodo delete() de un objeto no se llama necesariamente al eliminar objetos de forma masiva utilizando un QuerySet. Para asegurarse de borrar de una forma lgica y personalizada ejecutamos las seales pre_delete y/o post_delete. Desafortunadamente, no hay una solucin al usar creating o updating en los objetos cuando se llaman de forma masiva, ya que ninguno de los metodos save(), pre_save ypost_save emite seales hasta que son llamados. Otro patrn comn es escribir sentencias SQL personalizadas en los mtodos del modelo y los mtodos a nivel de mdulo. Para obtener ms informacin sobre el uso crudo de SQL, consulte la documentacinusing raw SQL. La herencia de modelos en Django funciona de forma idntica a la herencia de clases normales en Python. La nica decisin que se tiene que tomar es si se desea que los modelos padres tengan sus modelos propios (con sus propias tablas de la base de datos), o si los modelos padres puedan Ejecutando SQL personalizado Herencia de Modelos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API contener informacin comn que slo ser visible a travs de los modelos hijos. Hay tres estilos de herencia posibles en Django. 1. A menudo, usted slo tendr que usar la clase padre para contener la informacin que no quiere escribir para cada modelo hijo. Esta clase no se va a utilizar nunca de forma aislada, por lo que lasabstract-base-classes son las que usted est buscando. 2. Si es una subclase de un modelo existente (tal vez algo de otra aplicacin completamente) y desea que cada modelo tenga su tabla de base de datos propia, multi-herencia multi-table- inheritance es el camino a seguir. 3. Por ltimo, si slo se desea modificar el comportamiento Python a nivel de un modelo, sin necesidad de ninguna manera cambiar los modelos de los campos, puede utilizar los Modelos proxy. Las clases base abstractas son tiles cuando se quiere poner alguna informacin comn en otros modelos. Se puede escribir la clase base con el argumento abstract=True en la clase Meta. Este modelo no podr entonces ser usado para crear cualquier tabla de base de datos. En cambio, cuando se utiliza como una clase base para otros modelos, sus campos se aaden a los de la clase hija. Es un error tener campos de la clase base abstracta con el mismo nombre que los del hijo (y Django lanzar una excepcin). Un ejemplo: class InfoComun(models.Model): nombre = models.CharField(max_length=100) edad = models.PositiveIntegerField() class Meta: abstract = True class Estudiante(InfoComun): grupo = models.CharField(max_length=5) Las clases base abstractas pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API El modelo Estudiante tendr tres campos : nombre, edad y grupo. El modelo InfoComun no puede ser utilizado como un modelo normal de Django, ya que es una clase base abstracta. No genera una tabla de base de datos o un manager y no puede ser instanciado o guardar directamente. Para muchos usos, este tipo de herencia de modelos ser exactamente lo que quieres. Proporciona una manera de factorizar informacin comn a nivel Python, aunque slo sea la creacin de una tabla de base de datos para un modelo hijo a nivel de base de datos. Cuando una clase base abstracta se crea, hace que cualquier clase interna Meta que se declar en la clase base este disponible como un atributo. Si una clase hija no se declara con su propia clase Meta, heredar de la clase padre las opciones Meta. Si el modelo hijo quiere extender la clase Meta padre, necesita una subclase. Por ejemplo: class InfoComun(models.Model): ... class Meta: abstract = True ordering = ['nombre'] class Estudiante(InfoComun): ... class Meta(InfoComun.Meta): db_table = 'estudiantes_info' Django hace que un ajuste en una clase Meta en una clase abstracta base Meta antes de instalar los atributos Meta, este sea abstract=False . Esto significa que las clases hijos de las clases base abstractas no se convierten automticamente en clases abstractas en s mismos. Por supuesto, usted puede hacer que una clase base abstracta que herede de otra clase base abstracta. Slo tiene que recordar establecer explcitamente abstract=True en cada ocasin. Herencia Meta pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Algunos atributos no tiene sentido incluir en la clase Meta de una clase base abstracta. Por ejemplo, incluirdb_table significara que todas las clases secundarias (las que no especifiquen su propia Meta ) utilizaran la misma tabla de la base de datos, lo cual es casi seguro que no es lo que quieres. Si ests utilizando un atributo related_name en un ForeignKey o en ManyToManyField, siempre debes especificar un nombre nico para el nombre del campo contrario. Normalmente, esto causa un problema en las clases base abstractas, ya que los campos de esta clase se incluyen en cada una de las clases secundarias, con exactamente los mismos valores para los atributos (incluyendo related_name ) cada vez. Changed in Django 1.2: Please see the release notes Para evitar este problema, cuando se utiliza related_name en una clase base abstracta (nicamente), es que parte del nombre debe contener '%(app_label)s' y '%(class)s'. '%(class)s' es remplazado por el nombre en minsculas de la clase hijo que el campo esta utilizando. '%(app_label)s' es remplazado por el nombre en minsculas de la aplicacin en que est contenida la clase hija. El nombre de cada aplicacin instalada debe ser nico y los nombres de las clases del modelo dentro de cada aplicacin tambin debe ser nicas, por lo que el nombre resultante va a terminar siendo diferente. Por ejemplo, dada una aplicacin common/models.py: class Base(models.Model): m2m = models.ManyToManyField(OtherModel, related_name="%(app_label)s_%(class)s_related" ) class Meta: abstract = True class ChildA(Base): Ten cuidado con related_name pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API pass class ChildB(Base): pass Junto con otra aplicacin rare/models.py: from common.models import Base class ChildB(Base): pass El nombre inverso del campo common.ChildA.m2m sera common_childa_related mientras que el nombre inverso del nombre del campo common.ChildB.m2m sera common_childb_related y finalmente el nombre inverso de el campo rare.ChildB.m2m sera rare_childb_related. Depende de cmo se utilize el'%(class)s' y '%(app_label)s en parte para construir su nombre relacionado, pero si usted se olvida de usarlo, Django generara errores al validar sus modelos (o al ejecutar syncdb). Si no se especifica un atributo related_name para un campo de una clase base abstracta, la inversa de nombres por defecto ser el nombre de la clase hija seguido de '_set', tal y como normalmente sera si se hubiera declarado el campo directamente en la clase hija. Por ejemplo, en el cdigo anterior, si el atributorelated_name el atributo se omite, el nombre inverso para el campo m2m sera para el childa_setchildb_set y en el caso de ChildA el childb_set sera ChildB para el campo. El segundo tipo de modelo de herencia soportado por Django es cuando cada modelo de la jerarqua es un modelo de s mismo. Cada modelo corresponde con sus propias tablas de base de datos y se puede consultar y crear individualmente. La relacin de herencia presenta vnculos entre el modelo hijo y cada uno de sus padres (a travs de una creada automticamente OneToOneField) Por ejemplo: Herencias Multi-tabla pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) class Restaurant(Place): serves_hot_dogs = models.BooleanField() serves_pizza = models.BooleanField() Todos los campos del objeto Place tambin estarn disponibles en el objeto Restaurant, a pesar de que los datos residen en una tabla de base de datos diferente. As que estas relaciones son posibles: >>> Place.objects.filter(name="Bob's Cafe") >>> Restaurant.objects.filter(name="Bob's Cafe") Si tenemos un objeto Place que sea tambin un objetoRestaurant ``, podemos traer los los objetos desde el ``Place a los objetos ``Restaurant `` utilizando la versin en minsculas del nombre del modelo: >>> p = Place.objects.get(id=12) # Si p es un objeto Restaurant, podemos traer las clase hijas: >>> p.restaurant <Restaurant: ...> Sin embargo, si p en el ejemplo anterior no era un objetoRestaurant `` (que haba sido creado directamente como un objeto ``Place o era el padre de alguna otra clase), refirindose a p.restaurant lanzara una excepcin Restaurant.DoesNotExist En situaciones de herencia multi-tabla, no tiene sentido que una clase hija herede de su padre una clase Meta. Todas los opciones Meta ya han sido aplicados a la clase padre y aplicarlas de nuevo normalmente slo conducen a un comportamiento contradictorio (lo que contrasta con el caso de la clase base abstracta, donde la clase base no existe por derecho propio). As, un modelo hijo no tiene acceso a las clases Meta de su su padre. Sin embargo, hay unos pocos Herencia Multitabla y Meta pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API As, un modelo hijo no tiene acceso a las clases Meta de su su padre. Sin embargo, hay unos pocos casos limitados en que el hijo hereda el comportamiento de los padres: si el hijo no especifica un ordering o un atributo get_latest_by , heredar estos de su padre. Si el modelo padre tiene un orden y no queremos usarlo en el modelo, se puede inhabilitar explcitamente as: class ChildModel(ParentModel): ... class Meta: # Remove parent's ordering effect ordering = [] Debido a la herencia multi-tabla que utiliza un campo implcito OneToOneField para vincular el hijo y el padre, es posible moverse del padre al hijo hacia abajo, como en el ejemplo anterior. Sin embargo, se usa el nombre que es el valor predeterminado para related_name para las relaciones ForeignKey yManyToManyField. Si se va a colocar ese tipo de relaciones en una subclase de otro modelo, se debeespecificar el atributo related_name en cada campo como tal. Si se olvida colocarlo, Django generar un error al ejecutar validate o syncdb. Por ejemplo, utilizando la clase anterior Place otra vez, vamos a crear otra subclase con un campoManyToManyField: class Supplier(Place): # Se debe especificar el nombre de la relacin en todas las relaciones. castores = models.ManyToManyField(Restaurant, related_name='provider') Como se ha mencionado anteriormente, Django crea automticamente una vinculacin OneToOneField a la clase hija de cualquier de los modelos padres no abstractos. Si se desea controlar el nombre del atributo que une de nuevo al padre, se puede crear un campo propio OneToOneField y colocar parent_link=Truepara indicar que el campo es el enlace a la clase Herencia y relaciones inversas Especificar el campo de enlace padre pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API padre. Cuando se utiliza multi-table inheritance , una nueva tabla de base de datos se crea, por cada subclase de un modelo. Este suele ser el comportamiento deseado, ya que la subclases necesitan un lugar para almacenar los campos de datos adicionales que no estn presentes en la clase base. A veces, sin embargo, slo se quiere cambiar el comportamiento de un modelo Python - tal vez para cambiar el manager por defecto o aadir un nuevo mtodo. Esto es lo que la herencia de modelo proxy hace: crea un proxy para que el modelo original. Puede crear, borrar y actualizar las instancias del modelo de proxy y todos los datos se guardarn como si se estuviera usando el modelo original (no-proxy). La diferencia es que se pueden cambiar cosas como el ordenamiento del modelo predeterminado o el gestor por defecto en el proxy, sin tener que alterar el original. Los modelos proxy se declaran como los modelos normales. Le decimos a Django que es un modelo proxy mediante el establecimiento del atributo Meta de la clase a True. Por ejemplo, supongamos que queremos agregar un mtodo a un User estndar en un modelo usado en las plantillas. Podemos hacerlo as: from django.contrib.auth.models import User class MyUser(User): class Meta: proxy = True def do_something(self): La clase MyUser funciona de igual manera en la misma tabla de base de datos que su padre la clase User. Particularmente, cualquier nueva instancia de User ser accesible con MyUser, y viceversa: Modelos proxy pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API >>> u = User.objects.create(username="foobar") >>> MyUser.objects.get(username="foobar") <MyUser: foobar> Tambin es posible usar un modelo proxy para definir un valor de ordenamiento predeterminado diferente de un modelo. La clase normal del modelo User no tiene definido en el mismo (intencionalmente; la clasificacin es costosa y no queremos hacerlo todo el tiempo cuando traemos usuarios). Es posible que deseemos ordenar regularmente por el nombre del atributo del username cuando se utiliza el proxy. Esto es fcil: class OrderedUser(User): class Meta: ordering = ["username"] proxy = True Ahora una consulta a User puede ser desordenada y OrderedUser y los querys sern ordenados porusername. No hay una manera de retornar en Django, por decir, un objeto MyUser cada vez que se consulta el query de un objeto User. Un queryset para los objetos User devolver este tipo de objetos. El punto central de objetos proxy es que el cdigo se basa en el cdigo original del objeto User y puede utilizar las extensiones que se incluyen en el (que no se incluyen en cualquier otro caso). Esta no es una forma de reemplazar a un objeto User (o cualquier otra parte) del modelo con algo de su propia creacin. Un modelo de representacin deber heredar exactamente una clase modelo no abstracta. No puede heredar de mltiples modelos no abstractos como el modelo proxy, no proporciona ninguna conexin entre las filas de las tablas de bases de datos diferentes. Un modelo proxy se puede heredar de cualquier nmero de clases del modelo abstracto, siempre que se no define ninguno de sus campos del modelo. QuerySets que devuelven el modelo que fue pedido Restricciones en una clase base pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API Los modelos proxy heredan cualquier opcin Meta que no se defina en su modelo padre no-abstracto (el modelo proxy). Si no se especifica un manager en un modelo proxy, este hereda los managers de los modelos padre. Si se define un manager en el modelo proxy, se convertir en el valor predeterminado, a pesar de que se haya definido en la clase padre seguirn estando disponibles. Continuando con nuestro ejemplo anterior, se puede cambiar el manager predeterminado que se utiliza cuando se consulta el modelo User de la siguiente manera: class NewManager(models.Manager): ... class MyUser(User): objects = NewManager() class Meta: proxy = True Si se desea agregar un nuevo manager para el Proxy, sin tener que reemplazar el valor predeterminado existente, pueden utilizarse las tcnicas descritas en la custom manager y crear una clase base que contiene los nuevos managers y los que hereda de la clase base primaria: # Creamos una clase abstracta para el nuevo manager. class ExtraManagers(models.Model): secondary = NewManager() class Meta: abstract = True class MyUser(User, ExtraManagers): class Meta: Managers en modelos proxy pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API proxy = True Sin embargo no necesitaremos probablemente hacer esto muy a menudo, pero cuando esto se necesite, es posible. La herencia de un modelo proxy puede tener un aspecto bastante similar a la creacin de un modelo no manejado, usando managed y los atributos de una clase Meta de un modelo . Las dos alternativas no son exactamente lo mismo y vale la pena considerar cul se debe usar. Una diferencia es que se puede (y de hecho se debe a menos que queramos tener un modelo vaco) especificar los campos del modelo en los modelos con Meta.managed=False. Con esto podemos, ajustar cuidadosamente el atributo Meta.db_table al crear un modelo unmanaged que sombre un modelo existente y agregar los mtodos python en l. Sin embargo, eso sera muy repetitivo y frgil para mantener ambas copias sincronizadas si realizamos cualquier cambio en ellas. La otra diferencia ms importante para los modelos proxy, es cmo los managers de un modelo se manejan. Los modelos de proxy se comportan exactamente igual que los modelos no manejado. As que heredan los managers de el modelo de los padres, incluyendo el gestor por defecto. En lo normal de los casos en la herencia multi-tabla, los hijos no heredan los managers de sus padres, los managerspersonalizados no son siempre apropiados cuando los campos adicionales estn involucrados. La documentacin de manager documentation tiene ms informacin acerca de este ltimo caso. Cuando estas dos funciones fueron implementadas, se hicieron intentos para acoplarlos en una sola opcin. Result que las interacciones con la herencia, en general, y los managers, en particularmente hicieron la API muy complicada y potencialmente difcil de entender y utilizar. Result que se necesitan dos opciones en cualquier caso, por lo que surgi la actual separacin. Por lo tanto, las reglas generales son: 1. Si va a reflejar un modelo existente o una tabla de base de datos y no se desea que todas las Las diferencias entre la herencia proxy y los modelos no manejados pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API columnas originales de la tabla de base de datos, utilice Meta.managed=False. Esta opcin suele ser til para modelar vistas de bases de datos y tablas que no estn bajo el control de Django. 2. Si ests interesado en cambiar el comportamiento de un modelo python, pero quieres mantener todos los mismos campos que en el original, deves utilizar Meta.proxy=True. Esto pone las cosas de modo que el modelo proxy sea una copia exacta de la estructura de almacenamiento del modelo original cuando se guardan los datos. Al igual que con la subclasificacin de Python, es posible que un modelo Django herede de sus mltiples modelos padre. Tenga en cuenta que las reglas normales de Python en la resolucin de nombres se aplican. La primera clase base que aparece en un nombre en particular (por ejemplo Meta) ser el que se utiliza, por ejemplo, esto significa que si los padres contienen mltiples clases Meta, slo el primero se va a utilizar y todos los dems sern ignorados. En general, usted no tendr que heredan de mltiples padrea. El uso principal de los casos donde esto es til es en las clases mix-in la adicin de un campo en particular o un mtodo adicional para cada clase que herede el mix-in. Trate de mantener las jerarquas de herencia tan sencillas y directas como sea posible para que usted no tenga que calcular dnde se encuentra y de donde proviene una determinada pieza de informacin. En la herencia normal de clases Python, est permitido que una clase hija pueda anular cualquier atributo de la clase padre. En Django, esto no est permitido para las instancias de los los atributos Field (al menos, no por el momento). Si una clase base tiene un campo llamado author no se puede crear otro modelo con un campo author de cualquier clase que hereda de la clase base. Sobrescribir los campos de un modelo padre conduce a dificultades en reas como la inicializacin de nuevas instancias (especificando qu campo se esta inicializando con Model.__init__ ) y la serializacin. Estas son las caractersticas que la herencia normal de clase Python no tiene que tratar Herencia mltiple Nombres de campos hiding no estn permitidos pdfcrowd.com open in browser PRO version Are you a developer? Try out the HTML to PDF API en la misma manera, por lo que la diferencia entre la herencia de un modelo de Django y las herencias de clases de Python no es arbitraria. Esta restriccin slo se aplica a los atributos que estn sobre la instancia Field, Los atributos normales python se pueden modificar si se desea. Adems, slo se aplica al nombre del atributo como Python lo ve: si va a especificar manualmente el nombre de la columna de base de datos, usted puede tener el mismo nombre de columna que aparece tanto en el hijo y el modelo ancestro de la herencia multi-tabla (que son las columnas en dos tablas de bases de datos diferentes). Django levantar una exepcion FieldError si se invalida cualquier campo de un modelo en cualquier modelo ancestro. Publicado 27th November 2012 por Saul Garcia Etiquetas: base de datos, Django