2009-07-21 15 views
80

Instrucciones de mi supervisor: "Quiero evitar poner cualquier lógica en el models.py. A partir de ahora, vamos a usar eso como únicas clases para acceder a la base de datos, y mantener toda la lógica en clases externas que usan las clases de modelos, o envuélvalos ".models.py hacerse grande, ¿cuál es la mejor manera de romperlo?

Siento que este es el camino equivocado. Siento que mantener la lógica fuera de los modelos solo para mantener el archivo pequeño es una mala idea. Si la lógica es la mejor en el modelo, allí es donde realmente debería ir, independientemente del tamaño del archivo.

¿Existe una forma sencilla de usar? En PHP-speak, me gustaría proponerle al supervisor que solo tenemos models.py include() las clases modelo de otros lugares. Conceptualmente, esto permitiría a los modelos tener toda la lógica que queremos, pero manteniendo el tamaño del archivo reducido al aumentar la cantidad de archivos (lo que lleva a menos problemas de control de revisiones como conflictos, etc.).

Entonces, ¿hay una forma simple de eliminar las clases de modelo del archivo models.py, pero aún así los modelos funcionan con todas las herramientas de Django? ¿O hay una solución completamente diferente pero elegante para el problema general de un archivo "grande" de models.py? Cualquier entrada sería apreciada.

+6

Usted sabe la declaración de importación, ¿verdad? – balpha

+6

PD. No quiero decir eso ofensivamente, solo quiero saber dónde estás. – balpha

+0

Sí, pero no sabía si las herramientas de administración de django funcionarían simplemente usando instrucciones de importación para incorporar los Modelos. Prefiero preguntar aquí que perder mucho tiempo probando con importaciones de oleoducto solo para descubrir que las herramientas de django no funcionan bien con ellos. Admito que soy más nuevo para python y django, por lo que probablemente entiendo simplemente el enunciado de importación ... – Eddified

Respuesta

61

Django está diseñado para permitirle crear muchas aplicaciones pequeñas en lugar de una gran aplicación.

Dentro de cada gran aplicación hay muchas aplicaciones pequeñas que luchan por ser libres.

Si su models.py se siente grande, está haciendo demasiado. Detener. Relajarse. Descomponer.

Encuentra componentes de pequeña aplicación pequeños y potencialmente reutilizables, o piezas. No es necesario que realmente reutilizarlos. Solo piense en ellos como potencialmente reutilizables.

Considere sus rutas de actualización y descomponga las aplicaciones que quizás desee reemplazar algún día. No es necesario que realmente los reemplace, pero puede considerarlos como un "módulo" independiente de programación que podría reemplazarse por algo más frío en el futuro.

Tenemos aproximadamente una docena de aplicaciones, cada model.py no tiene más de 400 líneas de código. Todos están muy enfocados en menos de media docena de definiciones de clase discretas. (Estos no son límites estrictos, son observaciones sobre nuestro código.)

Nos descomponemos temprano y con frecuencia.

+1

justo en el punto. cualquier aplicación web no trivial sería varias pequeñas 'aplicaciones'. Indique la contrib y otras aplicaciones populares, la autenticación de usuario es una aplicación, el etiquetado es otro, los perfiles de usuario uno más, etc. – Javier

+4

Si bien esta es la forma "correcta" y útil de saber, no es exactamente lo que Estaba buscando. Me disculpo si no hubiera forma de saber qué tipo de respuesta estaba buscando.:) – Eddified

+0

@Eddified: si no haces esto, solo va a empeorar. Comience a dividir ahora. –

93

Es natural que las clases de modelo contengan métodos para operar en el modelo. Si tengo un modelo de libro, con un método book.get_noun_count(), ahí es donde pertenece; no quiero tener que escribir "get_noun_count(book)", a menos que el método realmente pertenezca intrínsecamente con algún otro paquete. (Podría, por ejemplo, si tengo un paquete para acceder a la API de Amazon con "get_amazon_product_id(book)".)

Me encogí cuando la documentación de Django sugirió poner modelos en un solo archivo, y tardé unos minutos desde el principio para descubrir cómo dividirlo en un subpaquete adecuado.

site/models/__init__.py 
site/models/book.py 

__init__.py parece:

from .book import Book 

por lo que todavía puede escribir "de site.models importar libro".


La siguiente información sólo se requiere para las versiones anteriores a Django 1.7, ver https://code.djangoproject.com/ticket/3591

El único truco es que es necesario establecer explícitamente la aplicación de cada modelo, debido a un error en Django : asume que el nombre de la aplicación es la penúltima entrada en la ruta del modelo. "site.models.Book" da como resultado "sitio", que es correcto; "site.models.book.Book" hace que piense que el nombre de la aplicación es "modelos". Este es un hack bastante desagradable por parte de Django; probablemente debería buscar en la lista de aplicaciones instaladas una coincidencia de prefijo.

class Book(models.Model): 
    class Meta: app_label = "site" 

Probablemente se podría utilizar una clase base o metaclase generalizar esto, pero no me he molestado con eso todavía.

+2

+1. He utilizado esto con éxito. Si bien S. Lott tiene razón en varias aplicaciones, es una buena idea, esta es la solución aquí y ahora. –

+0

Esta es la manera de hacerlo. Hay más información en el sitio web de Django: http://code.djangoproject.com/wiki/CookBookSplitModelsToFiles –

+0

@Alexander Ljungberg: No estoy convencido de que esto sea más simple que dividir las aplicaciones. Las aplicaciones se pueden dividir desde el 'models.py' original simplemente. A menudo, solo es un poco más que cortar y pegar desde urls.py, views.py, tests.py y models.py. –

4

No puedo entender cuál de los muchos posibles problemas que pueda tener. He aquí algunas posibilidades con las respuestas:

  • varios modelos en el mismo archivo

    ponerlas en archivos separados. Si hay dependencias, use importar para obtener los modelos adicionales .

  • funciones de lógica/utilidad extraños en models.py

    poner la lógica adicional en archivos separados.

  • métodos estáticos de selección de algunas instancias de modelo de base de datos

    Crear un nuevo Manager en un archivo separado.

  • métodos obviamente relacionado con el modelo

    guardar, __unicode__ y get_absolute_url son ejemplos.

Cuestiones relacionadas