Browse Source

impl channels tutorial 1 e 2

pull/2585/head
Leandro Roberto 7 years ago
parent
commit
c8b0b78d66
  1. 5
      requirements/requirements.txt
  2. 48
      sapl/base/consumers.py
  3. 7
      sapl/base/routing.py
  4. 7
      sapl/base/urls.py
  5. 101
      sapl/base/views.py
  6. 13
      sapl/routing.py
  7. 18
      sapl/settings.py
  8. 27
      sapl/templates/base/channel_index.html
  9. 47
      sapl/templates/base/channel_room.html
  10. 6
      setup.py

5
requirements/requirements.txt

@ -15,7 +15,6 @@ django-extensions==2.1.4
django-image-cropping==1.2
django-webpack-loader==0.6.0
drf-yasg==1.13.0
channels==2.1.7
easy-thumbnails==2.5
python-decouple==3.1
psycopg2-binary==2.7.6.1
@ -34,5 +33,9 @@ whoosh==2.7.4
pyoai==2.5.0
daphne==2.2.5
channels_redis==2.3.3
channels==2.1.7
git+git://github.com/interlegis/trml2pdf.git
git+git://github.com/interlegis/django-admin-bootstrapped

48
sapl/base/consumers.py

@ -0,0 +1,48 @@
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
# Join room group
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
self.accept()
def disconnect(self, close_code):
# Leave room group
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
# Receive message from room group
def chat_message(self, event):
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps({
'message': message
}))

7
sapl/base/routing.py

@ -0,0 +1,7 @@
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer),
]

7
sapl/base/urls.py

