Welcome to the second part
in the previous part, we finished our models
in this part we are going to set our views.py and urls.py files
first, let's install the required libraries and frameworks
pip install djangorestframework django-filter djangorestframework-simplejwt django-cors-headers
let's add some changes to our settings.py file
add these to INSTALLED_APPS
INSTALLED_APPS = [
...,
'django.contrib.staticfiles',
'django_resized',
'rest_framework',
'chat',
'rest_framework_simplejwt.token_blacklist',
'corsheaders',
]
now we are going to create REST_FRAMEWORK dictionary
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
],
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
)
}
now we'll add SIMPLE_JWT dictionary under the previous one
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=90),
'REFRESH_TOKEN_LIFETIME': timedelta(days=90),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'UPDATE_LAST_LOGIN': False,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'VERIFYING_KEY': None,
'AUDIENCE': None,
'ISSUER': None,
'JWK_URL': None,
'LEEWAY': 0,
'AUTH_HEADER_TYPES': ('Bearer',),
'AUTH_HEADER_NAME': 'HTTP_AUTHORIZATION',
'USER_ID_FIELD': 'id',
'USER_ID_CLAIM': 'user_id',
'USER_AUTHENTICATION_RULE': 'rest_framework_simplejwt.authentication.default_user_authentication_rule',
'AUTH_TOKEN_CLASSES': ('rest_framework_simplejwt.tokens.AccessToken',),
'TOKEN_TYPE_CLAIM': 'token_type',
'TOKEN_USER_CLASS': 'rest_framework_simplejwt.models.TokenUser',
'JTI_CLAIM': 'jti',
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
}
here
ACCESS_TOKEN_LIFETIME is the lifetime for the access token that will be used in JWT authorization, I set it to 90 minutes
REFRESH_TOKEN_LIFETIME is the lifetime for the refresh token that will be used to refresh the access token, I set it to 90 days (you can change as you want)
ROTATE_REFRESH_TOKENS it lets me to change the refresh token when I want and get new one
BLACKLIST_AFTER_ROTATION when the token will be rotated in the previous key, it will gives me a new token, but without blacklist I will be able to use the old token, but when I set this key to True it will takes the old token to a blacklist and you can't use it anymore
those are the most important keys I mentioned, to see the full keys and their uses, visit this link:
now let's add some CORS (Cross-Origin Resource Sharing) configuration
add this in MIDDLEWARE list
MIDDLEWARE = [
...,
"corsheaders.middleware.CorsMiddleware",
"django.middleware.common.CommonMiddleware",
...,
]
then add these under MIDDLEWARE list
CORS_ALLOW_CREDENTIALS = True
CORS_ALLOWED_ORIGINS = [
'http://localhost:5173',
'http://localhost:5174',
'http://127.0.0.1:5173',
'http://127.0.0.1:5174'
]
the CORS_ALLOWED_ORIGINS list includes the websites that can use our api, I set it to my localhost websites, when you are going to deploy your app, you must change it or add to them your website link
now we configured our settings.py file, let's run these commands to make new models (came already with blacklist, so, we need to run these commands to make sure our app will run correctly)
python manage.py makemigrations
python manage.py migrate
now, we are going to make new file inside chat folder and name it serializers.py and call our Chat model and drf inside it
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from .models import Chat
now let's write our serializer
first, we'll make ModelSerializer with our model Chat in serializer class ChatSerializer
class ChatSerializer(ModelSerializer):
class Meta:
model = Chat
fields = '__all__'
now, our chat serializer works with our chat model and choose the whole fields in our chat model
later in the views and when we'll connect with frontend, we'll face a problem with user field because it'll return the id of the user not the name of it, so we need to change our serializer like this
class ChatSerializer(ModelSerializer):
user = SerializerMethodField("get_name")
class Meta:
model = Chat
fields = '__all__'
def get_name(self, obj):
return obj.user.username
now we changed user field as depicted above, we called SerializerMethodField function and insert another function inside it, this function we'll return the user's name instead of the user id
now our simple serializer is ready
now, let's start with our views.py file
let's write these lines of code, I copied them from drf website and pasted them in our file
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
from rest_framework_simplejwt.views import TokenObtainPairView
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
@classmethod
def get_token(cls, user):
token = super().get_token(user)
token['username'] = user.username
return token
class MyTokenObtainPairView(TokenObtainPairView):
serializer_class = MyTokenObtainPairSerializer
I got these classes from djangorestframework-simplejwt docs, you can find them here:
we'll use these classes later in our urls.py file, now let's continue with our views.py
now we are going to create a function to create users
firstly, import these in the top of the file
import json
from django.http import JsonResponse
from django.contrib.auth.models import User
from rest_framework.decorators import api_view
we need to import json to loads our body from the frontend
JsonResponse is to give json response to our frontend
User model has the whole users inside it and we need it to create users
api_view is a decorator from drf decorators, and it used with fbv (Function Based Views) to make sure that it'll get post request only
now let's create our first views function, to make new users
@api_view(['POST'])
def createUser(request):
if request.method == "POST":
data = json.loads(request.body)
username = data['username']
password = data['password']
try:
User.objects.get(username=username)
return JsonResponse({"status": "405", "ok": False})
except:
User.objects.create_user(username=username, password=password).save()
return JsonResponse({"status": "200", "ok": True})
we create a function and give it a decorator to get only post request with our api
inside the function, I make a condition to make sure that the request is post and do the rest of the work
inside the condition, we'll load our json body (request from frontend) to data variable
make two variables username and password and give the json body values to them
then, we'll make try and except to make sure that the user isn't repeated (it must be unique), if the user name is already exists , it'll return json response, with status 405 and false ok response
otherwise, the user will be created and return 200 ok response
Note: use create_user instead of the known one create, because create_user make users with hashed passwords
our first function is completed, let's start with the next
now, we'll import these
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import IsAuthenticated
from .models import Room
we imported another decorator and a permission to make sure the user that make request is authenticated and import our Room model
now let's create a new function to create rooms
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def createRoom(request):
if request.method == "POST":
data = json.loads(request.body)
try:
Room.objects.get(name = data['name'], password = data['password'])
return JsonResponse({"status": 404})
except:
Room.objects.create(name = data['name'], password = data['password'])
return JsonResponse({"status": 200})
it is similar to CreateUser function, except that we give it another decorator, permission_classes and give it IsAuthenticated permission to make sure that the user who try to create new room is already authenticated, and the rest of the function is similar to the previous one
that's all to this article, in the next one I'll show you how to create a new function to show and create chat messages and to delete room (if you want)
See you in the next part
this is the Github repository for this chat project, don't forget to give it a star
django-react-chat-app
this is a simple chat app built with django and react
how to run this project
make a virtual environment and install the repository inside it
activate you virtual environment
venv/Scripts/activate # for linux: source venv/bin/activate
then take a dive inside backend folder and download the used packages
pip install -r requirements.txt
then run the server
python manage.py runserver
Note: make sure that the virtual environment is activated
Now get inside the frontend folder and run
npm i # or npm install
and then run the website
npm run dev
Happy Coding ^_^
Happy Coding ^_^
Top comments (0)