Diferença entre get_context_data e get_queryset e melhoria de códigos

247 views
Skip to first unread message

Régis Silva

unread,
Jun 17, 2015, 10:22:02 PM6/17/15
to django...@googlegroups.com
Ola pessoal, eu queria saber a diferença entre get_context_data e get_queryset.

E gostaria de saber a opinião de vocês sobre os meus códigos.

O que está certo e o que está errado neles?


class SaleDetailView(DetailView):
    template_name
= 'vendas/sale/sale_detail.html'
    model
= Sale


   
def get_context_data(self, **kwargs):
        s
= Sale.objects.get(pk=self.kwargs['pk'])
        sd
= SaleDetail.objects.all().filter(sale=s)
        context
= super(SaleDetailView, self).get_context_data(**kwargs)
        context
['count'] = sd.count()
        context
['Sale'] = s
        context
['Itens'] = sd
       
return context




    def get_queryset(self):
        p
= Product.objects.all()
        q
= self.request.GET.get('search_box')
       
# buscar por produto
       
if q is not None:
            p
= p.filter(product__icontains=q)
       
# filtra produtos em baixo estoque
       
if self.request.GET.get('filter_link', False):
            p
= p.filter(stock__lt=F('stock_min'))
       
return p



O que pode ser melhorado nesses códigos?

Eduardo Klosowski

unread,
Jun 18, 2015, 7:21:50 AM6/18/15
to django...@googlegroups.com
Vamos por partes. Primeiro a diferença de get_context_data e
get_queryset. Como você está usando o DetailView, ele possui um método
já ponto para buscar um objeto no banco, porém ele precisa saber de qual
model, qual a chave primária ou outra informação única. O model você
definiu no atributo model, porém toda a busca no banco é feita num
queryset, a implementação padrão do get_queryset é justamente retornar o
self.model.objects, se já não tiver um atributo queryset, se não retorna
o próprio. Para achar o registro coreto é utilizada a função get_object
que por padrão usa o get_queryset com os argumentos pk ou slug, só
defini-los na url.

O get_context_data é para informações adicionais que você queria passar
para a view, não é necessário pegar o objeto novamente, já foi feita
esta consulta e está disponível em self.object. Simplificando um pouco o
seu código, você poderia fazer:

sd = SaleDetail.objects.filter(sale=self.object)

Observe duas diferenças. Primeiro não é necessário criar a variável s e
nem passá-la no contexto, ela poderá ser acessada dentro do template por
padrão com os nomes object ou sale, também é possível alterar este nome
com os atributos da view.

A segunda diferença é que não utilizei o .all(), isso não força a
consulta no banco, não sei se ainda é assim, porém nas versões
anteriores quando utilizado o .all() a consulta era feita da forma que
estava, ou seja, ele faria um select de toda a tabela e depois o filtro.
A vantagem de não usar o .all() é que as consultas podem ser otimizadas.
Se você fizer um filtro numa tabela de categorias para pegar os
elementos e utilizá-los como um filtro para outra, como textos, no
estilo
Texto.objects.filter(categoria__in=Categoria.objects.filter(ativo=1)), o
django pode transformar isso em apenas um único select, mesmo nas vezes
que você usa .value_list ou outros métodos do queryset.

