2009-12-17 24 views
121

Mi views.py se ha vuelto demasiado grande y es difícil encontrar la vista correcta.Split views.py en varios archivos

¿Cómo puedo dividirlo en varios archivos y luego importarlo? ¿Implica alguna pérdida de velocidad?

¿Puedo hacer lo mismo con models.py?

+3

Divido mi archivo grande (7k líneas) views.py en archivos separados y el aumento en la velocidad fue significativo. – user1261774

Respuesta

143

En Django todo es un módulo de Python (* .py). Puede crear una carpeta de vista con un __init__.py dentro y todavía podrá importar sus vistas, porque esto también implementa un módulo de Python. Pero un ejemplo sería mejor.

El original views.py podría tener este aspecto:

def view1(arg): 
    pass 

def view2(arg): 
    pass 

con la siguiente estructura de carpetas/archivos que va a trabajar el mismo:

views/ 
    __init__.py 
    viewsa.py 
    viewsb.py 

viewsa.py:

def view1(arg): 
    pass 

viewsb.py:

def view2(arg): 
    pass 

__init__.py:

from viewsa import view1 
from viewsb import view2 

El rápida explicación sería: cuando se escribe from views import view1 Python buscará Vista1 en

  1. views.py, que es lo que ocurre en la primera (original) case

  2. views/__init__.py, que es lo que sucede en el segundo caso. Aquí, __init__.py puede proporcionar el método view1 porque lo importa.

Con este tipo de solución, es posible que tenga ninguna necesidad de cambiar import o urlpattern s argumentos en urls.py

Si tiene muchos métodos en cada nuevo archivo de vista, puede que le resulte útil para hacer la las importaciones en views/__init__.py utilizan *, así:

from viewsa import * 
from viewsb import * 

en realidad no sé acerca de los problemas de velocidad (pero dudo que haya alguna).

Para los modelos puede ser un poco difícil.

+1

¿Podría agregar un patrón de URL que coincida con view1 o view2 en su ejemplo? Porque estoy teniendo problemas con eso .... –

+2

Intenté hacer esto, pero cuando voy a importar mis modelos (desde app.models importa MyModel o desde modelos importan MyModel) Python se queja de que el modelo no existe. –

+0

¿Está bien si eliminamos views.py en el directorio raíz? –

9

Básicamente, puede poner su código, donde quiera. Solo asegúrese de cambiar las declaraciones de importación en consecuencia, p. para las vistas en el urls.py.

Sin saber su código real es difícil sugerir algo significativo. Tal vez puedas usar algún tipo de prefijo de nombre de archivo, p. views_helper.py, views_fancy.py, views_that_are_not_so_often_used.py o así ...

Otra opción sería crear un directorio con un views__init__.py, donde se importan todos los subvistas. Si necesita una gran cantidad de archivos, puede crear más subvistas anidadas a medida que crecen sus vistas ...

1

Dado que Django solo espera que una vista sea un objeto invocable, puede colocarla donde desee en su PYTHONPATH. Entonces, por ejemplo, puedes crear un nuevo paquete myapp.views y poner vistas en múltiples módulos allí. Naturalmente, tendrá que actualizar su urls.py y otros módulos que hacen referencia a estos callables de vista.

+1

Esto es realmente incorrecto - puede hacerse con modelos. Ver: http://code.djangoproject.com/ticket/4470 –

+1

Ah, es bueno saberlo, gracias :-) Siempre pensé que había un poco más de magia involucrada con los modelos y cómo viven en el paquete de la aplicación. Eliminé la línea sobre modelos en mi respuesta. –

+0

Me alegro de poder ayudar, me di cuenta más tarde que este enlace en realidad explica cómo se hace con los modelos mucho mejor: http://blog.amber.org/2009/01/19/moving-django-models-into-their-own- module/ –

4

Respuesta simple: Sí.

mejor es hacer un directorio llamado vistas y luego en su urls.py hacer:

import views 
... 
url(r'^classroom$', views.school.klass, name="classroom"), 
18

que he tenido que hacer esto antes (por causa claridades)

La forma en que hice esto era crear un directorio views, a continuación, en la que, cree un archivo llamado __init__.py

Ahora, cuando se está llamando en su urls.py, sólo hay que añadir otra parte

Por ejemplo, anteriormente, es posible que han llamado: -

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year') 
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year_by_user') 

Ahora puede llamar a algo en la línea de

url(r'^calendar/(?P<year>\d\d\d\d)/$', 'myproject.calendar.views.year.index') 
url(r'^calendar/(?P<year>\d\d\d\d)/(?P<user>[a-z]+)/$', 'myproject.calendar.views.year.user') 

Esto es, por supuesto, asumiendo que tenías views/year.py que contiene las funciones index y user;)

1

que divide casi todos los puntos de vista en mis aplicaciones en una carpeta de vistas (con un init .py de c ourse). Sin embargo, no importo todas las subvistas en init .py como han sugerido algunas de las respuestas. Parece que funciona bien.

1

He estado jugando con poner esto en mi init .py:

import os 

currPath = os.path.realpath(os.path.dirname(__file__)) 

dirFiles = [] 
for root, dirs, files in os.walk(currPath): 
    for name in files: 
     if name.endswith('.py') and not name.startswith('_'): 
      dirFiles.append(name.strip('.py')) 

for f in dirFiles: 
    exec("from %s import %s" % (f,f)) 

sigo siendo nuevo en Python, así que todavía estoy mirando el efecto que tiene en la velocidad/seguridad /facilidad de uso.

0

Supongamos que si usted tiene un archivo llamado: password_generator.py luego dentro views.py complemento: from password_generator import *

A continuación, puede llamar a la función de ese módulo de views.py.

1

Solo para compartir, tuve algunos problemas con la respuesta de Vincent Demeester. Todo está bien, excepto en init archivo .py, tengo que escribir de esta manera:

__init__.py:

from .viewsa import * 
from .viewsb import * 

De esta manera Todavía no necesito cambiar mi método import en urls.py. Estoy en Python 3.6.1 y Django 1.11.4.