Dividir views.py em vários arquivos

153

Meu views.pytornou-se muito grande e é difícil encontrar a visão correta.

Como o divido em vários arquivos e depois o importo? Isso envolve alguma perda de velocidade?

Posso fazer o mesmo com models.py?

barin
fonte
4
Dividi meu grande arquivo views.py (7k linhas) para separar arquivos e o aumento na velocidade foi significativo.
user1261774

Respostas:

190

No Django, tudo é um módulo Python (* .py). Você pode criar uma pasta de visualização com um __init__.pyinterior e ainda poderá importar suas visualizações, porque isso também implementa um módulo Python. Mas um exemplo seria melhor.

Seu original views.pypode ficar assim:

def view1(arg):
    pass

def view2(arg):
   pass

Com a seguinte estrutura de pastas / arquivos, funcionará da mesma maneira:

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

A explicação rápida seria: quando você escreve, o from views import view1Python procura por view1 em

  1. views.py, que é o que acontece no primeiro caso (original)

  2. views/__init__.py, que é o que acontece no segundo caso. Aqui, __init__.pyé capaz de fornecer o método view1 porque o importa.

Com este tipo de solução, você pode ter nenhuma necessidade de mudar importou urlpatterns argumentosurls.py

Se você tiver muitos métodos em cada novo arquivo de visualização, poderá ser útil fazer as importações em views/__init__.pyuso *, desta forma:

from viewsa import *
from viewsb import *

Na verdade, eu não sei sobre problemas de velocidade (mas duvido que exista).

Para modelos, pode ser um pouco difícil.

Vincent Demeester
fonte
2
Você poderia adicionar um padrão de URL que corresponda a view1 ou view2 no seu exemplo? Porque eu estou tendo problemas com isso ....
Pascal Klein
2
Tentei fazer isso, mas quando vou importar meus modelos (do app.models import MyModel ou dos modelos import MyModel), o Python reclama que o modelo não existe.
Chris Miller
Tudo bem se excluirmos o arquivo views.py no diretório raiz?
Roel
6
Esta solução não funciona para mim (mesmo erro que para @ ChrisMiller. Minha solução: em __init__.py:. from myapp.views.viewsa import *Observe que você não pode mais ter um views.py (ou pelo menos não será lido @ShiftNTab: erro para não . encontrar os seus pontos de vista em views.py) Espero que ajude!
ThePhi
E a convenção de nomenclatura: o nome do arquivo deve ser singular ou plural? Por exemplo: views.car.pyvsviews.cars.py
guival 28/11
21

Eu tive que fazer isso antes (por uma questão de clareza)

A maneira como fiz isso foi criar um viewsdiretório e, em seguida, criar um arquivo chamado__init__.py

Agora, quando você está ligando urls.py, basta adicionar outra parte

Por exemplo, anteriormente, você pode ter chamado: -

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')

Agora você pode ligar para algo como

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')

Obviamente, isso pressupõe que você views/year.pycontinha as funções indexe user;)

Mez
fonte
10

Basicamente, você pode colocar seu código, onde quiser. Apenas certifique-se de alterar as instruções de importação de acordo, por exemplo, para as visualizações no urls.py.

Não sabendo o seu código real, é difícil sugerir algo significativo. Talvez você possa usar algum tipo de prefixo do nome, por exemplo views_helper.py, views_fancy.py, views_that_are_not_so_often_used.pyou assim ...

Outra opção seria criar um viewsdiretório com um __init__.py, onde você importa todas as subvisões . Se você precisar de um grande número de arquivos, poderá criar mais subvisões aninhadas à medida que suas visualizações aumentarem ...

miku
fonte
8

Só por compartilhar, tive alguns problemas com a resposta de Vincent Demeester. Está tudo bem, exceto no arquivo init .py, eu tenho que escrever desta maneira:

__init__.py :

from .viewsa import *
from .viewsb import *

Dessa forma, ainda não preciso alterar meu importmétodo em urls.py. Estou no Python 3.6.1 e Django 1.11.4 .

viciado
fonte
5

Resposta simples: Sim.

O melhor é criar um diretório chamado views e, em seu urls.py, faça:

import views
...
url(r'^classroom$', views.school.klass, name="classroom"),
Peter Bengtsson
fonte
1

Dividi quase todas as visualizações nos meus aplicativos em uma pasta de visualizações (com um init .py, é claro). No entanto, não importo todas as subvisões no init .py, como sugeriram algumas das respostas. Parece funcionar muito bem.

DrBloodmoney
fonte
1

Como o Django apenas espera que a visualização seja um objeto que pode ser chamado, você pode colocá-lo onde quiser no seu PYTHONPATH. Assim, você poderia, por exemplo, criar um novo pacote myapp.views e colocar visualizações em vários módulos lá. Naturalmente, você precisará atualizar seu urls.py e outros módulos que fazem referência a essas exibições de chamadas.

Horst Gutmann
fonte
1
Na verdade, isso está incorreto - isso pode ser feito com modelos. Veja: code.djangoproject.com/ticket/4470
Jonathan Berger
1
Ah, bom saber, obrigado :-) Eu sempre pensei que havia um pouco mais de mágica envolvida com os modelos e como eles vivem no pacote de aplicativos. Removida a linha sobre modelos na minha resposta.
Horst Gutmann
Ainda bem que pude ajudar, eu percebi mais tarde que esta ligação realmente explica como é feito com modelos muito melhor: blog.amber.org/2009/01/19/...
Jonathan Berger
1

Eu tenho brincado em colocar isso no meu 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))

Ainda sou novo no python, então ainda estou analisando o efeito que ele tem na velocidade / segurança / facilidade de uso.

EToS
fonte
1

Suponha que, se você tiver um arquivo chamado password_generator.py:, em seguida, views.pyadicione:from password_generator import *

Então você pode chamar a função desse módulo de views.py.

Abhay
fonte
1

A resposta de Vincent Demeester é excelente! mas para mim a resposta do viciado funcionou como um encanto. Enfrentei dificuldades na migração do banco de dados. O erro indica a linha em que o primeiro modelo foi importado e diz que não foi possível reconhecer meu módulo de aplicativo. Pesquisei muito, mas não consegui encontrar uma solução, mas depois importei o modelo assim:

from ..models import ModelName

Funcionou!!

Bashar
fonte