Se tiver alguma dúvida recomendo fortemente olhar o código fonte dessas
views
(https://github.com/django/django/blob/master/django/views/generic/detail.py),
é bem simples a implementação dos métodos, porém ele podem estar um
pouco espalhados devido a reutilização. Mas de forma geral a DetailView
chama o get_object e grava o objeto em self.object, que por sua vez
chama a get_queryset, podendo vir do atributo queryset ou do
self.model.objects. Depois disso é chamado o get_context_data que você
pode passar informações adicionais a view.

Tem um projeto que estou refazendo e utilizando esses conceitos, só
olhar em
https://github.com/eduardoklosowski/ergo-animes/blob/remake/ergoanimes/views.py
a view AnimeDetailView. A ideia é que tenho um model do Anime e outro
com as informações do usuário (UserAnime) com por exemplo o número de
episódios visto por aquele usuário.

GitHub: https://github.com/eduardoklosowski/
Blog: https://eduardoklosowski.wordpress.com/
Podcast: http://www.piratasdainternet.com.br/

On 17-06-2015 23:22, Régis Silva wrote:
> Ola pessoal, eu queria saber a diferença entre get_context_data e
> get_queryset.
>
> E gostaria de saber a opinião de vocês sobre os meus códigos.
>
> O que está certo e o que está errado neles?
>
> https://github.com/rg3915/vendas/blob/master/vendas_project/vendas/views.py#L121-L132
>
> |
> classSaleDetailView(DetailView):
> template_name ='vendas/sale/sale_detail.html'
> model =Sale
>
>
> defget_context_data(self,**kwargs):
> s =Sale.objects.get(pk=self.kwargs['pk'])
> sd =SaleDetail.objects.all().filter(sale=s)
> context =super(SaleDetailView,self).get_context_data(**kwargs)
> context['count']=sd.count()
> context['Sale']=s
> context['Itens']=sd
> returncontext
>
> |
>
>
> https://github.com/rg3915/vendas/blob/master/vendas_project/vendas/views.py#L74-L88
>
> |
> defget_queryset(self):
> p =Product.objects.all()
> q =self.request.GET.get('search_box')
> # buscar por produto
> ifq isnotNone:
> p =p.filter(product__icontains=q)
> # filtra produtos em baixo estoque
> ifself.request.GET.get('filter_link',False):
> p =p.filter(stock__lt=F('stock_min'))
> returnp
>
> |
>
>
> O que pode ser melhorado nesses códigos?
>
> --
> Você recebeu essa mensagem porque está inscrito no grupo "Django Brasil"
> dos Grupos do Google.
> Para cancelar inscrição nesse grupo e parar de receber e-mails dele,
> envie um e-mail para django-brasi...@googlegroups.com
> <mailto:django-brasi...@googlegroups.com>.
> Para mais opções, acesse https://groups.google.com/d/optout.

Rafael dos Santos Gonçalves

unread,
Jun 18, 2015, 8:42:12 AM6/18/15
to django...@googlegroups.com
Esse site ajuda bastante a tirar essa dúvida. Ele mostra as implementações dos métodos.


--
Você está recebendo esta mensagem porque se inscreveu no grupo "Django Brasil" dos Grupos do Google.
Para cancelar inscrição nesse grupo e parar de receber e-mails dele, envie um e-mail para django-brasi...@googlegroups.com.
Para obter mais opções, acesse https://groups.google.com/d/optout.



--
Rafael dos Santos Gonçalves
Ramal - 6757

Eduardo Klosowski

unread,
Jun 18, 2015, 10:06:31 AM6/18/15
to django...@googlegroups.com
Agora sim que eu abandono o as views baseadas em função. Estava sofrendo
para encontrar a implementação correta de cada um dos métodos quando
queria verificar algo mais complexo.
On 18-06-2015 09:42, Rafael dos Santos Gonçalves wrote:
> Esse site ajuda bastante a tirar essa dúvida. Ele mostra as
> implementações dos métodos.
>
> https://ccbv.co.uk/
>
> Em 18 de junho de 2015 08:21, 'Eduardo Klosowski' via Django Brasil
> <django...@googlegroups.com <mailto:django...@googlegroups.com>>
> <mailto:django-brasil%2Bunsu...@googlegroups.com>
> <mailto:django-brasi...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com>>.
> Para mais opções, acesse https://groups.google.com/d/optout.
>
>
> --
> Você está recebendo esta mensagem porque se inscreveu no grupo
> "Django Brasil" dos Grupos do Google.
> Para cancelar inscrição nesse grupo e parar de receber e-mails dele,
> envie um e-mail para django-brasi...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com>.
> Para obter mais opções, acesse https://groups.google.com/d/optout.
>
>
>
>
> --
> Rafael dos Santos Gonçalves
> Ramal - 6757
>

Régis Silva

unread,
Jun 22, 2015, 7:22:37 AM6/22/15
to django...@googlegroups.com
Valeu pela ajuda pessoal.


Regis da Silva | Web Developer 

Linkedin github Google Plus Twitter Youtube pythonclub shopping-cart-8 new-way blogspot morris



--
Você recebeu esta mensagem porque está inscrito em um tópico do grupo "Django Brasil" dos Grupos do Google.

Para cancelar inscrição nesse tópico, acesse https://groups.google.com/d/topic/django-brasil/BJjiQrmL7bA/unsubscribe.
Para cancelar inscrição nesse grupo e todos os seus tópicos, envie um e-mail para django-brasi...@googlegroups.com.

Régis Silva

unread,
Jun 22, 2015, 8:09:36 AM6/22/15
to django...@googlegroups.com
Eduardo

p = Product.objects.all()

era necessário sim.


Regis da Silva | Web Developer 

Linkedin github Google Plus Twitter Youtube pythonclub shopping-cart-8 new-way blogspot morris


Eduardo Klosowski

unread,
Jun 22, 2015, 3:52:56 PM6/22/15
to django...@googlegroups.com
Depois de enviar as correções acabei dando uma pesquisada melhor.

Se for uma ListView é necessário, a menos que tenha outra coisa como um
filter.

Se for uma DetailView não é necessário, já que o get_object faz o filter.

Por isso as vezes pode funcionar e outras não.

Blog: https://eduardoklosowski.wordpress.com/
GitHub: https://github.com/eduardoklosowski/

On 22-06-2015 09:09, Régis Silva wrote:
> Eduardo
>
> p = Product.objects.all()
>
> era necessário sim.
>
>
> Regis da Silva | Web Developer
>
> Linkedin
> <https://www.linkedin.com/profile/public-profile-settings?trk=prof-edit-edit-public_profile>github
> <https://github.com/rg3915>Google Plus
> <https://plus.google.com/+R%C3%A9gisSilvaSantos>Twitter
> <https://twitter.com/rg3915>Youtube
> <https://www.youtube.com/channel/UCSCeh6nJILegqsqsS1WizOQ/videos>pythonclub
> <http://pythonclub.com.br/author/regis-da-silva.html>shopping-cart-8
> <http://rg-vendas.herokuapp.com/>new-way
> <http://new-way.herokuapp.com/>blogspot
> <http://latexbr.blogspot.com.br/>morris
> <http://rg3915.github.io/morris/morris.html>
>
>
> Em 22 de junho de 2015 08:22, Régis Silva <regis.sa...@gmail.com
> <mailto:regis.sa...@gmail.com>> escreveu:
>
> Valeu pela ajuda pessoal.
>
>
> Regis da Silva | Web Developer
>
> Linkedin
> <https://www.linkedin.com/profile/public-profile-settings?trk=prof-edit-edit-public_profile>github
> <https://github.com/rg3915>Google Plus
> <https://plus.google.com/+R%C3%A9gisSilvaSantos>Twitter
> <https://twitter.com/rg3915>Youtube
> <https://www.youtube.com/channel/UCSCeh6nJILegqsqsS1WizOQ/videos>pythonclub
> <http://pythonclub.com.br/author/regis-da-silva.html>shopping-cart-8
> <http://rg-vendas.herokuapp.com/>new-way
> <http://new-way.herokuapp.com/>blogspot
> <http://latexbr.blogspot.com.br/>morris
> <http://rg3915.github.io/morris/morris.html>
>
>
> Em 18 de junho de 2015 11:06, 'Eduardo Klosowski' via Django Brasil
> <django...@googlegroups.com
> <mailto:django...@googlegroups.com>> escreveu:
>
> Agora sim que eu abandono o as views baseadas em função. Estava
> sofrendo para encontrar a implementação correta de cada um dos
> métodos quando queria verificar algo mais complexo.
>
> GitHub: https://github.com/eduardoklosowski/
> Blog: https://eduardoklosowski.wordpress.com/
> Podcast: http://www.piratasdainternet.com.br/
>
> On 18-06-2015 09:42, Rafael dos Santos Gonçalves wrote:
>
> Esse site ajuda bastante a tirar essa dúvida. Ele mostra as
> implementações dos métodos.
>
> https://ccbv.co.uk/
>
> Em 18 de junho de 2015 08:21, 'Eduardo Klosowski' via Django
> Brasil
> <django...@googlegroups.com
> <mailto:django...@googlegroups.com>
> <mailto:django...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com
> <mailto:django-brasil%252Buns...@googlegroups.com>>
> <mailto:django-brasi...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com>
>
> <mailto:django-brasil%2Bunsu...@googlegroups.com
> <mailto:django-brasil%252Buns...@googlegroups.com>>>.
> Para mais opções, acesse
> https://groups.google.com/d/optout.
>
>
> --
> Você está recebendo esta mensagem porque se inscreveu
> no grupo
> "Django Brasil" dos Grupos do Google.
> Para cancelar inscrição nesse grupo e parar de receber
> e-mails dele,
> envie um e-mail para
> django-brasi...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com>
> <mailto:django-brasil%2Bunsu...@googlegroups.com
> <mailto:django-brasil%252Buns...@googlegroups.com>>.
> Para obter mais opções, acesse
> https://groups.google.com/d/optout.
>
>
>
>
> --
> Rafael dos Santos Gonçalves
> Ramal - 6757
>
> --
> Você recebeu essa mensagem porque está inscrito no grupo
> "Django Brasil"
> dos Grupos do Google.
> Para cancelar inscrição nesse grupo e parar de receber
> e-mails dele,
> envie um e-mail para
> django-brasi...@googlegroups.com
> Você recebeu esta mensagem porque está inscrito em um tópico do
> grupo "Django Brasil" dos Grupos do Google.
> Para cancelar inscrição nesse tópico, acesse
> https://groups.google.com/d/topic/django-brasil/BJjiQrmL7bA/unsubscribe.
> Para cancelar inscrição nesse grupo e todos os seus tópicos,
> envie um e-mail para django-brasi...@googlegroups.com
> <mailto:django-brasil%2Bunsu...@googlegroups.com>.
> Para obter mais opções, acesse https://groups.google.com/d/optout.
>
>
>
> --
Reply all
Reply to author
Forward
0 new messages