1573544168
Unlike other tutorials, I’m not using Python/Django for WebSocket connections. While doing so may seem cool from a tech perspective, it’s pretty sluggish and expensive — especially if you have a halfway decent number of users. Languages such as C++, Go and Elixir are much better at handling the core of chat.
In this tutorial, we will use Stream, an API for chat that takes care of WebSocket connections and other heavy lifting using Go, Raft and RocksDB.
Before we start thinking about the Python chat side of things let’s spin up a simple React frontend, so we have something nice and visual to look at:
$ 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
Replace the code in src/App.js
with:
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;
Next, run yarn start
to see the chat in action!
Make sure you have Python 3.7 up and running.
$ brew install python3
$ pip install virtualenv virtualenvwrapper
$ export WORKON_HOME=~/Envs
$ source /usr/local/bin/virtualenvwrapper.sh
$ mkvirtualenv chatexample -p `which python3`
$ workon chatexample
If that does not work, please try this snippet:
$ python3 -m venv chatexample
$ source chatexample/bin/activate
Now that you’re in your virtual env you should see python 3 when you run:
$ python --version
To kick off a new Django project, use the following snippet:
$ pip install django
$ django-admin startproject mychat
And to start your app:
$ cd mychat
$ python manage.py runserver
Now, when you open http://localhost:8000
, you should see this:
As a next step lets setup Django’s user auth.
$ python manage.py migrate
$ python manage.py createsuperuser
$ python manage.py runserver
Visit http://localhost:8000/admin/
and log in. Voila!
You should see the Django admin screen as shown below:
One of my favorite packages for integrating react with Django is Django Rest Framework. To make everything work, we will need to create endpoints for:
We could build those ourselves; however, there is a package called Djoser that has already solved this problem. It configured the necessary API endpoints for user registration, login, password reset, etc.
To install Djoser, use the following snippet:
$ pip install djangorestframework djoser
Then, edit urls.py
and change the file to contain:
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')),
]
Once complete, edit settings.py
and make the following changes:
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',
)
}
For more on the API endpoints that Djoser exposes
Now, let’s go ahead and test the registration endpoint:
$ curl -X POST http://127.0.0.1:8000/auth/users/ --data 'username=djoser&password=alpine12'
Now we need to customize the Djoser views to generate tokens for Stream. Let’s get started.
Let’s organize our files a bit and create a chat app folder in our project (make sure that you are in the correct directory):
$ python manage.py startapp auth
Install stream-chat:
$ pip install stream-chat
Create a custom serializer in auth/serializers.py
with the following logic:
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
And last, use the custom serializer by updating your settings.py
file:
STREAM_API_KEY = YOUR_STREAM_API_KEY # https://getstream.io/dashboard/
STREAM_API_SECRET = YOUR_STREAM_API_SECRET
DJOSER = {
'SERIALIZERS': {
'token': 'auth.serializers.StreamTokenSerializer',
}
}
Rerun your migration:
$ python manage.py migrate
To verify that it works, hit the login endpoint with a POST request:
$ curl -X POST http://127.0.0.1:8000/auth/token/login/ --data 'username=djoser&password=alpine12'
Both the auth_token
and stream_token
should be returned.
Adding an auth later to the frontend is an essential step for obvious reasons. In our case, it’s especially useful because we can fetch a user token from the backend API (powered by Python) and dynamically use it when sending messages.
First, install the CORS middleware package for Django:
$ pip install django-cors-headers
Then, modify your settings.py
to reference the djors-cors-header
middleware:
INSTALLED_APPS = (
...
'corsheaders',
...
)
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
And finally, add the following to your settings.py
file:
CORS_ORIGIN_ALLOW_ALL = True
The next step requires a few modifications to be made to your frontend. To start, you will want to ensure that you have all of the dependencies installed via yarn:
$ yarn add axios react-dom react-router-dom
Next, create the following files within your src/
directory:
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;
Be sure to replace YOUR_STREAM_APP_ID
with a valid Stream App ID which can be found on the dashboard.
Restart your frontend application and you should be hit with an auth wall! Enter your email and password and a token will be requested and stored in local storage.
Occasionally, you will want to write to the chat API using your backend Python-based server. Here’s a quick management command that you can use:
Verify that installed apps looks like this in 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',
]
Next, create the directory chat/management/commands
. In that directory, add a file called broadcast.py
with this content:
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']))
You can try posting a message to the chat like this:
$ python manage.py broadcast --message hello
And you should see a response like this:
I hope you enjoyed this tutorial on building a chat application with Django, Python and React!
Thank for reading !
#Python #Django #React #Webdev
1598839687
If you are undertaking a mobile app development for your start-up or enterprise, you are likely wondering whether to use React Native. As a popular development framework, React Native helps you to develop near-native mobile apps. However, you are probably also wondering how close you can get to a native app by using React Native. How native is React Native?
In the article, we discuss the similarities between native mobile development and development using React Native. We also touch upon where they differ and how to bridge the gaps. Read on.
Let’s briefly set the context first. We will briefly touch upon what React Native is and how it differs from earlier hybrid frameworks.
React Native is a popular JavaScript framework that Facebook has created. You can use this open-source framework to code natively rendering Android and iOS mobile apps. You can use it to develop web apps too.
Facebook has developed React Native based on React, its JavaScript library. The first release of React Native came in March 2015. At the time of writing this article, the latest stable release of React Native is 0.62.0, and it was released in March 2020.
Although relatively new, React Native has acquired a high degree of popularity. The “Stack Overflow Developer Survey 2019” report identifies it as the 8th most loved framework. Facebook, Walmart, and Bloomberg are some of the top companies that use React Native.
The popularity of React Native comes from its advantages. Some of its advantages are as follows:
Are you wondering whether React Native is just another of those hybrid frameworks like Ionic or Cordova? It’s not! React Native is fundamentally different from these earlier hybrid frameworks.
React Native is very close to native. Consider the following aspects as described on the React Native website:
Due to these factors, React Native offers many more advantages compared to those earlier hybrid frameworks. We now review them.
#android app #frontend #ios app #mobile app development #benefits of react native #is react native good for mobile app development #native vs #pros and cons of react native #react mobile development #react native development #react native experience #react native framework #react native ios vs android #react native pros and cons #react native vs android #react native vs native #react native vs native performance #react vs native #why react native #why use react native
1619518440
Welcome to my Blog , In this article, you are going to learn the top 10 python tips and tricks.
…
#python #python hacks tricks #python learning tips #python programming tricks #python tips #python tips and tricks #python tips and tricks advanced #python tips and tricks for beginners #python tips tricks and techniques #python tutorial #tips and tricks in python #tips to learn python #top 30 python tips and tricks for beginners
1623057780
Django…We all know the popularity of this Python framework. Django has become the first choice of developers to build their web applications. It is a free and open-source Python framework. Django can easily solve a lot of common development challenges. It allows you to build flexible and well-structured web applications.
A lot of common features of Django such as a built-in admin panel, ORM (object-relational mapping tool), Routing, templating have made the task easier for developers. They do not require spending so much time on implementing these things from scratch.
One of the most killer features of Django is the built-in Admin panel. With this feature, you can configure a lot of things such as an access control list, row-level permissions, and actions, filters, orders, widgets, forms, extra URL helpers, etc.
Django ORM works with all major databases out of the box. It supports all the major SQL queries which you can use in your application. Templating engine of Django is also very, very flexible and powerful at the same time. Even a lot of features are available in Django, developers still make a lot of mistakes while building an application. In this blog, we will discuss some common mistakes which you should avoid while building a Django application.
#gblog #python #python django #building a django application #django #applications
1619510796
Welcome to my Blog, In this article, we will learn python lambda function, Map function, and filter function.
Lambda function in python: Lambda is a one line anonymous function and lambda takes any number of arguments but can only have one expression and python lambda syntax is
Syntax: x = lambda arguments : expression
Now i will show you some python lambda function examples:
#python #anonymous function python #filter function in python #lambda #lambda python 3 #map python #python filter #python filter lambda #python lambda #python lambda examples #python map
1620177818
Welcome to my blog , hey everyone in this article you learn how to customize the Django app and view in the article you will know how to register and unregister models from the admin view how to add filtering how to add a custom input field, and a button that triggers an action on all objects and even how to change the look of your app and page using the Django suit package let’s get started.
#django #create super user django #customize django admin dashboard #django admin #django admin custom field display #django admin customization #django admin full customization #django admin interface #django admin register all models #django customization