Browse Source

Adicionada API com lista de serviços SEIT

master 4.0.22
Sesóstris Vieira 3 weeks ago
parent
commit
b699804214
  1. 3
      requirements/requirements.txt
  2. 1
      sigi/apps/servicos/api_urls.py
  3. 28
      sigi/apps/servicos/filters.py
  4. 54
      sigi/apps/servicos/serializers.py
  5. 32
      sigi/apps/servicos/views.py
  6. 20
      sigi/settings.py
  7. 21
      sigi/templates/sigi/api/redoc.html
  8. 28
      sigi/templates/sigi/api/swagger-ui.html
  9. 26
      sigi/urls.py

3
requirements/requirements.txt

@ -12,6 +12,7 @@ django-weasyprint==2.5.0
djangorestframework==3.17.1
dnspython==2.8.0
docutils==0.22.4
drf-spectacular==0.29.0
email-validator==2.3.0
gunicorn==25.3.0
ibge==0.0.5
@ -34,4 +35,4 @@ weasyprint==68.1
xlsxwriter==3.2.9
djbs-theme @ git+https://github.com/interlegis/djbs-theme.git@v1.0.7
django-dashboard @ git+https://github.com/interlegis/django-dashboard.git
dx-job-controller @ git+https://github.com/interlegis/dx-job-controller.git@v1.0.0
dx-job-controller @ git+https://github.com/interlegis/dx-job-controller.git@v1.0.0

1
sigi/apps/servicos/api_urls.py

@ -3,4 +3,5 @@ from sigi.apps.servicos import views
urlpatterns = [
path("resumoprodutos/", views.ResumoProdutosApiView.as_view()),
path("", views.ServicoListView.as_view()),
]

28
sigi/apps/servicos/filters.py

@ -1,6 +1,8 @@
import django_filters
from datetime import date, timedelta
from django.utils.translation import gettext as _
from django.contrib import admin
from sigi.apps.servicos.models import Servico
class ServicoAtivoFilter(admin.FieldListFilter):
@ -8,9 +10,7 @@ class ServicoAtivoFilter(admin.FieldListFilter):
self.model = model
self.model_admin = model_admin
self.parameter_name = f"{field_path}__isnull"
super().__init__(
field, request, params, model, model_admin, field_path
)
super().__init__(field, request, params, model, model_admin, field_path)
self.title = _("Serviço ativo")
lookup_choices = self.lookups(request, model_admin)
if lookup_choices is None:
@ -91,3 +91,25 @@ class DataUtimoUsoFilter(admin.SimpleListFilter):
de = date.today() - timedelta(days=30)
ate = date.today() - timedelta(days=7)
return queryset.filter(data_ultimo_uso__range=(de, ate))
class ServicoAPIFilter(django_filters.FilterSet):
uf = django_filters.CharFilter(
field_name="casa_legislativa__municipio__uf__sigla",
lookup_expr="iexact",
label=_("Sigla da UF"),
)
tipo_servico = django_filters.CharFilter(
field_name="tipo_servico__sigla",
lookup_expr="iexact",
label=_("Sigla do tipo de serviço"),
)
class Meta:
model = Servico
fields = [
"uf",
"tipo_servico",
"hospedagem_interlegis",
"data_ativacao",
]

54
sigi/apps/servicos/serializers.py

@ -1,6 +1,60 @@
from rest_framework import serializers
from yaml import serialize
from sigi.apps.casas.models import Orgao, TipoOrgao
from sigi.apps.servicos.models import Servico, TipoServico
class ProdutosSerializer(serializers.Serializer):
produto = serializers.CharField(max_length=40)
quantidade = serializers.IntegerField()
class OrgaoSerializer(serializers.ModelSerializer):
sigla = serializers.ReadOnlyField(source="get_sigla")
tipo_orgao_nome = serializers.CharField(source="tipo.nome", read_only=True)
tipo_orgao_sigla = serializers.CharField(
source="tipo.sigla", read_only=True
)
municipio = serializers.CharField(source="municipio.nome", read_only=True)
uf = serializers.CharField(source="municipio.uf.sigla", read_only=True)
telefone = serializers.ReadOnlyField()
class Meta:
model = Orgao
fields = [
"nome",
"sigla",
"tipo_orgao_nome",
"tipo_orgao_sigla",
"cnpj",
"logradouro",
"bairro",
"municipio",
"cep",
"uf",
"email",
"ult_alt_endereco",
"telefone",
]
class ServicoSerializer(serializers.ModelSerializer):
casa_legislativa = OrgaoSerializer(read_only=True)
tipo_servico_nome = serializers.CharField(
source="tipo_servico.nome", read_only=True
)
tipo_servico_sigla = serializers.CharField(
source="tipo_servico.sigla", read_only=True
)
class Meta:
model = Servico
fields = [
"casa_legislativa",
"tipo_servico_nome",
"tipo_servico_sigla",
"url",
"hospedagem_interlegis",
"data_ativacao",
]

32
sigi/apps/servicos/views.py

