Escrevendo um bate-papo em Python e Django

Boa tarde amigos Antecipando o início do curso Python Web Developer, tradicionalmente compartilhamos uma tradução útil com você.




Você vê um guia à sua frente que mostra como criar um aplicativo de bate-papo no Python, Django e React.

Ao contrário de outros manuais, não uso conexões Python e Django para WebSocket. Apesar de parecer legal do ponto de vista técnico, ele funciona bastante devagar e é caro por si só, especialmente se você tiver um número razoável de usuários. Idiomas como C ++, Go e Elixir fazem um trabalho muito melhor no núcleo do bate-papo.

Neste tutorial, usaremos o Stream, uma API de bate - papo que cuida das conexões WebSocket e outros aspectos pesados ​​usando Go, Raft e RocksDB.

Conteúdo:

  • Reagir interface de bate-papo demo
  • Instale o Django / Python
  • Autorização do Usuário
  • Estrutura de resto do Django
  • Geração de token para acesso ao servidor Stream de bate-papo
  • Reagir a integração de autorização
  • Enviando mensagens de um servidor Python
  • Últimos pensamentos

Repositório do Github com código de um artigo

Vamos começar!

Etapa 1: reagir à interface de bate-papo de demonstração


Antes de começarmos a pensar na parte do Python, vamos implantar uma interface simples no React para que tenhamos algo bonito e 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 

Substitua o código em src/App.js pelo seguinte:

 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; 

Agora, use o comando yarn start para ver o bate-papo em ação!

Etapa 2: Instale o Django / Python (pule esta etapa se você já possui tudo o que precisa)


Verifique se você possui o Python 3.7 e está em execução:

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

Se não funcionar, tente o seguinte código:

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

Agora que você está no seu ambiente virtual, deverá ver o python 3 na inicialização:

 $ python --version 

Para criar um novo projeto no Django, use o seguinte código:

 $ pip install django $ django-admin startproject mychat 

E execute o aplicativo:

 $ cd mychat $ python manage.py runserver 

Agora, quando você abrir http://localhost:8000 , verá o seguinte:



Etapa 3: Autorização do Usuário


O próximo passo é configurar a autorização do usuário no Django.

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

Vá para http://localhost:8000/admin/ e faça login. Voila!

Você verá uma guia do administrador semelhante à abaixo:



Etapa 4: Django Rest Framework


Um dos meus pacotes favoritos para integrar o React com o Django é o Django Rest Framework. Para fazê-lo funcionar, você precisa criar pontos de extremidade para:

  • Registro de usuário
  • Login do usuário.

Poderíamos fazê-los nós mesmos, no entanto, há um pacote chamado Djoser que resolve esse problema. Ele configurará os pontos de extremidade da API necessários para o registro do usuário, login, redefinição de senha, etc.

Para instalar o Djoser, use o seguinte:

 $ pip install djangorestframework djoser 

Depois disso, edite urls.py e altere o conteúdo do arquivo da seguinte maneira:

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

Quando terminar, edite settings.py e faça as alterações:

 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 obter mais informações sobre os pontos de extremidade da API que o Djoser fornece, consulte o seguinte:

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

Agora vamos continuar e testar o terminal de registro:

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

Etapa 5: gerar tokens para acessar o servidor de fluxo de bate-papo


Agora precisamos configurar as visualizações do Djoser para gerar tokens de fluxo. Então, vamos começar.
Vamos organizar um pouco nossos arquivos e criar uma pasta de aplicativo de bate-papo em nosso projeto (verifique se você está no diretório certo):

 $ python manage.py startapp auth 

Instale o stream-chat:

 $ pip install stream-chat 

Crie um serializador personalizado em auth/serializers.py usando a seguinte 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 fim, use um serializador personalizado para atualizar o arquivo 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', } } 

Reinicie a migração:

 $ python manage.py migrate 

Para verificar se funciona, acesse o terminal usando uma solicitação POST:

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

O retorno deve auth_token e stream_token .

Etapa 6: integrar a autorização do React


Por razões óbvias, adicionar autorização ao front-end é uma etapa importante. No nosso caso, isso é especialmente útil, pois podemos extrair o token do usuário da API (que é executada no Python) e usá-lo dinamicamente ao enviar mensagens.

Primeiro, instale o CORS, o pacote de middleware do Django:

 $ pip install django-cors-headers 

Modifique o arquivo settings.py para se referir ao djors-cors-header :

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

Por fim, adicione o seguinte ao seu arquivo settings.py :

 CORS_ORIGIN_ALLOW_ALL = True 

A próxima etapa exigirá algumas alterações na sua interface. Para começar, você precisará ter todas as dependências instaladas através do yarn:

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

Em seguida, crie os seguintes arquivos no diretório 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; 

Substitua YOUR_STREAM_APP_ID pelo ID do aplicativo Stream válido, que pode ser encontrado no painel .

Reinicie o aplicativo no front-end e você verá a autorização! Digite seu endereço de e-mail e senha, o token será solicitado e armazenado no armazenamento local.

Etapa 7: Enviando mensagens do servidor Python


Se você deseja criar de repente uma API de bate-papo usando seu back-end em Python, existe um comando especial que você pode usar.

Verifique se os aplicativos instalados ficam assim em 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', ] 

Em seguida, crie o diretório chat / management / command. Nesse diretório, adicione um arquivo chamado broadcast.py com o seguinte conteúdo:

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

Você pode tentar enviar uma mensagem de bate-papo da seguinte maneira:

 $ python manage.py broadcast --message hello 

E você verá esta resposta:



Últimos pensamentos


Espero que você tenha gostado deste tutorial sobre como criar um aplicativo de bate-papo no Django, Python e React!

Para um passeio interativo pelo Stream Chat , consulte nosso guia sobre como criar uma API no site do Stream . Se você gosta de se aprofundar no código dos componentes do Stream Chat React, pode encontrar a documentação completa aqui . Se você deseja criar um bate-papo no Stream, temos o prazer de oferecer vários SDKs para idiomas e estruturas populares até o iOS mais recente (Swift) .

Só isso. Vejo você no webinar aberto sobre o Django ORM Tricks .

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


All Articles