@ -8,6 +8,7 @@ from django.contrib.auth.views import (password_reset, password_reset_complete,
password_reset_done)
from django.views.generic.base import RedirectView, TemplateView
from sapl import base
from sapl.base.views import AutorCrud, ConfirmarEmailView, TipoAutorCrud
from sapl.settings import EMAIL_SEND_USER, MEDIA_URL
@ -97,7 +98,7 @@ urlpatterns = [
url(r'^sistema/app-config/', include(AppConfigCrud.get_urls())),
# TODO mover estas telas para a app 'relatorios'
url(r'^sistema/relatorios/$',
url(r'^sistema/relatorios/$',
RelatoriosListView.as_view(), name='relatorios_list'),
url(r'^sistema/relatorios/materia-por-autor$',
RelatorioMateriasPorAutorView.as_view(), name='materia_por_autor'),
@ -185,4 +186,8 @@ urlpatterns = [
LogotipoView.as_view(), name='logotipo'),
url(r'^channel$', base.views.chanel_index, name='channel_index'),
url(r'^channel/(?P<room_name>[^/]+)/$',
base.views.chanel_room, name='channel_room'),
] + recuperar_senha + alterar_senha + admin_user

101
sapl/base/views.py

@ -1,6 +1,7 @@
import collections
import itertools
import datetime
import itertools
import json
import logging
import os
@ -15,11 +16,13 @@ from django.core.urlresolvers import reverse, reverse_lazy
from django.db import connection
from django.db.models import Count, Q, ProtectedError
from django.http import Http404, HttpResponseRedirect
from django.shortcuts import render
from django.template import TemplateDoesNotExist
from django.template.loader import get_template
from django.utils import timezone
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_decode, urlsafe_base64_encode
from django.utils.safestring import mark_safe
from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic import (CreateView, DeleteView, FormView, ListView,
@ -61,6 +64,16 @@ from .forms import (AlterarSenhaForm, CasaLegislativaForm,
from .models import AppConfig, CasaLegislativa
def chanel_index(request):
return render(request, 'base/channel_index.html', {})
def chanel_room(request, room_name):
return render(request, 'base/channel_room.html', {
'room_name_json': mark_safe(json.dumps(room_name))
})
def filtra_url_materias_em_tramitacao(qr, qs, campo_url, local_ou_status):
id_materias = []
filtro_url = qr[campo_url]
@ -289,7 +302,7 @@ class AutorCrud(CrudAux):
class RelatoriosListView(TemplateView):
template_name='base/relatorios_list.html'
template_name = 'base/relatorios_list.html'
def get_context_data(self, **kwargs):
context = super(TemplateView, self).get_context_data(**kwargs)
@ -799,15 +812,15 @@ class RelatorioNormasPublicadasMesView(FilterView):
context['ano'] = self.request.GET['ano']
normas_mes = collections.OrderedDict()
meses = {1: 'Janeiro', 2: 'Fevereiro', 3:'Março', 4: 'Abril', 5: 'Maio', 6:'Junho',
7: 'Julho', 8: 'Agosto', 9:'Setembro', 10:'Outubro', 11:'Novembro', 12:'Dezembro'}
meses = {1: 'Janeiro', 2: 'Fevereiro', 3: 'Março', 4: 'Abril', 5: 'Maio', 6: 'Junho',
7: 'Julho', 8: 'Agosto', 9: 'Setembro', 10: 'Outubro', 11: 'Novembro', 12: 'Dezembro'}
for norma in context['object_list']:
if not meses[norma.data.month] in normas_mes:
normas_mes[meses[norma.data.month]] = []
normas_mes[meses[norma.data.month]].append(norma)
context['normas_mes'] = normas_mes
quant_normas_mes = {}
for key in normas_mes.keys():
quant_normas_mes[key] = len(normas_mes[key])
@ -833,19 +846,20 @@ class RelatorioNormasVigenciaView(FilterView):
vigencia = kwargs['data']['vigencia']
if ano:
qs = qs.filter(ano=ano)
if vigencia == 'True':
qs_dt_not_null = qs.filter(data_vigencia__isnull=True)
qs = (qs_dt_not_null | qs.filter(data_vigencia__gte=datetime.datetime.now().date())).distinct()
qs = (qs_dt_not_null | qs.filter(
data_vigencia__gte=datetime.datetime.now().date())).distinct()
else:
qs = qs.filter(data_vigencia__lt=datetime.datetime.now().date())
qs = qs.filter(
data_vigencia__lt=datetime.datetime.now().date())
kwargs.update({
'queryset': qs
})
return kwargs
def get_context_data(self, **kwargs):
context = super(RelatorioNormasVigenciaView,
self).get_context_data(**kwargs)
@ -855,17 +869,20 @@ class RelatorioNormasVigenciaView(FilterView):
if not self.filterset.form.is_valid():
return context
normas_totais = NormaJuridica.objects.filter(ano=self.request.GET['ano'])
normas_totais = NormaJuridica.objects.filter(
ano=self.request.GET['ano'])
context['quant_total'] = len(normas_totais)
if self.request.GET['vigencia'] == 'True':
context['vigencia'] = 'Vigente'
context['quant_vigente'] = len(context['object_list'])
context['quant_nao_vigente'] = context['quant_total'] - context['quant_vigente']
context['quant_nao_vigente'] = context['quant_total'] - \
context['quant_vigente']
else:
context['vigencia'] = 'Não vigente'
context['quant_nao_vigente'] = len(context['object_list'])
context['quant_vigente'] = context['quant_total'] - context['quant_nao_vigente']
context['quant_vigente'] = context['quant_total'] - \
context['quant_nao_vigente']
qr = self.request.GET.copy()
context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
@ -891,7 +908,7 @@ class EstatisticasAcessoNormas(TemplateView):
return self.render_to_response(context)
context['ano'] = self.request.GET['ano']
query = '''
select norma_id, ano, extract(month from horario_acesso) as mes, count(*)
from norma_normaestatisticas
@ -904,20 +921,21 @@ class EstatisticasAcessoNormas(TemplateView):
rows = cursor.fetchall()
normas_mes = collections.OrderedDict()
meses = {1: 'Janeiro', 2: 'Fevereiro', 3:'Março', 4: 'Abril', 5: 'Maio', 6:'Junho',
7: 'Julho', 8: 'Agosto', 9:'Setembro', 10:'Outubro', 11:'Novembro', 12:'Dezembro'}
meses = {1: 'Janeiro', 2: 'Fevereiro', 3: 'Março', 4: 'Abril', 5: 'Maio', 6: 'Junho',
7: 'Julho', 8: 'Agosto', 9: 'Setembro', 10: 'Outubro', 11: 'Novembro', 12: 'Dezembro'}
for row in rows:
if not meses[int(row[2])] in normas_mes:
normas_mes[meses[int(row[2])]] = []
norma_est = [NormaJuridica.objects.get(id=row[0]), row[3]]
normas_mes[meses[int(row[2])]].append(norma_est)
# Ordena por acesso e limita em 5
for n in normas_mes:
sorted_by_value = sorted(normas_mes[n], key=lambda kv: kv[1], reverse=True)
sorted_by_value = sorted(
normas_mes[n], key=lambda kv: kv[1], reverse=True)
normas_mes[n] = sorted_by_value[0:5]
context['normas_mes'] = normas_mes
return self.render_to_response(context)
@ -952,8 +970,8 @@ class ListarInconsistenciasView(PermissionRequiredMixin, ListView):
tabela.append(
('mandato_sem_data_inicio',
'Mandatos sem data inicial',
len(mandato_sem_data_inicio())
)
len(mandato_sem_data_inicio())
)
)
tabela.append(
('parlamentares_mandatos_intersecao',
@ -977,7 +995,7 @@ class ListarInconsistenciasView(PermissionRequiredMixin, ListView):
('legislatura_infindavel',
'Legislaturas sem data fim',
len(legislatura_infindavel())
)
)
)
return tabela
@ -1000,14 +1018,14 @@ class ListarLegislaturaInfindavelView(PermissionRequiredMixin, ListView):
def get_context_data(self, **kwargs):
context = super(
ListarLegislaturaInfindavelView, self
).get_context_data(**kwargs)
).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhuma encontrada.'
] = 'Nenhuma encontrada.'
return context
@ -1050,14 +1068,14 @@ class ListarBancadaComissaoAutorExternoView(PermissionRequiredMixin, ListView):
def get_context_data(self, **kwargs):
context = super(
ListarBancadaComissaoAutorExternoView, self
).get_context_data(**kwargs)
).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrado.'
] = 'Nenhum encontrado.'
return context
@ -1084,7 +1102,7 @@ class ListarAutoresDuplicadosView(PermissionRequiredMixin, ListView):
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrado.'
] = 'Nenhum encontrado.'
return context
@ -1097,10 +1115,12 @@ def parlamentares_mandatos_intersecao():
for c in combinacoes:
data_inicio_mandato1 = c[0].data_inicio_mandato
data_fim_mandato1 = c[0].data_fim_mandato if c[0].data_fim_mandato else timezone.now().date()
data_fim_mandato1 = c[0].data_fim_mandato if c[0].data_fim_mandato else timezone.now(
).date()
data_inicio_mandato2 = c[1].data_inicio_mandato
data_fim_mandato2 = c[1].data_fim_mandato if c[1].data_fim_mandato else timezone.now().date()
data_fim_mandato2 = c[1].data_fim_mandato if c[1].data_fim_mandato else timezone.now(
).date()
if data_inicio_mandato1 and data_inicio_mandato2:
exists = intervalos_tem_intersecao(
@ -1131,7 +1151,7 @@ class ListarParlMandatosIntersecaoView(PermissionRequiredMixin, ListView):
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrado.'
] = 'Nenhum encontrado.'
return context
@ -1152,14 +1172,14 @@ class ListarMandatoSemDataInicioView(PermissionRequiredMixin, ListView):
def get_context_data(self, **kwargs):
context = super(
ListarMandatoSemDataInicioView, self
).get_context_data(**kwargs)
).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrada.'
] = 'Nenhum encontrada.'
return context
@ -1187,27 +1207,27 @@ class ListarMatProtocoloInexistenteView(PermissionRequiredMixin, ListView):
def get_context_data(self, **kwargs):
context = super(
ListarMatProtocoloInexistenteView, self
).get_context_data(**kwargs)
).get_context_data(**kwargs)
paginator = context['paginator']
page_obj = context['page_obj']
context['page_range'] = make_pagination(
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhuma encontrada.'
] = 'Nenhuma encontrada.'
return context
def protocolos_com_materias():
protocolos = {}
for m in MateriaLegislativa.objects.filter(numero_protocolo__isnull=False).order_by('-ano', 'numero_protocolo'):
if Protocolo.objects.filter(numero=m.numero_protocolo, ano=m.ano).exists():
key = "{}/{}".format(m.numero_protocolo, m.ano)
val = protocolos.get(key, list())
val.append(m)
protocolos[key] = val
return [(v[0], len(v)) for (k, v) in protocolos.items() if len(v) > 1]
@ -1230,7 +1250,7 @@ class ListarProtocolosComMateriasView(PermissionRequiredMixin, ListView):
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrado.'
] = 'Nenhum encontrado.'
return context
@ -1244,6 +1264,7 @@ def protocolos_duplicados():
return [(v[0], len(v)) for (k, v) in protocolos.items() if len(v) > 1]
class ListarProtocolosDuplicadosView(PermissionRequiredMixin, ListView):
model = get_user_model()
template_name = 'base/protocolos_duplicados.html'
@ -1263,7 +1284,7 @@ class ListarProtocolosDuplicadosView(PermissionRequiredMixin, ListView):
page_obj.number, paginator.num_pages)
context[
'NO_ENTRIES_MSG'
] = 'Nenhum encontrado.'
] = 'Nenhum encontrado.'
return context

13
sapl/routing.py

@ -1,5 +1,12 @@
from channels.routing import ProtocolTypeRouter
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import sapl.base.routing
application = ProtocolTypeRouter({
# Empty for now (http->django views is added by default)
})
'websocket': AuthMiddlewareStack(
URLRouter(
sapl.base.routing.websocket_urlpatterns
)
),
})

18
sapl/settings.py

@ -207,6 +207,14 @@ TEMPLATES = [
WSGI_APPLICATION = 'sapl.wsgi.application'
ASGI_APPLICATION = "sapl.routing.application"
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
# Database
# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
@ -347,11 +355,11 @@ LOGGING = {
'level': 'INFO',
'propagate': True,
},
'django': {
'handlers': ['applogfile'],
'level': 'ERROR',
'propagate': True,
},
#'django': {
# 'handlers': ['applogfile'],
# 'level': 'ERROR',
# 'propagate': True,
#},
}
}

27
sapl/templates/base/channel_index.html

@ -0,0 +1,27 @@
<!-- chat/templates/chat/index.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Chat Rooms</title>
</head>
<body>
What chat room would you like to enter?<br/>
<input id="room-name-input" type="text" size="100"/><br/>
<input id="room-name-submit" type="button" value="Enter"/>
<script>
document.querySelector('#room-name-input').focus();
document.querySelector('#room-name-input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#room-name-submit').click();
}
};
document.querySelector('#room-name-submit').onclick = function(e) {
var roomName = document.querySelector('#room-name-input').value;
window.location.pathname = '/channel/' + roomName + '/';
};
</script>
</body>
</html>

47
sapl/templates/base/channel_room.html

@ -0,0 +1,47 @@
<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Chat Room</title>
</head>
<body>
<textarea id="chat-log" cols="100" rows="20"></textarea><br/>
<input id="chat-message-input" type="text" size="100"/><br/>
<input id="chat-message-submit" type="button" value="Send"/>
</body>
<script>
var roomName = {{ room_name_json }};
var chatSocket = new WebSocket(
'ws://' + window.location.host +
'/ws/chat/' + roomName + '/');
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
document.querySelector('#chat-log').value += (message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#chat-message-input').focus();
document.querySelector('#chat-message-input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#chat-message-submit').click();
}
};
document.querySelector('#chat-message-submit').onclick = function(e) {
var messageInputDom = document.querySelector('#chat-message-input');
var message = messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
</script>
</html>

6
setup.py

@ -44,13 +44,7 @@ install_requires = [
'channels==2.1.7',
# 'git+git://github.com/interlegis/trml2pdf.git',
<<<<<<< HEAD
# 'git+git://github.com/interlegis/django-admin-bootstrapped',
=======
# 'git+git://github.com/jasperlittle/django-rest-framework-docs',
# 'git+git://github.com/interlegis/django-admin-bootstrapped',
>>>>>>> config inicial
]
setup(
name='interlegis-sapl',

Loading…
Cancel
Save