Écrire un chat en Python et Django

Bonjour mes amis. En prévision du début du cours Python Web Developer, nous partageons traditionnellement une traduction utile avec vous.




Vous voyez un guide devant vous qui vous explique comment créer une application de chat en Python, Django et React.

Contrairement à d'autres manuels, je n'utilise pas Python et Django pour les connexions WebSocket. Malgré le fait que cela semble cool d'un point de vue technique, cela fonctionne plutôt lentement et en soi, c'est cher, surtout si vous avez un nombre décent d'utilisateurs. Les langages comme C ++, Go et Elixir font un bien meilleur travail du noyau de chat.

Dans ce tutoriel, nous utiliserons Stream, une API de chat qui prend en charge les connexions WebSocket et d'autres aspects lourds en utilisant Go, Raft et RocksDB.

Contenu:

  • Interface de chat de dĂ©monstration React
  • Installez Django / Python
  • Autorisation utilisateur
  • Cadre de repos Django
  • GĂ©nĂ©ration de jetons pour l'accès au serveur de Chat Stream
  • IntĂ©gration de l'autorisation React
  • Envoi de messages depuis un serveur Python
  • Dernières pensĂ©es

DĂ©pĂ´t Github avec le code d'un article

Commençons!

Étape 1: React Demo Chat Interface


Avant de commencer à penser à la partie Python, déployons une interface simple sur React afin d'avoir quelque chose de beau et de visuel:

$ 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 

Remplacez le code dans src/App.js par ce qui suit:

 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; 

Maintenant, utilisez la commande yarn start pour voir le chat en action!

Étape 2: Installez Django / Python (ignorez cette étape si vous avez déjà tout ce dont vous avez besoin)


Assurez-vous que vous avez Python 3.7 et qu'il fonctionne:

 $ 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 cela ne fonctionne pas, essayez le code suivant:

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

Maintenant que vous êtes dans votre environnement virtuel, vous devriez voir python 3 au démarrage:

 $ python --version 

Pour créer un nouveau projet dans Django, utilisez le code suivant:

 $ pip install django $ django-admin startproject mychat 

Et exécutez l'application:

 $ cd mychat $ python manage.py runserver 

Maintenant, lorsque vous ouvrez http://localhost:8000 , vous verrez ce qui suit:



Étape 3: Autorisation utilisateur


L'Ă©tape suivante consiste Ă  configurer l'autorisation utilisateur dans Django.

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

Accédez à http://localhost:8000/admin/ et connectez-vous. Voila!

Vous verrez un onglet administrateur similaire Ă  celui ci-dessous:



Étape 4: Django Rest Framework


L'un de mes packages préférés pour l'intégration de React avec Django est le Django Rest Framework. Pour le faire fonctionner, vous devez créer des points de terminaison pour:

  • Inscription des utilisateurs
  • Connexion utilisateur.

Nous pourrions les fabriquer nous-mêmes, mais il existe un package appelé Djoser qui résout ce problème. Il configurera les points de terminaison API nécessaires pour l'enregistrement des utilisateurs, la connexion, la réinitialisation du mot de passe, etc.

Pour installer Djoser, utilisez ce qui suit:

 $ pip install djangorestframework djoser 

Après cela, modifiez urls.py et modifiez le contenu du fichier comme suit:

 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')), ] 

Une fois terminé, modifiez settings.py et apportez les modifications:

 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', ) } 

Pour plus d'informations sur les points de terminaison API fournis par Djoser, consultez les éléments suivants:

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

Maintenant, continuons et testons le point de terminaison d'enregistrement:

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

Étape 5: Générez des jetons pour accéder au serveur de flux de conversation


Nous devons maintenant configurer les vues Djoser pour générer des jetons Stream. Commençons donc.
Organisons un peu nos fichiers et créons un dossier d'application de chat dans notre projet (assurez-vous d'être dans le bon répertoire):

 $ python manage.py startapp auth 

Installez stream-chat:

 $ pip install stream-chat 

Créez un sérialiseur personnalisé dans auth/serializers.py utilisant la logique suivante:

 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 

Enfin, utilisez un sérialiseur personnalisé pour mettre à jour le fichier 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', } } 

Redémarrez la migration:

 $ python manage.py migrate 

Pour vérifier que cela fonctionne, accédez au point de terminaison à l'aide d'une demande POST:

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

Le retour doit ĂŞtre auth_token et stream_token .

Étape 6: Intégrer l'autorisation React


Pour des raisons évidentes, l'ajout d'une autorisation au frontend est une étape importante. Dans notre cas, cela est particulièrement utile, car nous pouvons extraire le jeton utilisateur de l'API (qui s'exécute sur Python) et l'utiliser dynamiquement lors de l'envoi de messages.

Tout d'abord, installez CORS, le progiciel middleware pour Django:

 $ pip install django-cors-headers 

Modifiez ensuite le fichier settings.py pour faire référence au djors-cors-header :

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

Enfin, ajoutez ce qui suit Ă  votre fichier settings.py :

 CORS_ORIGIN_ALLOW_ALL = True 

L'étape suivante nécessitera quelques modifications de votre interface. Pour commencer, vous devrez vous assurer que toutes les dépendances sont installées via yarn:

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

Ensuite, créez les fichiers suivants dans le répertoire 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; 

Assurez-vous de remplacer YOUR_STREAM_APP_ID par l'ID d'application Stream valide, qui se trouve sur le tableau de bord .

Redémarrez l'application sur le front-end et vous verrez l'autorisation! Entrez votre adresse e-mail et votre mot de passe, le jeton sera demandé et stocké dans le stockage local.

Étape 7: envoi de messages depuis le serveur Python


Si vous souhaitez soudainement créer une API de chat à l'aide de votre backend en Python, il existe une commande spéciale que vous pouvez utiliser.

Assurez-vous que les applications installées ressemblent à ceci dans 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', ] 

Ensuite, créez le répertoire chat / gestion / commandes. Dans ce répertoire, ajoutez un fichier appelé broadcast.py avec le contenu suivant:

 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'])) 

Vous pouvez essayer d'envoyer un message de discussion comme suit:

 $ python manage.py broadcast --message hello 

Et vous verrez cette réponse:



Dernières pensées


J'espère que vous avez apprécié ce tutoriel sur la création d'une application de chat dans Django, Python et React!

Pour une visite interactive de Stream Chat , veuillez consulter notre guide sur la création d'une API sur le site Web de Stream . Si vous aimez fouiller dans le code des composants Stream Chat React, vous pouvez trouver la documentation complète ici . Si vous souhaitez créer un chat sur Stream, nous sommes heureux de vous proposer divers SDK pour les langages et frameworks populaires jusqu'au dernier iOS (Swift) .

C’est tout. Rendez-vous au webinaire ouvert sur Django ORM Tricks .

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


All Articles