Categorías
Python

Python para los científicos sociales

 

Tabla de Contenidos

  • Objetivos
  • Introducción
  • websockets 101
  • Consumidores y GroupsTemplatesViewsTest
  • plantillas
  • Más Vistos
  • prueba
  • Autenticación de usuario
  • Entrar Alertas
  • cordura Compruebe
  • Pensamientos finales
  • plantillas
  • Vistas
  • prueba

en este tutorial, vamos a utilizar los canales de Django para crear una aplicación en tiempo real que actualizada una lista de usuarios al inicio de sesión y hacia fuera.

Con WebSockets (a través de los canales de Django) la gestión de la comunicación entre el cliente y el servidor, cada vez que un usuario está autenticado, un evento será transmitido a cada otro usuario conectado. pantalla de cada usuario va a cambiar de forma automática, sin que tengan que recargar sus navegadores.

NOTA: Nosotros recomendamos que tenga un poco de experiencia con Django antes de comenzar este tutorial. Además, usted debe estar familiarizado con el concepto de WebSockets. Bono

gratuito: Haga clic aquí para obtener acceso a una guía gratuita Django Recursos de Aprendizaje (PDF) que le muestra sugerencias y trucos, así como los errores comunes a evitar al crear aplicaciones web Python + Django.

nuestros usos de aplicación:

  • Python (V3.6.0)
  • Django (v1.10.5)
  • Django canales (v1.0.3)
  • Redis (v3.2.8) Objetivos

Al final de este tutorial, será capaz de …

Introducción

en primer lugar, crear un nuevo entorno virtual para aislar las dependencias de nuestro proyecto:

$ mkdir django-example-channels
$ cd django-example-channels
$ python3.6 -m venv env
$ source env/bin/activate
(env)$

Instalar Django, Canales de Django, y ASGI Redis, y luego crear un nuevo proyecto Django y aplicación :

(env)$ pip install django==1.10.5 channels==1.0.2 asgi_redis==1.0.0
(env)$ django-admin.py startproject example_channels
(env)$ cd example_channels
(env)$ python manage.py startapp example
(env)$ python manage.py migrate

NOTA: Durante el transcurso de este tutorial, vamos a crear una variedad de diferentes archivos y carpetas. Por favor refiérase a la estructura de carpetas del repositorio del proyecto si se queda atascado.

A continuación, descargar e instalar Redis. Si estás en un Mac, se recomienda usar Homebrew:

$ brew install redis

de inicio del servidor Redis en una nueva ventana de terminal y asegúrese de que se está ejecutando en el puerto por defecto, 6379. El número de puerto será importante cuando decimos a Django cómo para comunicarse con Redis.

Complete la instalación mediante la actualización en el archivo INSTALLED_APPS settings.py del proyecto:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'example',
]

continuación, configurar el CHANNEL_LAYERS mediante el establecimiento de un backend defecto y enrutamiento:

CHANNEL_LAYERS = {
'default': {
'BACKEND': 'asgi_redis.RedisChannelLayer',
'CONFIG': {
'hosts': [('localhost', 6379)],
},
'ROUTING': 'example_channels.routing.channel_routing',
}
}

Este utiliza un motor de Redis que también se necesita en la producción.

WebSockets 101

Normalmente, Django utiliza HTTP para comunicarse entre el cliente y el servidor:

diferencia de HTTP, el protocolo WebSockets permite la comunicación bidireccional, lo que significa que el servidor puede enviar datos al cliente sin ser impulsado por el usuario. Con HTTP, sólo el cliente que realiza una solicitud recibe una respuesta. Con WebSockets, el servidor puede comunicarse con varios clientes de forma simultánea. Como veremos más adelante en este tutorial, enviamos mensajes websockets utilizando los WS: // prefijo, en lugar de http: //.

NOTA: Antes de la inmersión en , revisar rápidamente la documentación Canales Conceptos.

Los consumidores y los grupos de

Let crear nuestro primer consumidor, que maneja las conexiones básicas entre el cliente y el servidor. Crear un nuevo archivo llamado example_channels / ejemplo / consumers.py :

from channels import Group

def ws_connect(message):
Group('users').add(message.reply_channel)

def ws_disconnect(message):
Group('users').discard(message.reply_channel)

