[pyar] New-only fields para ForeignKeys en Django admin?

Maximiliano Bertacchini maxiberta en gmail.com
Jue Feb 24 11:56:34 ART 2011


On 21/02/11 02:18, Federico Heinz wrote:
> Enamorado como estoy con el admin app de Django, me he encontrado con
> que le falta un feature que sería muy útil: relaciones en las que,
> una vez dadas de alta, no se puedan cambiar los extremos.
>
> Para ilustrar de lo que estoy hablando, que creo que es un use
> case bastante común, adjunto un zip con un femto-proyecto de juguete,
> llamado "pajarones". Tiene dos tablas: una de especies, y una de
> colores, y hay una relación de muchos a muchos entre ellas, la idea
> es que uno puede decir en ella cuáles especies de pájaros tienen
> cuáles colores, y al revés.
>
> Si arrancan el proyecto y van a la URL
>
> <http://localhost:8000/admin/pajarones/species/2/>
>
> Van a ver (ilustrando mi ignorancia en ornitología), que los
> guacamayos pueden ser rojos o azules, y verán tres renglones "vacíos"
> en la lista de colores, por si quiero agregar más colores posibles
> del guacamayo.
>
> Esto está bueno, pero:
>    * en realidad, es raro que yo quiera cambiar el color que figura en
>      una relación existente. Más cercano a la semántica de la cosa, es
>      que, si me equivoqué relacionando el marrón con el guacamayo,
>      borre la relación y no le cambie el destino.
>    * desde acá puedo ver todos los colores posibles del guacamayo,
>      pero si quiero ir a la página de ese color, para ver o corregir
>      su información, no tengo una manera de hacerlo directamente.
>
> Sería mejor si el admin usara un<select>  para ese campo sólo en los
> renglones reservados para nuevas relaciones. En las relaciones ya
> existentes, debería mostrar simplemente el __unicode__() del objeto
> relacionado, hipervinculado con la página de admin que edita el
> objeto.
>
> Jugando un rato, armé un custom widget que hace una parte de esto: en
> admin.py está el widget NewOnlySelect, que muestra distintas cosas
> dependiendo de si le asignan un valor o no:
>    * si no tiene valor, muestra un<select>, tal como antes para que
>      el usuario pueda dar de alta una relación
>    * si tiene valor, lo mete en un<input type="hidden">,
>      y muestra el texto asociado a la selección
>
> Lo pueden ver en acción si, en vez de ver qué colores tienen los
> guacamayos, se fijan cuáles especies tienen color rojo
> <http://localhost:8000/admin/pajarones/color/2/>
>
> El problema es que me parece que esta técnica no promete mucho más
> que esto, porque hay dos cosas que no puede hacer en el caso en el
> que tiene un valor:
>    1. eliminar el signo "+" en verde al lado del texto, que permite
>       dar de alta un objeto en la otra tabla. Ese botón está bueno al
>       lado del<select>, pero sin el<select>  no tiene sentido
>    2. hacer que el texto "Loro" sea un link a la página de admin del
>       loro, y que "Guacamayo" haga lo propio con el guacamayo. Para
>       eso tendría que construir una URL del tipo
>           "http://localhost:8000/admin/pajarones/<clase>/<id>/"
>       y si bien el widget sabe cuál es el id (es el valor que le
>       asignaron), no tiene idea de cuál es la clase (bueno, en este
>       caso sí podríamos hardcodearlo, pero no sirve para el caso
>       general).
>
> Se me ocurre que puede haber alguna punta por el lado de usar un form
> customizado que use un formfield especial para los foreign keys...
> pero no ví nada que sirva para cambiar el formfield que se usa para
> "todos los campos de tal tipo", sólo para "tal y cual campo". En
> síntesis... BUMP.
>
> ¿Alguna sugerencia?
>
> 	Fede
> _______________________________________________
> pyar mailing list pyar en python.org.ar
> http://listas.python.org.ar/listinfo/pyar
>
> PyAr - Python Argentina - Sitio web: http://www.python.org.ar/
Fede, te paso el proyecto con algunos cambios. Para eliminar el signo 
'+' de los inlines se pueden settear los fields en readonly_fields (esto 
sería más o menos lo mismo que hace tu NewOnlySelect widget). Pero al 
mismo tiempo hay que permitir agregar relaciones nuevas. Para esto 
definí un custom form para los inlines, que setea todos los fields como 
readonly sólo si el form ya está asociado a un objeto. Acá usé la clase 
ReadOnlyWidget que bajé de: http://www.djangosnippets.org/snippets/1682/ 
(lo mando adjunto igual).

En cuanto a la url del objeto relacionado, primero hay que definir el 
método get_absolute_url() de cada model. Después, en este ejemplo 
simplemente redefiní el método __unicode__ de la clase intermedia de la 
relación many_to_many (Species.colors.through.__unicode__) para que 
imprima las urls de la especie y del color relacionados (usando 
mark_safe). Seguramente hay alguna manera más elegante de hacer esto :-)

Espero que te sea útil. Saludos,

-- 
Max

------------ próxima parte ------------
An embedded and charset-unspecified text was scrubbed...
Name: admin.py
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20110224/8c50dc5f/attachment.ksh>
------------ próxima parte ------------
An embedded and charset-unspecified text was scrubbed...
Name: models.py
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20110224/8c50dc5f/attachment-0001.ksh>
------------ próxima parte ------------
An embedded and charset-unspecified text was scrubbed...
Name: readonlywidget.py
URL: <http://listas.python.org.ar/pipermail/pyar/attachments/20110224/8c50dc5f/attachment-0002.ksh>


More information about the pyar mailing list