@ -2,16 +2,20 @@ from django.db.models import Q, Prefetch, Count, F, Value, Case, When
from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt
from django.views.generic import ListView
from django_filters.rest_framework import DjangoFilterBackend
from import_export import resources
from import_export.fields import Field
from rest_framework import generics
from rest_framework import generics, filters
from sigi.apps.casas.models import Orgao
from sigi.apps.servicos.serializers import ServicoSerializer
from sigi.apps.contatos.models import UnidadeFederativa
from sigi.apps.convenios.models import Convenio
from sigi.apps.eventos.models import Evento, TipoEvento
from sigi.apps.servicos.filters import ServicoAPIFilter
from sigi.apps.servicos.models import Servico
from sigi.apps.servicos.serializers import ProdutosSerializer
from sigi.apps.utils import to_ascii
from sigi.apps.utils.filters import DeterministicOrderingFilter
class ServicoResource(resources.ModelResource):
@ -40,6 +44,32 @@ class ServicoResource(resources.ModelResource):
return servico.casa_legislativa.telefone
class ServicoListView(generics.ListAPIView):
"""Lista de serviços ativos prestados pelo Interlegis às Casas Legislativas"""
queryset = Servico.objects.filter(data_desativacao=None).select_related(
"casa_legislativa__municipio__uf", "tipo_servico"
)
serializer_class = ServicoSerializer
filter_backends = [
DjangoFilterBackend,
filters.SearchFilter,
DeterministicOrderingFilter,
]
filterset_class = ServicoAPIFilter
search_fields = [
"casa_legislativa__nome",
"casa_legislativa__cnpj",
]
ordering_fields = [
"casa_legislativa__municipio__uf__sigla",
"casa_legislativa__nome",
"tipo_servico__sigla",
"data_ativacao",
]
ordering = ["-data_ativacao"]
class CasasAtendidasListView(ListView):
model = Orgao
template_name = "servicos/casas_atendidas.html"

20
sigi/settings.py

@ -16,7 +16,6 @@ from django.utils.translation import gettext_lazy as _
from django.conf.locale.pt_BR import formats as br_formats
from djbs import djbs_constants
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent
@ -63,6 +62,7 @@ INSTALLED_APPS = [
"import_export",
"tinymce",
"rest_framework",
"drf_spectacular",
"sigi.apps.casas",
"sigi.apps.contatos",
"sigi.apps.convenios",
@ -284,6 +284,7 @@ TINYMCE_DEFAULT_CONFIG = {
# Rest Framework settings
REST_FRAMEWORK = {
"DEFAULT_SCHEMA_CLASS": "drf_spectacular.openapi.AutoSchema",
"DEFAULT_RENDERER_CLASSES": [
"rest_framework.renderers.JSONRenderer",
],
@ -291,6 +292,23 @@ REST_FRAMEWORK = {
"PAGE_SIZE": 100,
}
# drf-spectacular settings
SPECTACULAR_SETTINGS = {
"TITLE": "SIGI API",
"DESCRIPTION": "API de dados abertos dos Serviços prestados pelo Interlegis / Senado Federal",
"VERSION": "1.0.0",
"SERVE_INCLUDE_SCHEMA": False,
"CONTACT": {
"name": "Serviço de Gestão de Informações Educacionais do ILB/Interlegis",
"email": "lct_seginfe@senado.leg.br",
},
"LICENSE": {
"name": "GPL-2.0.1",
"url": "https://github.com/interlegis/sigi?tab=GPL-2.0-1-ov-file#",
},
}
# SIGI specific settings
HOSPEDAGEM_PATH = Path(env("HOSPEDAGEM_PATH", default="/tmp/HOSP/"))

21
sigi/templates/sigi/api/redoc.html

@ -1,21 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>SIGI ReDoc documentation</title>
<!-- needed for adaptive design -->
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
<!-- ReDoc doesn't change outer page styles -->
<style>
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<redoc spec-url='{% url schema_url %}'></redoc>
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
</body>
</html>

28
sigi/templates/sigi/api/swagger-ui.html

@ -1,28 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>SIGI Swagger documentation</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="//unpkg.com/swagger-ui-dist@3/swagger-ui.css" />
</head>
<body>
<div id="swagger-ui"></div>
<script src="//unpkg.com/swagger-ui-dist@3/swagger-ui-bundle.js"></script>
<script>
const ui = SwaggerUIBundle({
url: "{% url schema_url %}",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "BaseLayout",
requestInterceptor: (request) => {
request.headers['X-CSRFToken'] = "{{ csrf_token }}"
return request;
}
})
</script>
</body>
</html>

26
sigi/urls.py

@ -14,7 +14,11 @@ Including another URLconf
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from rest_framework.schemas import get_schema_view
from drf_spectacular.views import (
SpectacularAPIView,
SpectacularSwaggerView,
SpectacularRedocView,
)
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
@ -47,29 +51,15 @@ urlpatterns = [
"api/doc/",
RedirectView.as_view(pattern_name="swagger-ui", permanent=False),
),
path(
"api/doc/schema.yaml",
get_schema_view(
title="SIGI rest API Schema",
description="REST API for SIGI opendata",
version="1.0.0",
),
name="openapi-schema",
),
path("api/schema/", SpectacularAPIView.as_view(), name="openapi-schema"),
path(
"api/doc/swagger-ui/",
TemplateView.as_view(
template_name="sigi/api/swagger-ui.html",
extra_context={"schema_url": "openapi-schema"},
),
SpectacularSwaggerView.as_view(url_name="openapi-schema"),
name="swagger-ui",
),
path(
"api/doc/redoc/",
TemplateView.as_view(
template_name="sigi/api/redoc.html",
extra_context={"schema_url": "openapi-schema"},
),
SpectacularRedocView.as_view(url_name="openapi-schema"),
name="redoc",
),
path("api/casas/", include("sigi.apps.casas.api_urls")),

Loading…
Cancel
Save