visualizações de classe em Django

votos
48

Django vista aponta para uma função, que pode ser um problema se você quiser alterar apenas um pouco de funcionalidade. Sim, eu poderia ter milhão de argumentos chave e ainda mais se as declarações na função, mas eu estava pensando mais em uma abordagem orientada a objetos.

Por exemplo, eu tenho uma página que exibe um usuário. Esta página é muito semelhante à página que apresenta um grupo, mas ainda não é tão semelhante a usar apenas um outro modelo de dados. Grupo também tem membros etc ...

Uma forma seria a apontar vista para métodos de classe e, em seguida, estender essa classe. Alguém já experimentou esta abordagem ou tem alguma outra idéia?

Publicado 03/08/2008 em 16:55
fonte usuário
Em outras línguas...                            


9 respostas

votos
41

Eu criei e usei minhas próprias classes visão genérica, definindo __call__assim uma instância da classe é exigível. Eu realmente gosto; enquanto views genéricas do Django permitir alguma personalização através de argumentos chave, OO vistas genéricos (se o seu comportamento é dividida em uma série de métodos diferentes) pode ter muito mais refinado personalização através de subclasses, que me permite repetir-me muito menos. (Eu fico cansado de reescrever o mesmo criar / atualização vista lógica sempre que eu precisar de ajustar algo views genéricas do Django não chegam a permitir).

Eu afixei algum código em djangosnippets.org .

O verdadeiro única desvantagem que vejo é a proliferação de chamadas de métodos internos, que podem afetar o desempenho um pouco. Eu não acho que isso é muito de uma preocupação; é raro que a execução de código Python seria o gargalo de desempenho em um aplicativo web.

ATUALIZAÇÃO : próprias do Django views genéricas são agora baseada em classes.

ATUALIZAÇÃO : FWIW, eu mudei minha opinião sobre as opiniões baseadas na classe uma vez que esta resposta foi escrito. Depois de tê-los usado extensivamente em um par de projetos, eu sinto que eles tendem a levar a código que é satisfatoriamente DRY para escrever, mas muito difícil de ler e manter depois, porque a funcionalidade está distribuída em tantos lugares diferentes, e subclasses são tão dependentes em cada detalhe de implementação das superclasses e mixins. Agora sinto que TemplateResponse e vista decoradores é uma resposta melhor para decompor código vista.

Respondeu 29/08/2008 em 05:29
fonte usuário

votos
13

Eu precisava usar vistas base de classe, mas eu queria ser capaz de usar o nome completo da classe no meu URLconf sem sempre ter que instanciar a classe vista antes de usá-lo. O que me ajudou foi uma metaclasse surpreendentemente simples:

class CallableViewClass(type):
    def __call__(cls, *args, **kwargs):
        if args and isinstance(args[0], HttpRequest):
            instance = super(CallableViewClass, cls).__call__()
            return instance.__call__(*args, **kwargs)
        else:
            instance = super(CallableViewClass, cls).__call__(*args, **kwargs)
            return instance


class View(object):
    __metaclass__ = CallableViewClass

    def __call__(self, request, *args, **kwargs):
        if hasattr(self, request.method):
            handler = getattr(self, request.method)
            if hasattr(handler, '__call__'):
                return handler(request, *args, **kwargs)
        return HttpResponseBadRequest('Method Not Allowed', status=405)

Eu posso agora ambos instanciar classes de vista e usar as instâncias como funções de visualização, ou posso simplesmente apontar o meu URLconf a minha classe e ter a instanciar metaclass (e chamar) a classe vista para mim. Isso funciona, marcando o primeiro argumento para __call__- se é um HttpRequest, ele deve ser uma solicitação HTTP real, porque seria absurdo attept para instanciar uma classe vista com um HttpRequestexemplo.

class MyView(View):
    def __init__(self, arg=None):
        self.arg = arg
    def GET(request):
        return HttpResponse(self.arg or 'no args provided')

@login_required
class MyOtherView(View):
    def POST(request):
        pass

# And all the following work as expected.
urlpatterns = patterns(''
    url(r'^myview1$', 'myapp.views.MyView', name='myview1'),
    url(r'^myview2$', myapp.views.MyView, name='myview2'),
    url(r'^myview3$', myapp.views.MyView('foobar'), name='myview3'),
    url(r'^myotherview$', 'myapp.views.MyOtherView', name='otherview'),
)

(I postou um trecho para este na http://djangosnippets.org/snippets/2041/ )

Respondeu 27/05/2010 em 14:02
fonte usuário

votos
9

Se você está simplesmente exibindo dados de modelos, por que não usar as Visualizações Django genéricos ? Eles são projetados para permitir que você os dados mostram fáceis de um modelo sem ter que escrever o seu próprio ponto de vista e outras coisas sobre o mapeamento paramaters URL para vistas, buscar dados, o tratamento de casos de ponta, saída de renderização, etc.

Respondeu 07/08/2008 em 11:44
fonte usuário

votos
3

Você sempre pode criar uma classe, substituir o __call__função e em seguida, aponte o arquivo de URL para uma instância da classe. Você pode dar uma olhada no FormWizard classe para ver como isso é feito.

Respondeu 26/08/2008 em 12:38
fonte usuário

votos
2

A menos que você quiser fazer algo um pouco complexo, utilizando os pontos de vista genéricos são o caminho a percorrer. Eles são muito mais poderoso do que seu nome sugere, e se você está apenas exibindo visualizações de dados modelo genérico vai fazer o trabalho.

Respondeu 11/08/2008 em 23:59
fonte usuário

votos
2

Parece-me que você está tentando combinar coisas que não devem ser combinados. Se você precisa fazer o processamento diferente em sua visão, dependendo se é um usuário ou grupo objeto que você está tentando olhar para, em seguida, você deve usar duas funções vista diferentes.

Por outro lado, não pode haver expressões comuns que você gostaria de extrair fora de suas vistas tipo object_detail ... talvez você poderia usar um decorador ou apenas funções auxiliares?

-Dan

Respondeu 03/08/2008 em 18:40
fonte usuário

votos
1

Você pode usar as Visualizações Django genéricos. Você pode facilmente atingir funcionalidade desejada completas Django Visualizações genéricos

Respondeu 08/10/2014 em 06:53
fonte usuário

votos
1

views genéricas geralmente será o caminho a percorrer, mas em última análise, você está livre para lidar com URLs como quiser. FormWizard faz as coisas de uma forma baseada em classes, como fazem alguns aplicativos para APIs RESTful.

Basicamente com uma URL que você está dado um monte de variáveis ​​e local para fornecer uma exigível, o que pode ser chamado que você fornece é completamente até você - a forma padrão é fornecer uma função - mas em última análise Django não coloca restrições sobre o que você faz.

Eu concordo que mais alguns exemplos de como fazer isso seria bom, FormWizard é provavelmente o lugar para começar embora.

Respondeu 23/09/2008 em 20:05
fonte usuário

votos
1

Se você quiser compartilhar a funcionalidade comum entre as páginas eu sugiro que você olhar para marcas personalizadas. Eles são muito fáceis de criar , e são muito poderosos.

Além disso, os modelos podem se estender de outros modelos . Isso permite que você tenha um modelo de base para configurar o layout da página e para compartilhar esta entre outros modelos que preenchem os espaços em branco. Você pode modelos ninho para qualquer profundidade; o que lhe permite especificar o layout em grupos separados de páginas relacionadas no mesmo lugar.

Respondeu 26/08/2008 em 12:30
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more