Escribir un chat en Python y Django

Buenas tardes amigos. En previsión del inicio del curso Python Web Developer, tradicionalmente compartimos una traducción útil con usted.




Verá una guía frente a usted que le dice cómo crear una aplicación de chat en Python, Django y React.

A diferencia de otros manuales, no uso Python y Django para las conexiones WebSocket. A pesar de que suena genial desde un punto de vista técnico, funciona bastante lento y en sí mismo es costoso, especialmente si tiene un número decente de usuarios. Lenguajes como C ++, Go y Elixir hacen un trabajo mucho mejor del núcleo del chat.

En este tutorial, utilizaremos Stream, una API de chat que se encarga de las conexiones WebSocket y otros aspectos pesados ​​utilizando Go, Raft y RocksDB.

Contenido:

  • Reaccionar interfaz de chat de demostración
  • Instalar Django / Python
  • Autorización de usuario
  • Django rest framework
  • Generación de tokens para acceder al servidor de Stream de chat
  • Integración de Autorización de Reacción
  • Enviar mensajes desde un servidor Python
  • Últimos pensamientos

Repositorio de Github con código de un artículo

¡Empecemos!

Paso 1: Reaccionar la interfaz de chat de demostración


Antes de comenzar a pensar en la parte de Python, implementemos una interfaz simple en React para que tengamos algo hermoso y visual:

$ yarn global add create-react-app $ brew install node && brew install yarn # skip if installed $ create-react-app chat-frontend $ cd chat-frontend $ yarn add stream-chat-react 

Reemplace el código en src/App.js con lo siguiente:

 import React from "react"; import { Chat, Channel, ChannelHeader, Thread, Window } from "stream-chat-react"; import { MessageList, MessageInput } from "stream-chat-react"; import { StreamChat } from "stream-chat"; import "stream-chat-react/dist/css/index.css"; const chatClient = new StreamChat("qk4nn7rpcn75"); // Demo Stream Key const userToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoiY29vbC1za3ktOSJ9.mhikC6HPqPKoCP4aHHfuH9dFgPQ2Fth5QoRAfolJjC4"; // Demo Stream Token chatClient.setUser( { id: "cool-sky-9", name: "Cool sky", image: "https://getstream.io/random_svg/?id=cool-sky-9&name=Cool+sky" }, userToken ); const channel = chatClient.channel("messaging", "godevs", { // image and name are required, however, you can add custom fields image: "https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png", name: "Talk about Go" }); const App = () => ( <Chat client={chatClient} theme={"messaging light"}> <Channel channel={channel}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); export default App; 

¡Ahora, use el comando de yarn start para ver el chat en acción!

Paso 2: Instale Django / Python (omita este paso si ya tiene todo lo que necesita)


Asegúrese de tener Python 3.7 y se está ejecutando:

 $ brew install python3 $ pip install virtualenv virtualenvwrapper $ export WORKON_HOME=~/Envs $ source /usr/local/bin/virtualenvwrapper.sh $ mkvirtualenv chatexample -p `which python3` $ workon chatexample 

Si no funciona, intente con el siguiente código:

 $ python3 -m venv chatexample $ source chatexample/bin/activate 

Ahora que está en su entorno virtual, debería ver python 3 al inicio:

 $ python --version 

Para crear un nuevo proyecto en Django, use el siguiente código:

 $ pip install django $ django-admin startproject mychat 

Y ejecuta la aplicación:

 $ cd mychat $ python manage.py runserver 

Ahora, cuando abra http://localhost:8000 , verá lo siguiente:



Paso 3: Autorización de usuario


El siguiente paso es configurar la autorización del usuario en Django.

 $ python manage.py migrate $ python manage.py createsuperuser $ python manage.py runserver 

Vaya a http://localhost:8000/admin/ e inicie sesión. Voila!

Verá una pestaña de administrador similar a la siguiente:



Paso 4: Django Rest Framework


Uno de mis paquetes favoritos para integrar React con Django es el Django Rest Framework. Para que funcione, debe crear puntos finales para:

  • Registro de usuario
  • Inicio de sesión de usuario.

Podríamos hacerlos nosotros mismos, sin embargo, hay un paquete llamado Djoser que resuelve este problema. Configurará los puntos finales API necesarios para el registro de usuarios, inicio de sesión, restablecimiento de contraseña, etc.

Para instalar Djoser, use lo siguiente:

 $ pip install djangorestframework djoser 

Después de eso, edite urls.py y cambie el contenido del archivo de la siguiente manera:

 from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include('djoser.urls')), path('auth/', include('djoser.urls.authtoken')), ] 

Cuando termine, edite settings.py y realice cambios:

 INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'djoser', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.TokenAuthentication', ) } 

