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.