Introdução
Para construir uma página de lista que permite filtragem e paginação, você precisa fazer com que algumas coisas diferentes funcionem juntas. O mapeador objeto-relacional (ORM) do Django e a classe de paginação integrada tornam mais fácil para os desenvolvedores se tornarem produtivos sem o conhecimento de como lidar com bancos de dados e SQL nos bastidores. Neste guia, você aprenderá como filtrar um QuerySet dinamicamente usando AJAX.
Para o exemplo neste artigo, peguei um conjunto de dados das 50 melhores músicas do Spotify por país aqui . Você também pode baixar o mesmo conjunto de dados aqui . Como de costume, o código usado neste guia está disponível no GitHub. Você pode encontrar o link no final deste guia.
Primeiros passos
Para começar, comece um novo projeto Django como este:
django-admin startproject my_proj
Em seguida, crie um aplicativo de amostra:
cd meu_proj python manage.py startapp my_app
Atualize o settings.py
:
INSTALLED_APPS +=[ 'my_app' ]
Esta é a estrutura de diretórios que você seguirá no guia:
├── db.sqlite3 ├── manage.py ├── my_app/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── migrações/ │ ├── models.py │ ├── templates/ │ │ ├── base.html │ │ └── index.html │ ├── tests.py │ └── views.py ├── my_proj/ │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── top50contry.csv └── requisitos.txt
Preparação de dados
Antes de pular para o código real, primeiro precisamos enviar todos os dados para o banco de dados.
Eu criei um modelo básico chamado TopSongPoularity
para armazenar as informações necessárias do conjunto de dados.
Aqui está o models.py
de my_app
:
## my_app/models.py de modelos de importação django.db classe TopSongPoularity (models.Model): title=models.CharField (max_length=220) artist=models.CharField (max_length=220) top_genre=models.CharField (max_length=220) year=models.IntegerField () pop=models.IntegerField () duração=models.IntegerField () country=models.CharField (max_length=100) def __str __ (self): return self.title
Agora que você criou o modelo, migre-o para o banco de dados com o seguinte:
python manage.py makemigrations python manage.py migrate
Em seguida, temos que enviar todos os dados CSV para o banco de dados, então usaremos o shell para executar um script:
shell
python manage.py
Execute o script abaixo no shell para enviar os dados CSV para o banco de dados:
#Django Shell importar csv de datetime import datetime from my_app.models import TopSongPoularity com open ('top50contry.csv','r') como fin: leitor=csv.reader (fin) cabeçalhos=próximo (leitor, nenhum) para linha no leitor: obj={ "título": linha [1], "artista": linha [2], "top_genre": linha [3], "ano": int (linha [4]), "pop": int (linha [15]), "duração": int (linha [12]), "país": linha [16] } TopSongPoularity.objects.create (** obj)
Criação de visualizações
A seguir, vamos escrever as visualizações. ListTopSongs
é uma visão baseada em classe (CBV) que herda a classe View
. No método get ()
da classe, ele pega os parâmetros de consulta e filtra o QuerySet de acordo. Depois que o QuerySet é filtrado, ele chama get_paginated_context ()
para obter os dados paginados em formato serializado.
getCountries ()
é uma visualização baseada em função (FBV) que retorna a saída JSON para todos os países exclusivos no banco de dados:
# my_app/views.py import json de django.core.paginator import Paginator from django.core.serializers import serialize de django.http import JsonResponse de django.shortcuts import render de django.views import View from.models import TopSongPoularity índice def (pedido): renderização de retorno (solicitação,"index.html", {}) classe ListTopSongs (View): # definir limite de página padrão como 10 page_limit=10 # padrão ''' Método auxiliar para obter o contexto de paginação fora do queryset de determinado número de página com limite. Args: queryset: objeto queryset filtrado página: um número que representa o número da página limite: a contagem de resultados, por página. Retorna o JSON de queryset para a página fornecida, com meta info de paginação. ''' def get_paginated_context (self, queryset, page, limit): se não for página: página=1 # se nenhuma página for fornecida, defina 1 # se o limite for especificado, defina o limite da página se limite: self.page_limit=limit # instanciar o objeto paginator com queryset e limite de página paginator=Paginator (queryset, self.page_limit) # obter o objeto da página page_obj=paginator.get_page (page) # serializar os objetos para json serialized_page=serialize ("json", page_obj.object_list) # obtenha apenas os campos obrigatórios do json serialized_page. serialized_page=[obj ["campos"] para obj em json.loads (serialized_page)] # retorna o contexto. Retorna { "data": serialized_page, "paginação": { "página": página, "limit": limite, "has_next": page_obj.has_next (), "has_prev": page_obj.has_previous (), "total": queryset.count () } } ''' Método GET para esta visão. ''' def get (self, request, * args, ** kwargs): # buscar os parâmetros de consulta page=request.GET.get ('page') limit=request.GET.get ('limit') country=request.GET.get ('country') start=request.GET.get ('start') end=request.GET.get ('end') sort_by=request.GET.get ('sort_by') # obter todos os resultados do banco de dados. queryset=TopSongPoularity.objects.all () '''filtrar o objeto queryset com base nos parâmetros de consulta''' # 1. com base no país se país e país!="todos": queryset=queryset.filter (país=país) # 2. Com base na data (data de início e término) se começar e terminar: se iniciar!="0"e terminar!="0": queryset=queryset.filter ( year__gte=start, ano__lte=fim ) # 3. Classificando o queryset filtrado se sort_by e sort_by!="0": queryset=queryset.order_by (sort_by) # retornar a saída serializada por # método de chamada'get_paginated_context' to_return=self.get_paginated_context (queryset, página, limite) retornar JsonResponse (to_return, status=200) def getCountries (solicitação): # obter países do banco de dados # excluindo valores nulos e em branco if request.method=="GET"e request.is_ajax (): country=TopSongPoularity.objects.all (). \ lista_valores ('país'). distinto () país=[c [0] para c na lista (país)] return JsonResponse ({ "país": país, }, status=200)
Criação de URLs
Agora, vamos encaminhar as visualizações:
# my_proj/urls.py do caminho de importação django.urls from my_app.views import ListTopSongs, index, getCountries urlpatterns=[ path ('api/get/top_songs', ListTopSongs.as_view ()), caminho ('api/get/countries', getCountries, name="get_countries"), caminho ('', índice) ]
Criação de modelos
Agora que o código de back-end está pronto, vamos passar para o front-end.
Usei um template base ( base.html
) como segue, que inclui Bootstrap e bibliotecas jQuery:
Foguete de registro {% block style%} {% endblock style%} {% block content%} {% endblock%} {% block javascript%} {% endblock javascript%}
Agora vamos criar o index.html
que exibe a tabela com os filtros. Este arquivo de modelo herda o base.html
e cria a tabela com um cabeçalho e corpo vazio. No final, também contém dois botões para “Próximo” e “Anterior”.
A parte restante do index.html
, que é a parte JavaScript, é explicada abaixo:
{% extends'base.html'%} {% block content%} {% endblock content%}resultados encontrados.Página:
Título País Principal gênero Artista Duração Pop Ano
Criação de scripts do lado do cliente
A última parte deste guia é conectar o front-end com o back-end usando AJAX. Consulte os comentários mencionados nos snippets de código abaixo:
{% block javascript%} {% endblock javascript%}
Conclusão
Neste guia, você aprendeu como usar AJAX e como se comunicar com o back-end de forma assíncrona. Filtrar os dados tabulares é um cenário comum de lidar, e espero que este guia tenha dado a você uma melhor compreensão de como lidar com a filtragem dos dados.
Você também pode usar estruturas REST como estrutura Django REST para manter as coisas simples, se preferir.
Se você enfrentar qualquer problema ao seguir o guia, pode sempre verificar meu Repositório Github para ver o todo projeto.
A postagem Filtrando QuerySets dinamicamente no Django apareceu primeiro em LogRocket Blog .