Para obtener más información sobre los puntos finales de API que proporciona Djoser, consulte lo siguiente:

https://djoser.readthedocs.io/en/latest/sample_usage.html

Ahora continuemos y pruebe el punto final de registro:

 $ curl -X POST http://127.0.0.1:8000/auth/users/ --data 'username=djoser&password=alpine12' 

Paso 5: generar tokens para acceder al servidor de Stream de chat


Ahora necesitamos configurar las vistas de Djoser para generar tokens de Stream. Entonces comencemos.
Organicemos un poco nuestros archivos y creemos una carpeta de aplicación de chat en nuestro proyecto (asegúrese de estar en el directorio correcto):

 $ python manage.py startapp auth 

Instalar stream-chat:

 $ pip install stream-chat 

Cree un serializador personalizado en auth/serializers.py usando la siguiente lógica:

 from djoser.serializers import TokenSerializer from rest_framework import serializers from djoser.conf import settings as djoser_settings from stream_chat import StreamChat from django.conf import settings class StreamTokenSerializer(TokenSerializer): stream_token = serializers.SerializerMethodField() class Meta: model = djoser_settings.TOKEN_MODEL fields = ('auth_token','stream_token') def get_stream_token(self, obj): client = StreamChat(api_key=settings.STREAM_API_KEY, api_secret=settings.STREAM_API_SECRET) token = client.create_token(obj.user.id) return token 

Por último, use un serializador personalizado para actualizar el archivo settings.py :

 STREAM_API_KEY = YOUR_STREAM_API_KEY # https://getstream.io/dashboard/ STREAM_API_SECRET = YOUR_STREAM_API_SECRET DJOSER = { 'SERIALIZERS': { 'token': 'auth.serializers.StreamTokenSerializer', } } 

Reiniciar la migración:

 $ python manage.py migrate 

Para verificar que funciona, vaya al punto final utilizando una solicitud POST:

 $ curl -X POST http://127.0.0.1:8000/auth/token/login/ --data 'username=djoser&password=alpine12' 

El retorno debería ser auth_token y stream_token .

Paso 6: Integrar la autorización de reacción


Por razones obvias, agregar autorización a la interfaz es un paso importante. En nuestro caso, esto es especialmente útil, ya que podemos extraer el token de usuario de la API (que se ejecuta en Python) y usarlo dinámicamente al enviar mensajes.

Primero, instale CORS, el paquete de middleware para Django:

 $ pip install django-cors-headers 

Luego modifique el archivo settings.py para referirse al djors-cors-header :

 INSTALLED_APPS = ( ... 'corsheaders', ... ) MIDDLEWARE = [ ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... ] 

Finalmente, agregue lo siguiente a su archivo settings.py :

 CORS_ORIGIN_ALLOW_ALL = True 

El siguiente paso requerirá algunos cambios en su interfaz. Para comenzar, deberá asegurarse de tener todas las dependencias instaladas a través de hilo:

 $ yarn add axios react-dom react-router-dom 

A continuación, cree los siguientes archivos en el directorio src/ :

  • AuthedRoute.js
  • UnauthedRoute.js
  • withSession.js
  • Login.js
  • Chat.js

App.js


 import React from "react"; import { BrowserRouter as Router, Switch } from "react-router-dom"; import Chat from "./Chat"; import Login from "./Login"; import UnauthedRoute from "./UnauthedRoute"; import AuthedRoute from "./AuthedRoute"; const App = () => ( <Router> <Switch> <UnauthedRoute path="/auth/login" component={Login} /> <AuthedRoute path="/" component={Chat} /> </Switch> </Router> ); export default App; 

AuthedRoute.js


 import React from "react"; import { Redirect, Route } from "react-router-dom"; const AuthedRoute = ({ component: Component, loading, ...rest }) => { const isAuthed = Boolean(localStorage.getItem("token")); return ( <Route {...rest} render={props => loading ? ( <p>Loading...</p> ) : isAuthed ? ( <Component history={props.history} {...rest} /> ) : ( <Redirect to={{ pathname: "/auth/login", state: { next: props.location } }} /> ) } /> ); }; export default AuthedRoute; 

UnauthedRoute.js


 import React from "react"; import { Redirect, Route } from "react-router-dom"; const AuthedRoute = ({ component: Component, loading, ...rest }) => { const isAuthed = Boolean(localStorage.getItem("token")); return ( <Route {...rest} render={props => loading ? ( <p>Loading...</p> ) : !isAuthed ? ( <Component history={props.history} {...rest} /> ) : ( <Redirect to={{ pathname: "/" }} /> ) } /> ); }; export default AuthedRoute; 

withSession.js


 import React from "react"; import { withRouter } from "react-router"; export default (Component, unAuthed = false) => { const WithSession = ({ user = {}, streamToken, ...props }) => user.id || unAuthed ? ( <Component userId={user.id} user={user} session={window.streamSession} {...props} /> ) : ( <Component {...props} /> ); return withRouter(WithSession); }; 

