Pergunta

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

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

Uma maneira seria apontar pontos de vista para métodos de classe e então estender essa classe.Alguém já tentou essa abordagem ou tem alguma outra ideia?

Foi útil?

Solução

Eu criei e usei minhas próprias classes de visualização genéricas, definindo __call__ portanto, uma instância da classe pode ser chamada.Eu realmente gosto;enquanto as visualizações genéricas do Django permitem alguma personalização por meio de argumentos de palavras-chave, as visualizações genéricas OO (se seu comportamento for dividido em vários métodos separados) podem ter uma personalização muito mais refinada por meio de subclasses, o que me permite repetir muito menos.(Fico cansado de reescrever a mesma lógica de criação/atualização de visualização sempre que preciso ajustar algo que as visualizações genéricas do Django não permitem).

Eu postei um código em djangosnippets.org.

A única desvantagem real que vejo é a proliferação de chamadas de métodos internos, o que pode impactar um pouco o desempenho.Não acho que isso seja uma grande preocupação;é raro que a execução do código Python seja o gargalo de desempenho em um aplicativo da web.

ATUALIZAR:Próprio do Django visualizações genéricas agora são baseados em classe.

ATUALIZAR:FWIW, mudei minha opinião sobre as visualizações baseadas em classes desde que esta resposta foi escrita.Depois de usá-los extensivamente em alguns projetos, sinto que eles tendem a levar a códigos que são satisfatoriamente SECOS para escrever, mas muito difíceis de ler e manter posteriormente, porque a funcionalidade está espalhada por muitos lugares diferentes e as subclasses são muito dependentes. em cada detalhe de implementação das superclasses e mixins.agora sinto isso Resposta do modelo e view decorators é uma resposta melhor para decompor o código de view.

Outras dicas

Eu precisava usar visualizações baseadas em classe, mas queria poder usar o nome completo da classe em meu URLconf sem ter que instanciar sempre a classe de visualização antes de usá-la.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)

Agora posso instanciar classes de visualização e usar as instâncias como funções de visualização, OU posso simplesmente apontar meu URLconf para minha classe e fazer com que a metaclasse instancie (e chame) a classe de visualização para mim.Isso funciona verificando o primeiro argumento para __call__ – se for um HttpRequest, deve ser uma solicitação HTTP real porque seria absurdo tentar instanciar uma classe de visualização com um HttpRequest instância.

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

(Eu postei um trecho para isso em http://djangosnippets.org/snippets/2041/)

Se você está simplesmente exibindo dados de modelos, por que não usar o Visualizações genéricas do Django?Eles foram projetados para permitir que você mostre facilmente os dados de um modelo sem ter que escrever sua própria visualização e outras coisas sobre mapeamento de parâmetros de URL para visualizações, busca de dados, manipulação de casos extremos, renderização de saída, etc.

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

Parece-me que você está tentando combinar coisas que não deveriam ser combinadas.Se você precisar fazer um processamento diferente em sua visualização, dependendo se é um objeto Usuário ou Grupo que você está tentando visualizar, você deve usar duas funções de visualização diferentes.

Por outro lado, pode haver expressões comuns que você deseja extrair das visualizações do tipo object_detail ...talvez você possa usar um decorador ou apenas funções auxiliares?

-Dan

A menos que você queira fazer algo um pouco complexo, usar as visualizações genéricas é a melhor opção.Eles são muito mais poderosos do que o nome indica e, se você estiver apenas exibindo dados do modelo, visualizações genéricas resolverão o problema.

As visualizações genéricas geralmente são a melhor opção, mas, em última análise, você está livre para lidar com URLs da maneira que desejar.O FormWizard faz as coisas de maneira baseada em classes, assim como alguns aplicativos para APIs RESTful.

Basicamente, com uma URL, você recebe um monte de variáveis ​​​​e um local para fornecer um chamável, o que você pode chamar depende inteiramente de você - a maneira padrão é fornecer uma função - mas, em última análise, o Django não impõe restrições ao que você faz.

Eu concordo que mais alguns exemplos de como fazer isso seriam bons, mas o FormWizard é provavelmente o lugar para começar.

Se você deseja compartilhar funcionalidades comuns entre páginas, sugiro que você dê uma olhada nas tags personalizadas.Eles são bastante fácil de criar, e são muito poderosos.

Também, modelos podem se estender de outros modelos.Isso permite que você tenha um modelo base para configurar o layout da página e compartilhá-lo com outros modelos que preencham as lacunas.Você pode aninhar modelos em qualquer profundidade;permitindo que você especifique o layout em grupos separados de páginas relacionadas em um só lugar.

Você pode usar as visualizações genéricas do Django.Você pode facilmente alcançar a funcionalidade desejada através das visualizações genéricas do Django

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top