Los consumidores son la contrapartida de las vistas de Django. Cualquier usuario que se conecta a nuestra aplicación se agrega al grupo de “usuarios” y recibirá los mensajes enviados por el servidor. Cuando el cliente se desconecta de nuestra aplicación, el canal se retira del grupo, y el usuario dejará de recibir mensajes.

A continuación, conjunto de amainó rutas, que funcionan casi de la misma manera que la configuración de Django URL, añadiendo el siguiente código en un nuevo archivo llamado example_channels / routing.py :

from channels.routing import route
from example.consumers import ws_connect, ws_disconnect

channel_routing = [
route('websocket.connect', ws_connect),
route('websocket.disconnect', ws_disconnect),
]

Así, definimos channel_routing en lugar de urlpatterns y la ruta () en lugar de url (). Tenga en cuenta que vinculamos nuestras funciones de consumo a WebSockets. escritura

plantillas

Vamos un poco de HTML que puede comunicarse con nuestro servidor a través de un WebSocket. Crear una carpeta “plantillas” dentro “ejemplo” y luego añadir un “ejemplo” carpeta dentro de “plantillas” – “example_channels / ejemplo / templates / ejemplo”.

Añadir un archivo _base.html :






Example Channels<itle><br /> </head><br /> <body></p> <div class="container"> <br /> {% block content %}{% endblock content %} </div> <p> <script src="//code.jquery.com/jquery-3.1.1.min.js"></script><br /> {% block script %}{% endblock script %}<br /> </body><br /> </html><br /> </code> </p> <p> Y <em> user_list.html </em>: </p> <p> <code>{% extends 'example/_base.html' %}</p> <p>{% block content %}{% endblock content %}</p> <p>{% block script %}<br /> <script> var socket = new WebSocket('ws://' + window.location.host + '/users/');</p> <p> socket.onopen = function open() { console.log('WebSockets connection created.'); };</p> <p> if (socket.readyState == WebSocket.OPEN) { socket.onopen(); } </script><br /> {% endblock script %}<br /> </code> </p> <p> Ahora, cuando el cliente abre correctamente una conexión con el servidor usando un WebSocket, veremos un mensaje de confirmación de impresión a la consola . </p> <h3> Vistas </h3> <p> configurar una vista de Django apoyo para hacer nuestra plantilla dentro <em> example_channels / ejemplo / views.py </em>: </p> <p> <code>from django.shortcuts import render</p> <p>def user_list(request):<br /> return render(request, 'example/user_list.html')<br /> </code> </p> <p> Añadir la URL a <em> example_channels / ejemplo / urls.py </em>: </p> <p> <code>from django.conf.urls import url<br /> from example.views import user_list</p> <p>urlpatterns = [<br /> url(r'^$', user_list, name='user_list'),<br /> ]<br /> </code> </p> <p> actualización de la URL del proyecto así en <em> example_channels / example_channels / urls.py </em>: </p> <p> <code>from django.conf.urls import include, url<br /> from django.contrib import admin</p> <p>urlpatterns = [<br /> url(r'^admin/', admin.site.urls),<br /> url(r'^', include('example.urls', namespace='example')),<br /> ]<br /> </code> </p> <h3> prueba </h3> <p> listo para la prueba? </p> <p> <code>(env)$ python manage.py runserver<br /> </code> </p> <p> <strong> NOTA: </strong> Puede ejecutar alternativamente python manage.py runserver –noworker y python manage.py runworker en dos terminales diferentes para probar los servidores de interfaz y de los trabajadores como dos procesos separados. Ambos métodos funcionan! </p> <p> Cuando visite http: // localhost: 8000 /, debería ver la letra mensaje de conexión al terminal: </p> <p> <code>[2017/02/19 23:24:57] HTTP GET / 200 [0.02, 127.0.0.1:52757]<br /> [2017/02/19 23:24:58] WebSocket HANDSHAKING /users/ [127.0.0.1:52789]<br /> [2017/02/19 23:25:03] WebSocket DISCONNECT /users/ [127.0.0.1:52789]<br /> </code> </p> <h2> Autenticación de usuario </h2> <p> Ahora que hemos demostrado que podemos abrir una conexión, nuestro siguiente paso es mango autenticacion de usuario. Recordemos: Queremos un usuario pueda iniciar sesión en nuestra aplicación y ver una lista de todos los otros usuarios que están suscritos al grupo de ese usuario. En primer lugar, necesitamos una forma para que los usuarios puedan crear cuentas e ingrese. Comience por la creación de una página de acceso simple que permitirá a los usuarios autenticarse con un nombre de usuario y contraseña. </p> <p> Crear un nuevo archivo llamado <em> log_in.html </em> dentro “example_channels / ejemplo / templates / ejemplo”: </p> <p> <code>{% extends 'example/_base.html' %}</p> <p>{% block content %}</p> <form action="{% url 'example:log_in' %}" method="post"> {% csrf_token %}<br /> {% for field in form %}</p> <div> {{ field.label_tag }}<br /> {{ field }} </div> <p> {% endfor %}<br /> <button type="submit">Log in</button><br /> </form> <p>Don't have an account? <a href="{% url 'example:sign_up' %}">Sign up!</a></p> <p>{% endblock content %}<br /> </code> </p> <p> A continuación, actualizar <em> example_channels / ejemplo / views.py </em> así: </p> <p> <code>from django.contrib.auth import login, logout<br /> from django.contrib.auth.forms import AuthenticationForm<br /> from django.core.urlresolvers import reverse<br /> from django.shortcuts import render, redirect</p> <p>def user_list(request):<br /> return render(request, 'example/user_list.html')</p> <p>def log_in(request):<br /> form = AuthenticationForm()<br /> if request.method == 'POST':<br /> form = AuthenticationForm(data=request.POST)<br /> if form.is_valid():<br /> login(request, form.get_user())<br /> return redirect(reverse('example:user_list'))<br /> else:<br /> print(form.errors)<br /> return render(request, 'example/log_in.html', {'form': form})</p> <p>def log_out(request):<br /> logout(request)<br /> return redirect(reverse('example:log_in'))<br /> </code> </p> <p> Django viene con formas que el apoyo funcionalidad de autenticación común. Podemos utilizar el AuthenticationForm para manejar la conexión del usuario. Esta forma comprueba el nombre de usuario y contraseña suministrada, a continuación, devuelve un objeto de usuario si no se encuentra un usuario validado. Registramos en el usuario validado y los redirija a nuestra página web. Un usuario también debe tener la capacidad de cerrar la sesión de la aplicación, por lo que se crea una vista de cierre de sesión que proporciona esa funcionalidad y luego toma la parte posterior de usuario a la pantalla de inicio de sesión. </p> <p> luego actualizar <em> example_channels / ejemplo / urls.py </em>: </p> <p> <code>from django.conf.urls import url<br /> from example.views import log_in, log_out, user_list</p> <p>urlpatterns = [<br /> url(r'^log_in/$', log_in, name='log_in'),<br /> url(r'^log_out/$', log_out, name='log_out'),<br /> url(r'^$', user_list, name='user_list')<br /> ]<br /> </code> </p> <p> También necesitamos una manera de crear nuevos usuarios. Crear una página de registro de la misma manera que el inicio de sesión mediante la adición de un nuevo archivo llamado <em> sign_up.html </em> a “example_channels / ejemplo / templates / ejemplo”: </p> <p> <code>{% extends 'example/_base.html' %}</p> <p>{% block content %}</p> <form action="{% url 'example:sign_up' %}" method="post"> {% csrf_token %}<br /> {% for field in form %}</p> <div> {{ field.label_tag }}<br /> {{ field }} </div> <p> {% endfor %}<br /> <button type="submit">Sign up</button></p> <p>Already have an account? <a href="{% url 'example:log_in' %}">Log in!</a></p> </p></form> <p>{% endblock content %}<br /> </code> </p> <p> en cuenta que la página de inicio de sesión tiene un enlace con el signo- hasta la página y la página de registro tiene un enlace de vuelta al inicio de sesión. </p> <p> Añadir la siguiente función a los puntos de vista: </p> <p> <code>def sign_up(request):<br /> form = UserCreationForm()<br /> if request.method == 'POST':<br /> form = UserCreationForm(data=request.POST)<br /> if form.is_valid():<br /> form.save()<br /> return redirect(reverse('example:log_in'))<br /> else:<br /> print(form.errors)<br /> return render(request, 'example/sign_up.html', {'form': form})<br /> </code> </p> <p> Utilizamos otra incorporado en forma de creación de usuarios. Después de la validación de formularios con éxito, redirigimos a la página de inicio de sesión. </p> <p> Asegúrese de importar la forma: example_channels </p> <p> <code>from django.contrib.auth.forms import AuthenticationForm, UserCreationForm<br /> </code> </p> <p> actualización <em> / ejemplo / urls.py </em> nuevo: </p> <p> <code>from django.conf.urls import url<br /> from example.views import log_in, log_out, sign_up, user_list</p> <p>urlpatterns = [<br /> url(r'^log_in/$', log_in, name='log_in'),<br /> url(r'^log_out/$', log_out, name='log_out'),<br /> url(r'^sign_up/$', sign_up, name='sign_up'),<br /> url(r'^$', user_list, name='user_list')<br /> ]<br /> </code> </p> <p> En este punto, tenemos que crear un usuario. Ejecutar el servidor y la visita http: // localhost: 8000 / sign_up / en su navegador. Rellenar el formulario con un nombre de usuario y una contraseña válidos y enviarlo a crear nuestro primer usuario. </p> <p> <strong> NOTA: </strong> Intente utilizar a Miguel como el nombre de usuario y johnson123 como la contraseña. </p> <p> El sign_up vista nos redirige a la vista log_in, y desde allí se puede autenticar a nuestro usuario recién creado. </p> <p> Después de iniciar sesión, podemos probar nuestras nuevas vistas de autenticación. </p> <p> Utilice el formulario de registro para crear varios usuarios nuevos en preparación para la siguiente sección. </p> <h2> Entrar Alertas </h2> <p> Tenemos trabajo básico de autenticación de usuario, pero que todavía tienen que mostrar una lista de usuarios y necesitamos el servidor para decirle al grupo cuando un usuario se conecta y out.We necesidad de editar nuestras funciones consumidores para que estos enviar un mensaje justo después de una conecta el cliente y justo antes de que un cliente se desconecta. Los datos de mensajes incluirán el estado de nombre de usuario y la conexión del usuario. </p> <p> actualización <em> example_channels / ejemplo / consumers.py </em> así: </p> <p> <code>import json<br /> from channels import Group<br /> from channels.auth import channel_session_user, channel_session_user_from_http</p> <p>@channel_session_user_from_http<br /> def ws_connect(message):<br /> Group('users').add(message.reply_channel)<br /> Group('users').send({<br /> 'text': json.dumps({<br /> 'username': message.user.username,<br /> 'is_logged_in': True<br /> })<br /> })</p> <p>@channel_session_user<br /> def ws_disconnect(message):<br /> Group('users').send({<br /> 'text': json.dumps({<br /> 'username': message.user.username,<br /> 'is_logged_in': False<br /> })<br /> })<br /> Group('users').discard(message.reply_channel)<br /> </code> </p> <p> en cuenta que hemos añadido a los decoradores de funciones para obtener el usuario de la sesión de Django. Además, todos los mensajes deberán ser JSON-serializable, por lo volcamos nuestros datos en una cadena JSON. </p> <p> A continuación, actualizar <em> example_channels / ejemplo / templates / ejemplo / user_list.html </em>: </p> <p> <code>{% extends 'example/_base.html' %}</p> <p>{% block content %}<br /> <a href="{% url 'example:log_out' %}">Log out</a><br /> </p> <ul> {% for user in users %}<br /> <!-- NOTE: We escape HTML to prevent XSS attacks. --></p> <li data-username="{{ user.username|escape }}"> {{ user.username|escape }}: {{ user.status|default:'Offline' }} </li> <p> {% endfor %} </ul> <p>{% endblock content %}</p> <p>{% block script %}<br /> <script> var socket = new WebSocket('ws://' + window.location.host + '/users/');</p> <p> socket.onopen = function open() { console.log('WebSockets connection created.'); };</p> <p> socket.onmessage = function message(event) { var data = JSON.parse(event.data); // NOTE: We escape JavaScript to prevent XSS attacks. var username = encodeURI(data['username']); var user = $('li').filter(function () { return $(this).data('username') == username; });</p> <p> if (data['is_logged_in']) { user.html(username + ': Online'); } else { user.html(username + ': Offline'); } };</p> <p> if (socket.readyState == WebSocket.OPEN) { socket.onopen(); } </script><br /> {% endblock script %}<br /> </code> </p> <p> En nuestra página web, nos ampliar nuestra lista de usuarios para mostrar una lista de usuarios. Almacenamos nombre de usuario de cada usuario como un atributo de datos para hacer más fácil para encontrar el artículo de usuario en el DOM. También vamos a añadir un detector de eventos en nuestro WebSocket que puede manejar los mensajes del servidor. Cuando recibimos un mensaje, que analizan los datos JSON, encontrar el elemento </p> <li> para el usuario dado, y actualización que el estado del usuario. </p> <p> Django no hace un seguimiento de si un usuario está conectado, por lo que necesitamos para crear un modelo simple de hacer eso por nosotros. Crear un modelo loggedInUser con una conexión de uno a uno a nuestro modelo de usuario en <em> example_channels / ejemplo / models.py </em>: </p> <p> <code>from django.conf import settings<br /> from django.db import models</p> <p>class LoggedInUser(models.Model):<br /> user = models.OneToOneField(<br /> settings.AUTH_USER_MODEL, related_name='logged_in_user')<br /> </code> </p> <p> Nuestra aplicación va a crear una instancia loggedInUser cuando un usuario inicia sesión en la aplicación, y se elimine la instancia cuando el usuario cierra la sesión. </p> <p> Hacer que la migración de esquemas y luego migrar la base de datos para aplicar los cambios. </p> <p> <code>(env)$ python manage.py makemigrations<br /> (env)$ python manage.py migrate<br /> </code> </p> <p> A continuación, actualizar nuestro punto de vista de lista de usuarios, en <em> example_channels / ejemplo / views.py </em>, para recuperar una lista de usuarios para hacer: </p> <p> <code>from django.contrib.auth import get_user_model, login, logout<br /> from django.contrib.auth.decorators import login_required<br /> from django.contrib.auth.forms import AuthenticationForm, UserCreationForm<br /> from django.core.urlresolvers import reverse<br /> from django.shortcuts import render, redirect</p> <p>User = get_user_model()</p> <p>@login_required(login_url='/log_in/')<br /> def user_list(request):<br /> """<br /> NOTE: This is fine for demonstration purposes, but this should be<br /> refactored before we deploy this app to production.<br /> Imagine how 100,000 users logging in and out of our app would affect<br /> the performance of this code!<br /> """<br /> users = User.objects.select_related('logged_in_user')<br /> for user in users:<br /> user.status = 'Online' if hasattr(user, 'logged_in_user') else 'Offline'<br /> return render(request, 'example/user_list.html', {'users': users})</p> <p>def log_in(request):<br /> form = AuthenticationForm()<br /> if request.method == 'POST':<br /> form = AuthenticationForm(data=request.POST)<br /> if form.is_valid():<br /> login(request, form.get_user())<br /> return redirect(reverse('example:user_list'))<br /> else:<br /> print(form.errors)<br /> return render(request, 'example/log_in.html', {'form': form})</p> <p>@login_required(login_url='/log_in/')<br /> def log_out(request):<br /> logout(request)<br /> return redirect(reverse('example:log_in'))</p> <p>def sign_up(request):<br /> form = UserCreationForm()<br /> if request.method == 'POST':<br /> form = UserCreationForm(data=request.POST)<br /> if form.is_valid():<br /> form.save()<br /> return redirect(reverse('example:log_in'))<br /> else:<br /> print(form.errors)<br /> return render(request, 'example/sign_up.html', {'form': form})<br /> </code> </p> <p> Si un usuario tiene un loggedInUser asociado, entonces grabamos el estado del usuario como “ en línea”, y si no es así, el usuario se encuentra‘fuera de línea’. También añadimos un decorador @login_required tanto a nuestra lista de usuarios y registrar los puntos de vista para restringir el acceso sólo a usuarios registrados. </p> <p> Añadir las importaciones, así: </p> <p> <code>from django.contrib.auth import get_user_model, login, logout<br /> from django.contrib.auth.decorators import login_required<br /> </code> </p> <p> En este punto, los usuarios pueden entrar y salir, lo que activará el servidor para enviar mensajes al cliente, pero no tenemos ninguna manera de saber qué usuarios están conectados cuando el usuario primero troncos. El usuario sólo ve las actualizaciones cuando cambia el estado de otro usuario. Aquí es donde el loggedInUser entra en juego, pero necesitamos una manera de crear una instancia de loggedInUser cuando un usuario se conecta, y luego eliminarlo cuando el usuario cierra la sesión. biblioteca </p> <p> El Django incluye una característica conocida como señales que transmite notificaciones cuando se producen ciertas acciones. Las aplicaciones pueden escuchar esas notificaciones y luego actuar sobre ellas. Podemos explotar dos útiles, una función de señales (user_logged_in y user_logged_out) para manejar nuestro comportamiento loggedInUser. </p> <p> dentro “example_channels / ejemplo”, añadir un nuevo archivo llamado <em> signals.py </em>: </p> <p> <code>from django.contrib.auth import user_logged_in, user_logged_out<br /> from django.dispatch import receiver<br /> from example.models import LoggedInUser</p> <p>@receiver(user_logged_in)<br /> def on_user_login(sender, **kwargs):<br /> LoggedInUser.objects.get_or_create(user=kwargs.get('user'))</p> <p>@receiver(user_logged_out)<br /> def on_user_logout(sender, **kwargs):<br /> LoggedInUser.objects.filter(user=kwargs.get('user')).delete()<br /> </code> </p> <p> Tenemos que hacer las señales disponibles en la configuración de nuestra aplicación, example_channels <em> / ejemplo / apps.py </em>: </p> <p> <code>from django.apps import AppConfig</p> <p>class ExampleConfig(AppConfig):<br /> name = 'example'</p> <p> def ready(self):<br /> import example.signals<br /> </code> </p> <p> actualización <em> example_channels / ejemplo / __ init__.py </em> así: </p> <p> <code>default_app_config = 'example.apps.ExampleConfig'<br /> </code> </p> <h2> cordura Entradas </h2> <p> Ahora hemos terminado la codificación y estamos listos para conectarse a nuestro servidor con múltiples usuarios para probar nuestra aplicación. </p> <p> Ejecutar el servidor de Django, inicie la sesión como un usuario, y visite la página principal. Deberíamos ver una lista de todos a los usuarios en nuestra aplicación, cada uno con un estado de “fuera de línea”. A continuación, abra una nueva ventana de incógnito e inicie sesión como un usuario diferente y ver ambas pantallas. Justo cuando inicie sesión, el navegador habitual actualiza el estado de usuario “en línea”. Desde nuestra ventana de incógnito, vemos que el usuario conectado también tiene un estado de “línea”. Podemos probar los WebSockets entrando y saliendo en nuestros diferentes dispositivos con diferentes usuarios. </p> </p> <p> <img src="https://eltecnofilo.es/wp-content/uploads/2020/03/django-channels-in-action.5dccd8179248.png"> </p> <p> Observando la consola del programador en el servidor de la actividad en nuestra terminal de cliente y, podemos confirmar que WebSocket se están formando conexiones cuando un usuario se conecta y destruidos cuando un usuario cierra la sesión. </p> <p> <code>[2017/02/20 00:15:23] HTTP POST /log_in/ 302 [0.07, 127.0.0.1:55393]<br /> [2017/02/20 00:15:23] HTTP GET / 200 [0.04, 127.0.0.1:55393]<br /> [2017/02/20 00:15:23] WebSocket HANDSHAKING /users/ [127.0.0.1:55414]<br /> [2017/02/20 00:15:23] WebSocket CONNECT /users/ [127.0.0.1:55414]<br /> [2017/02/20 00:15:25] HTTP GET /log_out/ 302 [0.01, 127.0.0.1:55393]<br /> [2017/02/20 00:15:26] HTTP GET /log_in/ 200 [0.02, 127.0.0.1:55393]<br /> [2017/02/20 00:15:26] WebSocket DISCONNECT /users/ [127.0.0.1:55414]<br /> </code> </p> <p> <strong> NOTA </strong>: También es posible usar ngrok para exponer el servidor local a Internet de forma segura. Hacer esto le permitirá golpear el servidor local desde varios dispositivos como el teléfono o la tableta. </p> <h2> Pensamientos finales </h2> <p> Hemos cubierto mucho en este tutorial – Canales de Django, WebSockets, la autenticación de usuario, señales, y un cierto desarrollo front-end. La toma de distancia principal es la siguiente: Canales amplía la funcionalidad de una aplicación tradicional de Django dejando a empujar los mensajes del servidor de grupos de usuarios a través de WebSockets. </p> <p> Esto es algo muy poderoso! </p> <p> pensar en algunas de las aplicaciones. Podemos crear salas de chat, juegos multijugador, y aplicaciones de colaboración que permiten a los usuarios comunicarse en tiempo real. Incluso las tareas cotidianas se mejoran con WebSockets. Por ejemplo, en lugar de solicitando periódicamente información al servidor para ver si una tarea de larga duración se ha completado, el servidor puede empujar una actualización de estado para el cliente cuando se termine. </p> <p> Este tutorial solo araña la superficie de lo que podemos hacer con los canales de Django, también. Explorar la documentación Canales Django y ver qué más se puede crear. Bono </p> <p> <strong> gratuito: </strong> Haga clic aquí para obtener acceso a una guía gratuita Django Recursos de Aprendizaje (PDF) que le muestra sugerencias y trucos, así como los errores comunes a evitar al crear aplicaciones web Python + Django. </p> <p> Grab el código final de los django-ejemplo canales de pases. ¡Salud! </p> </div><!-- .entry-content --> </div><!-- .post-inner --> <div class="section-inner"> </div><!-- .section-inner --> <nav class="pagination-single section-inner" aria-label="Entrada" role="navigation"> <hr class="styled-separator is-style-wide" aria-hidden="true" /> <div class="pagination-single-inner"> <a class="previous-post" href="https://eltecnofilo.es/inheritance-y-composicion-una-guia-python-oop/"> <span class="arrow" aria-hidden="true">←</span> <span class="title"><span class="title-inner">Inheritance y Composición: Una guía Python OOP</span></span> </a> <a class="next-post" href="https://eltecnofilo.es/python-gui-de-programacion-con-tkinter/"> <span class="arrow" aria-hidden="true">→</span> <span class="title"><span class="title-inner">Python GUI de programación con Tkinter</span></span> </a> </div><!-- .pagination-single-inner --> <hr class="styled-separator is-style-wide" aria-hidden="true" /> </nav><!-- .pagination-single --> <div class="comments-wrapper section-inner"> <div id="respond" class="comment-respond"> <h2 id="reply-title" class="comment-reply-title">Deja un comentario <small><a rel="nofollow" id="cancel-comment-reply-link" href="/python-para-los-cientificos-sociales/#respond" style="display:none;">Cancelar la respuesta</a></small></h2><form action="https://eltecnofilo.es/wp-comments-post.php" method="post" id="commentform" class="section-inner thin max-percentage" novalidate><p class="comment-notes"><span id="email-notes">Tu dirección de correo electrónico no será publicada.</span> Los campos obligatorios están marcados con <span class="required">*</span></p><p class="comment-form-comment"><label for="comment">Comentario</label> <textarea id="comment" name="comment" cols="45" rows="8" maxlength="65525" required="required"></textarea></p><p class="comment-form-author"><label for="author">Nombre <span class="required">*</span></label> <input id="author" name="author" type="text" value="" size="30" maxlength="245" required='required' /></p> <p class="comment-form-email"><label for="email">Correo electrónico <span class="required">*</span></label> <input id="email" name="email" type="email" value="" size="30" maxlength="100" aria-describedby="email-notes" required='required' /></p> <p class="comment-form-url"><label for="url">Web</label> <input id="url" name="url" type="url" value="" size="30" maxlength="200" /></p> <p class="comment-form-cookies-consent"><input id="wp-comment-cookies-consent" name="wp-comment-cookies-consent" type="checkbox" value="yes" /> <label for="wp-comment-cookies-consent">Guardar mi nombre, correo electrónico y sitio web en este navegador para la próxima vez que haga un comentario.</label></p> <p class="form-submit"><input name="submit" type="submit" id="submit" class="submit" value="Publicar el comentario" /> <input type='hidden' name='comment_post_ID' value='6806' id='comment_post_ID' /> <input type='hidden' name='comment_parent' id='comment_parent' value='0' /> </p></form> </div><!-- #respond --> </div><!-- .comments-wrapper --> </article><!-- .post --> </main><!-- #site-content --> <div class="footer-nav-widgets-wrapper header-footer-group"> <div class="footer-inner section-inner"> <aside class="footer-widgets-outer-wrapper" role="complementary"> <div class="footer-widgets-wrapper"> <div class="footer-widgets column-one grid-item"> <div class="widget widget_search"><div class="widget-content"><form role="search" method="get" class="search-form" action="https://eltecnofilo.es/"> <label for="search-form-2"> <span class="screen-reader-text">Buscar:</span> <input type="search" id="search-form-2" class="search-field" placeholder="Buscar …" value="" name="s" /> </label> <input type="submit" class="search-submit" value="Buscar" /> </form> </div></div> <div class="widget widget_recent_entries"><div class="widget-content"> <h2 class="widget-title subheading heading-size-3">Entradas recientes</h2> <ul> <li> <a href="https://eltecnofilo.es/vps-cloud-hosting/">VPS cloud hosting</a> </li> <li> <a href="https://eltecnofilo.es/versiones-de-ejecucion-de-python-en-acoplable-como-probar-la-ultima-release-python/">Versiones de ejecución de Python en acoplable: Cómo probar la última Release Python</a> </li> <li> <a href="https://eltecnofilo.es/leer-y-escribir-archivos-csv/">Leer y escribir archivos CSV</a> </li> <li> <a href="https://eltecnofilo.es/python-puro-vs-vs-numpy-tensorflow-comparacion-de-rendimiento/">Python puro vs vs NumPy TensorFlow Comparación de Rendimiento</a> </li> <li> <a href="https://eltecnofilo.es/estructura-python-programa-lexico/">Estructura Python Programa léxico</a> </li> </ul> </div></div><div class="widget widget_recent_comments"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Comentarios recientes</h2><ul id="recentcomments"><li class="recentcomments"><span class="comment-author-link"><a href="https://wordpress.org/" rel="external nofollow ugc" class="url">A WordPress Commenter</a></span> en <a href="https://eltecnofilo.es/hello-world/#comment-1">Hello world!</a></li></ul></div></div> </div> <div class="footer-widgets column-two grid-item"> <div class="widget widget_archive"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Archivos</h2> <ul> <li><a href='https://eltecnofilo.es/2020/04/'>abril 2020</a></li> <li><a href='https://eltecnofilo.es/2020/03/'>marzo 2020</a></li> <li><a href='https://eltecnofilo.es/2019/12/'>diciembre 2019</a></li> </ul> </div></div><div class="widget widget_categories"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Categorías</h2> <ul> <li class="cat-item cat-item-22"><a href="https://eltecnofilo.es/category/python/">Python</a> </li> <li class="cat-item cat-item-1"><a href="https://eltecnofilo.es/category/uncategorized/">Uncategorized</a> </li> </ul> </div></div><div class="widget widget_meta"><div class="widget-content"><h2 class="widget-title subheading heading-size-3">Meta</h2> <ul> <li><a rel="nofollow" href="https://eltecnofilo.es/wp-login.php">Acceder</a></li> <li><a href="https://eltecnofilo.es/feed/">Feed de entradas</a></li> <li><a href="https://eltecnofilo.es/comments/feed/">Feed de comentarios</a></li> <li><a href="https://es.wordpress.org/">WordPress.org</a></li> </ul> </div></div> </div> </div><!-- .footer-widgets-wrapper --> </aside><!-- .footer-widgets-outer-wrapper --> </div><!-- .footer-inner --> </div><!-- .footer-nav-widgets-wrapper --> <footer id="site-footer" role="contentinfo" class="header-footer-group"> <div class="section-inner"> <div class="footer-credits"> <p class="footer-copyright">© 2020 <a href="https://eltecnofilo.es/">My Blog</a> </p><!-- .footer-copyright --> <p class="powered-by-wordpress"> <a href="https://es.wordpress.org/"> Funciona gracias a WordPress </a> </p><!-- .powered-by-wordpress --> </div><!-- .footer-credits --> <a class="to-the-top" href="#site-header"> <span class="to-the-top-long"> Ir arriba <span class="arrow" aria-hidden="true">↑</span> </span><!-- .to-the-top-long --> <span class="to-the-top-short"> Subir <span class="arrow" aria-hidden="true">↑</span> </span><!-- .to-the-top-short --> </a><!-- .to-the-top --> </div><!-- .section-inner --> </footer><!-- #site-footer --> <script src='https://eltecnofilo.es/wp-includes/js/comment-reply.min.js?ver=5.3.4'></script> <script src='https://eltecnofilo.es/wp-includes/js/wp-embed.min.js?ver=5.3.4'></script> <script> /(trident|msie)/i.test(navigator.userAgent)&&document.getElementById&&window.addEventListener&&window.addEventListener("hashchange",function(){var t,e=location.hash.substring(1);/^[A-z0-9_-]+$/.test(e)&&(t=document.getElementById(e))&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())},!1); </script> </body> </html>