Login.js


 import React, { Component } from "react"; import axios from "axios"; class Login extends Component { constructor(props) { super(props); this.state = { loading: false, email: "", password: "" }; this.initStream = this.initStream.bind(this); } async initStream() { await this.setState({ loading: true }); const base = "http://localhost:8000"; const formData = new FormData(); formData.set("username", this.state.email); formData.set("password", this.state.password); const registration = await axios({ method: "POST", url: `${base}/auth/users/`, data: formData, config: { headers: { "Content-Type": "multipart/form-data" } } }); const authorization = await axios({ method: "POST", url: `${base}/auth/token/login/`, data: formData, config: { headers: { "Content-Type": "multipart/form-data" } } }); localStorage.setItem("token", authorization.data.stream_token); await this.setState({ loading: false }); this.props.history.push("/"); } handleChange = e => { this.setState({ [e.target.name]: e.target.value }); }; render() { return ( <div className="login-root"> <div className="login-card"> <h4>Login</h4> <input type="text" placeholder="Email" name="email" onChange={e => this.handleChange(e)} /> <input type="password" placeholder="Password" name="password" onChange={e => this.handleChange(e)} /> <button onClick={this.initStream}>Submit</button> </div> </div> ); } } export default Login; 

Chat.js


 import React, { Component } from "react"; import { Chat, Channel, ChannelHeader, Thread, Window } from "stream-chat-react"; import { MessageList, MessageInput } from "stream-chat-react"; import { StreamChat } from "stream-chat"; import "stream-chat-react/dist/css/index.css"; class App extends Component { constructor(props) { super(props); this.client = new StreamChat("<YOUR_STREAM_APP_ID>"); this.client.setUser( { id: "cool-sky-9", name: "Cool Sky", image: "https://getstream.io/random_svg/?id=cool-sky-9&name=Cool+sky" }, localStorage.getItem("token") ); this.channel = this.client.channel("messaging", "godevs", { image: "https://cdn.chrisshort.net/testing-certificate-chains-in-go/GOPHER_MIC_DROP.png", name: "Talk about Go" }); } render() { return ( <Chat client={this.client} theme={"messaging light"}> <Channel channel={this.channel}> <Window> <ChannelHeader /> <MessageList /> <MessageInput /> </Window> <Thread /> </Channel> </Chat> ); } } export default App; 

Asegúrese de reemplazar YOUR_STREAM_APP_ID con el ID válido de la aplicación Stream, que se puede encontrar en el tablero .

Reinicie la aplicación en el front end y verá la autorización. Ingrese su dirección de correo electrónico y contraseña, el token será solicitado y almacenado en el almacenamiento local.

Paso 7: Enviar mensajes desde el servidor Python


Si de repente quieres crear una API de chat usando tu backend en Python, hay un comando especial que puedes usar.

Asegúrese de que las aplicaciones instaladas se vean así en settings.py :

 INSTALLED_APPS = [ 'corsheaders', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'rest_framework.authtoken', 'djoser', ] 

A continuación, cree el directorio chat / management / command. En este directorio, agregue un archivo llamado broadcast.py con el siguiente contenido:

 from django.core.management.base import BaseCommand, CommandError from django.conf import settings from stream_chat import StreamChat class Command(BaseCommand): help = 'Broadcast the message on your channel' def add_arguments(self, parser): parser.add_argument('--message') def handle(self, *args, **options): client = StreamChat(api_key=settings.STREAM_API_KEY, api_secret=settings.STREAM_API_SECRET) client.update_user({"id": "system", "name": "The Server"}) channel = client.channel("messaging", "kung-fu") channel.create("system") response = channel.send_message({"text": "AMA about kung-fu"}, 'system') self.stdout.write(self.style.SUCCESS('Successfully posted a message with id "%s"' % response['message']['id'])) 

Puede intentar enviar un mensaje de chat de la siguiente manera:

 $ python manage.py broadcast --message hello 

Y verá esta respuesta:



Últimos pensamientos


¡Espero que hayas disfrutado este tutorial sobre cómo crear una aplicación de chat en Django, Python y React!

Para un recorrido interactivo de Stream Chat , consulte nuestra guía sobre cómo crear una API en el sitio web de Stream . Si le gusta explorar el código de los componentes de Stream Chat React, puede encontrar la documentación completa aquí . Si desea crear un chat en Stream, nos complace ofrecer varios SDK para idiomas y marcos populares hasta el último iOS (Swift) .

Eso es todo. Nos vemos en el seminario web abierto sobre Trucos de Django ORM .

Source: https://habr.com/ru/post/475672/


All Articles