-
Notifications
You must be signed in to change notification settings - Fork 0
/
list_and_detail.py
281 lines (230 loc) · 11.2 KB
/
list_and_detail.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
# coding: utf-8
from django.views.generic import ListView, DetailView
from app_exemplo.models import ListaDeReproducao
class ListasDeReproducao(ListView):
"""
O artigo que faz o uso desse código pode ser conferido em:
http://douglasmiranda.com/artigo/listview-django-class-based-generic-views-i/
http://douglasmiranda.com/artigo/json-view-django-class-based-generic-views-iii/
ListasDeReproducao é a nossa class based generic view que herda de
ListView que pode ser encontrada em: django/views/generic/list.py
É bem simples utilizar a generic view ListView para listar objetos.
Tanto que neste exemplo o código é basicamente este:
class ListasDeReproducao(ListView):
model = ListaDeReproducao
O resto são as explicações e opções de personalização que você
pode fazer com ListView.
"""
"""
Você pode usar o atributo "template_name" para informar a
localização do template personalizado que você quer utilizar.
Caso não queira informar, que é o que eu fiz aqui, por padrão
o Django tentará encontrar um template com um nome neste padrão:
'NomeDoModel_TipoDeView.html'. Como o nosso model é o
'ListaDeReproducao' e nossa view é uma ListView ele buscará por:
'listadereproducao_list.html'. Você pode conferir em:
app_exemplo/templates/app_exemplo/
Para informar a localização do template com o nome personalizado
basta fazer como na linha comentada abaixo.
"""
# template_name = 'app_exemplo/lista_de_reproducao.html'
"""
Uma ListView, obviamente, precisa de dados para serem listados.
Se estes dados estão vindo de algum model, nós precisamos informar
o model que queremos extrair esta lista de objetos.
Em nosso caso o model é o 'ListaDeReproducao'.
"""
model = ListaDeReproducao
"""
Um outro atributo que pode substituir o model é o queryset.
Com ele é possível passar a lita de objetos a serem listados.
A vantagem é que você já pode personalizar a recuperação desses
dados, informando por exemplo um .filter(), .order(), entre outros
métodos disponíveis no model.
"""
# queryset = ListaDeReproducao.objects.all()
"""
O 'context_object_name' é o nome da variável de contexto que estará
disponível para você manipular em seu template, em nosso caso
no 'listadereproducao_list.html'.
Quando você não informa um nome personalizado, que foi o que fizemos,
a variável vai se chamar 'object_list' que será uma lista de objetos.
Ela também poderá ser chamada por um nome composto da seguinte maneira:
NOME_DO_MODEL_list, em nosso caso "listadereproducao_list".
Para representar visualmente, em nosso exemplo será algo como isto:
{
# OUTROS OBJETOS DE CONTEXTO,
'object_list':
[<ListaDeReproducao: Animiais>,
<ListaDeReproducao: Clicks>,
<ListaDeReproducao: Armas disparando>,
<ListaDeReproducao: Sons de armas (GERAL)>],
'listadereproducao_list':
[<ListaDeReproducao: Animiais>,
<ListaDeReproducao: Clicks>,
<ListaDeReproducao: Armas disparando>,
<ListaDeReproducao: Sons de armas (GERAL)>]
}
Podemos manipular, por exemplo, assim:
<ul>
{% for lista_de_reproducao in object_list %}
<li>
<p>{{ lista_de_reproducao.titulo }}</p>
<p>{{ lista_de_reproducao.descricao }}</p>
</li>
{% endfor %}
</ul>
Então se quisermos que "object_list" vire, por exemplo, "listas_de_reproducao"
faça como na linha comentada abaixo:
"""
# context_object_name = 'listas_de_reproducao'
"""
Sobre Objetos de contexto
Se você quiser obter o 'context_object_name' ou o 'queryset', você poderia
simplesmente usar dos métodos: "get_queryset, get_context_object_name" que podem
ser encontrados, para melhor visualização, em django/views/generic/list.py.
Caso queira fazer mais do que apenas obter, se quizer, em algum momento modificar,
tratar casos específicos ou mesmo deixar mais explícito os objetos de contexto que
estarão disponíveis em seu template, você pode utilizar o "get_context_data"
Por exemplo:
"""
# def get_context_data(self, **kwargs):
# context = super(ListasDeReproducao, self).get_context_data(**kwargs)
# # Aqui você fará inclusão, alteração ou exclusão de contextos como desejar
# context['ultima_lista_de_reproducao'] = ListaDeReproducao.objects.latest()
# return context
"""
Se quiser saber em tempo de execução quais os objetos de contexto
que estão sendo passados para seu template, você pode definir este método
e mandar imprimir em console para que você possa ver assim que acessar a url.
def get_context_data(self, **kwargs):
context = super(ListasDeReproducao, self).get_context_data(**kwargs)
# imprimindo no console o que há no dicionário de contextos
print context
return context
Você verá algo desse tipo:
{
'paginator': None,
'page_obj': None,
'is_paginated': False,
'object_list':
[<ListaDeReproducao: Animiais>,
<ListaDeReproducao: Clicks>,
<ListaDeReproducao: Armas disparando>,
<ListaDeReproducao: Sons de armas (GERAL)>],
'listadereproducao_list':
[<ListaDeReproducao: Animiais>,
<ListaDeReproducao: Clicks>,
<ListaDeReproducao: Armas disparando>,
<ListaDeReproducao: Sons de armas (GERAL)>]
}
"""
"""
Toda lista de objetos tende a aumentar, para isto precisamos controlar a
exibição desses objetos em tela com a paginação.
Para isto basta fornecer ao atributo 'paginate_by' a quantidade de objetos
que você quer que seja listada por página. Por exemplo:
paginate_by = 15
Listará 15 objetos por página.
Se quiser ver em nosso exemplo isto em uso experimente descomentar a linha
abaixo, e serão exibidos 2 objetos por página.
"""
# paginate_by = 4
"""
No template, em um exemplo bem simples de páginação você poderia fazer algo como:
{% if is_paginated %}
<div class="paginacao">
<span class="paginacao-links">
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">anterior</a>
{% endif %}
<span class="page-current">
Página {{ page_obj.number }} de {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">próxima</a>
{% endif %}
</span>
</div>
{% endif %}
Que terá como resultado algo como: "Página 1 de 2. próxima"
"""
"""
Sobre paginação
A criatividade é bastante aplicada neste ponto, então você além de explorar as opções
de personalização do template pode alterar conforme quiser o limite desta paginação
inclusive em tempo de execução com o "paginate_queryset". Nas linhas comentadas abaixo
exemplifico isto, tentando obter da url o parâmetro "limite" para ser usado como paginação,
caso não exista eu uso a paginação padrão.
"""
# def paginate_queryset(self, queryset, page_size):
# page_size = self.request.GET.get('limite', page_size)
# paginate_queryset = super(ListasDeReproducao, self).paginate_queryset(queryset, page_size)
# return paginate_queryset
class DetalhesListasDeReproducao(DetailView):
"""
O artigo que faz o uso desse código pode ser conferido em:
http://douglasmiranda.com/artigo/detailview-django-class-based-generic-views-ii/
DetalhesListasDeReproducao é a nossa class based generic view que
herda de DetailView que pode ser encontrada em: django/views/generic/detail.py
É bem simples utilizar a generic view DetailView para exibir informações de um
objeto ou mais, baseado no "slug" ou na chave primária "pk". Geralmente precisamos
disso quando, à partir, de um lista de objetos temos de exibir mais informações
de um objeto especificamente ou mesmo gerar o permalink dele. Como por exemplo a
página interna de uma notícia. Em nosso caso queremos mais detalhes sobre a lista
de reprodução para visualizar mais informações e os áudios contidos na lista.
O código deste exemplo é basicamente este:
class DetalhesListasDeReproducao(DetailView):
model = ListaDeReproducao
O resto são as explicações e opções de personalização que você
pode fazer com DetailView, que há alguns atributos semelhantes no ListView.
"""
"""
A personalização deste atributo é feita da mesma forma que no ListView,
veja mais na view ListasDeReproducao.
O que muda é que se você não definir, automaticamente ela vai buscar o seguinte
template: "listadereproducao_detail.html" que é a soma do nome do Model + o tipo
de view: Model: ListaDeReproducao e View: DetailView
"""
# template_name = 'app_exemplo/lista_de_reproducao_detalhes.html'
"""
Como na ListView: ListasDeReproducao, aqui também é necessário informar o model
do qual extrairemos as informações desejadas.
"""
model = ListaDeReproducao
"""
Como no ListView aqui você pode escolher entre fornecer o model e/ou o queryset.
Mas manipular queryset no DetailView seria para casos bem específicos, pois filtragem
e outras coisas que podem ser feitas com o queryset são geralmente feitas já na hora
de listar, no caso, em uma ListView e no DetailView o objeto selecionado já é o definitivo
e queremos somente extrair informações dele. Para fazer maiores personalizações no objeto
de contexto gerado pela DetailView é necessário manipular os objetos de contexto com
o método "get_context_data".
"""
# queryset = ListaDeReproducao.objects.all()
"""
Se você não der um nome para o objeto de contexto para manipular nos templates o nome dele
será o nome do model, neste caso "listadereproducao", em lower case mesmo. Ou poderá ser acessado
também como "object".
Se você visualizar as variáveis de contexto que estão sendo passadas para seu template verá
algo assim:
{
'listadereproducao': <ListaDeReproducao: Armas disparando>,
'object': <ListaDeReproducao: Armas disparando>
}
Você pode personalizá-lo como na linha comentada abaixo:
"""
# context_object_name = 'lista_de_reproducao'
"""
Sobre Objetos de contexto
O objeto de contexto na DetailView é diferente da ListView, pois no conteúdo extraído do
Model não temos uma lista e sim um objeto, já que a intenção é listar os detalhes de um
objeto específico.
Não quer dizer que você não possa definir o método "get_context_data" e personalizar os
objetos de contexto:
"""
# def get_context_data(self, **kwargs):
# context = super(DetalhesListasDeReproducao, self).get_context_data(**kwargs)
# # Aqui você fará inclusão, alteração ou exclusão de contextos como desejar
# context['listas_de_outras_coisas'] = OutroModel.objects.all()
# return context