{"id":20455328,"url":"https://github.com/alexmhack/django_chat","last_synced_at":"2026-03-09T10:33:53.100Z","repository":{"id":44980649,"uuid":"150886240","full_name":"Alexmhack/django_chat","owner":"Alexmhack","description":"Creating a chatbot system using django2 and vue.js along with many modules.","archived":false,"fork":false,"pushed_at":"2022-12-08T13:57:58.000Z","size":723,"stargazers_count":2,"open_issues_count":9,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-09T02:44:18.924Z","etag":null,"topics":["beginner-tutorial","chat-system","django2","djoser","user-auth","vuejs"],"latest_commit_sha":null,"homepage":null,"language":"Vue","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Alexmhack.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-09-29T17:13:17.000Z","updated_at":"2023-08-27T01:35:43.000Z","dependencies_parsed_at":"2023-01-25T07:46:40.650Z","dependency_job_id":null,"html_url":"https://github.com/Alexmhack/django_chat","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Alexmhack/django_chat","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fdjango_chat","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fdjango_chat/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fdjango_chat/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fdjango_chat/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Alexmhack","download_url":"https://codeload.github.com/Alexmhack/django_chat/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Alexmhack%2Fdjango_chat/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30291807,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-09T02:57:19.223Z","status":"ssl_error","status_checked_at":"2026-03-09T02:56:26.373Z","response_time":61,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["beginner-tutorial","chat-system","django2","djoser","user-auth","vuejs"],"created_at":"2024-11-15T11:18:35.094Z","updated_at":"2026-03-09T10:33:53.046Z","avatar_url":"https://github.com/Alexmhack.png","language":"Vue","readme":"# django_chat\nCreating a chatbot system using django2 and vue.js along with many modules.\n\n**Start django project**\n\nWe will name our django project **chatire** you can name it whatever you want. The \ntrailing **dot** at the end creates django project in the **current** folder.\n\n```\ndjango-admin startproject chatire .\n```\n\nNow ```migrate``` and ```createsuperuser```\n\n```\npython manage.py migrate\npython manage.py createsuperuser\npython manage.py runserver\n```\n\n# Authentication And User Management\nOur project will have system for login and signing up users. This will be done by \nimplementing a user and authentication management so users can create account and \nlogin.\n\nThanks to Django’s excellent and vibrant community, most of the work has been done \nfor us. Hence we’re going to make use of a third-party django library called djoser\n\nInstall it using ```pip```\n\n```\npip install djoser\npip install djangorestframework\n```\n\n[Djoser](http://djoser.readthedocs.io/) is a REST Implementation of Django’s inbuilt \nauthentication system. So instead of forms and views that return html, it provides us \nwith REST endpoints for user registration, token creation, user management etc.\n\n## Configuring Djoser\nWe will be using djoser at the very basic level, there is a lot more that can be done \nwith djoser. \n\nConfigure our project for **djoser**\n\n```\nINSTALLED_APPS = [\n    'django.contrib.admin',\n    ...\n    'rest_framework',\n    'rest_framework.authtoken',\n    'djoser',\n]\n```\n\nAdd **djoser urls** to ```urls.py```\n\n```\n# djoser urls\nurlpatterns += [\n    path('auth/', include('djoser.urls')),\n    path('auth/', include('djoser.urls.authtoken')),\n]\n```\n\nNow include the ```rest_framework.authentication.TokenAuthentication``` to **django rest frameword authentication classes**. Add this to the bottom of ```settings.py``` file.\n\n```\n# django rest frameworks authentication classes\nREST_FRAMEWORK = {\n    'DEFAULT_AUTHENTICATION_CLASSES': (\n        'rest_framework.authentication.TokenAuthentication',\n    ),\n}\n```\n\nNow we will try out the **djoser** endpoint.\n\nRun the server using ```python manage.py runserver``` and in **git bash** or **terminal** type \n\n```\ncurl -X POST http://127.0.0.1:8000/auth/users/create/ --data \"username=alexmhack\u0026password=trydjango\"\n{\"email\":\"\",\"username\":\"alexmhack\",\"id\":2}\n```\n\n**NOTE:** If you get any errors saying ```password not recognized as internal \ncommand... then``` use double quotes in like this \n```\"username=alexmhack\u0026password=trydjango\"```. Also don't forget to add ```/``` \nat the end of the url.\n\nThis command has created a new user, you can check the console where server is running...\n```\n[...] \"POST /auth/users/create/ HTTP/1.1\" 201 37\n```\n\nAlternatively you can use ```\u0026email=``` field to give the username email also.\n\n# Vue.js\nWe’ll make use of vue-cli to quickly create a Vue app ```(instead of the \u003cscript\u003e tag method)```. This method allows us to leverage the full power of ES6+ and single file Vue components.\n\nInstall ```vue-cli``` using ```npm```\n\n```\nnpm install -g vue-cli\n```\n\nLet's create a new project based on webpack template with vue-cli\n\n```\nvue init webpack chatire-frontend\n```\n\nThis will download the webpack and ask for project details. Be sure to accept \n**install vue-router** option. And also **npm install** option. \n\nAfter the process completes run the dev server using\n\n```\nnpm run dev\n```\n\nLocate to [localhost:8000](http://127.0.0.1:8000/)\n\nFor more details on this project visit this [link](https://danidee10.github.io/2018/01/01/realtime-django-1.html)\n\nvue-cli also sets up hotreloading for us which really improves the developer’s \nexperience. As soon as you hit save after editing a component, the change is \nimmediately reflected in the browser.\n\n# Configure Vue Router\nCreate two components inside **chatire-frontend/src/components** folder. One will we ```Chat.vue``` for showing the chat screen and the other is ```UserAuth.vue``` that will be shown to unauthenticated users for login and sign up.\n\nEdit the ```chatire-frontend/src/router/index.js``` file and add\n\n```\nimport Vue from 'vue'\nimport Router from 'vue-router'\nimport Chat from '@/components/Chat'\nimport UserAuth from '@/components/UserAuth'\n\nVue.use(Router)\n\nconst router = new Router({\n  routes: [\n    {\n      path: '/chats',\n      name: 'Chat',\n      component: Chat\n    },\n\n    {\n      path: '/auth',\n      name: 'UserAuth',\n      component: UserAuth\n    }\n  ]\n})\n\nrouter.beforeEach((to, from, next) =\u003e {\n  if (sessionStorage.getItem('authToken') !== null || to.path === '/auth') {\n    next()\n  }\n  else {\n    next('/auth')\n  }\n})\n\nexport default router\n```\n\nThe beforeEach guard is called before a navigating to any route in our application.\n\nIf a token is stored in the sessionStorage we allow the navigation to proceed by \ncalling next() else we redirect to the auth component.\n\nNo matter the route a user navigates to in our application this function will check \nif the user has an auth token and redirect them appropraitely.\n\n# Login / Signup Template\nAdd the below piece of code in ```UseAuth.vue```\n\n```\n\u003ctemplate\u003e\n  \u003cdiv class=\"container\"\u003e\n    \u003ch1 class=\"text-center\"\u003eWelcome to Chatire!\u003c/h1\u003e\n    \u003cdiv id=\"auth-container\" class=\"row\"\u003e\n      \u003cdiv class=\"col-sm-4 offset-sm-4\"\u003e\n        \u003cul class=\"nav nav-tabs nav-justified\" id=\"myTab\" role=\"tablist\"\u003e\n          \u003cli class=\"nav-item\"\u003e\n            \u003ca class=\"nav-link active\" id=\"signup-tab\" data-toggle=\"tab\" href=\"#signup\" role=\"tab\" aria-controls=\"signup\" aria-selected=\"true\"\u003eSign Up\u003c/a\u003e\n          \u003c/li\u003e\n          \u003cli class=\"nav-item\"\u003e\n            \u003ca class=\"nav-link\" id=\"signin-tab\" data-toggle=\"tab\" href=\"#signin\" role=\"tab\" aria-controls=\"signin\" aria-selected=\"false\"\u003eSign In\u003c/a\u003e\n          \u003c/li\u003e\n        \u003c/ul\u003e\n\n        \u003cdiv class=\"tab-content\" id=\"myTabContent\"\u003e\n\n          \u003cdiv class=\"tab-pane fade show active\" id=\"signup\" role=\"tabpanel\" aria-labelledby=\"signin-tab\"\u003e\n            \u003cform @submit.prevent=\"signUp\"\u003e\n              \u003cdiv class=\"form-group\"\u003e\n                \u003cinput v-model=\"email\" type=\"email\" class=\"form-control\" id=\"email\" placeholder=\"Email Address\" required\u003e\n              \u003c/div\u003e\n              \u003cdiv class=\"form-row\"\u003e\n                \u003cdiv class=\"form-group col-md-6\"\u003e\n                  \u003cinput v-model=\"username\" type=\"text\" class=\"form-control\" id=\"username\" placeholder=\"Username\" required\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"form-group col-md-6\"\u003e\n                  \u003cinput v-model=\"password\" type=\"password\" class=\"form-control\" id=\"password\" placeholder=\"Password\" required\u003e\n                \u003c/div\u003e\n              \u003c/div\u003e\n              \u003cdiv class=\"form-group\"\u003e\n                \u003cdiv class=\"form-check\"\u003e\n                  \u003cinput class=\"form-check-input\" type=\"checkbox\" id=\"toc\" required\u003e\n                  \u003clabel class=\"form-check-label\" for=\"gridCheck\"\u003e\n                    Accept terms and Conditions\n                  \u003c/label\u003e\n                \u003c/div\u003e\n              \u003c/div\u003e\n              \u003cbutton type=\"submit\" class=\"btn btn-block btn-primary\"\u003eSign up\u003c/button\u003e\n            \u003c/form\u003e\n          \u003c/div\u003e\n\n          \u003cdiv class=\"tab-pane fade\" id=\"signin\" role=\"tabpanel\" aria-labelledby=\"signin-tab\"\u003e\n            \u003cform @submit.prevent=\"signIn\"\u003e\n              \u003cdiv class=\"form-group\"\u003e\n                \u003cinput v-model=\"username\" type=\"text\" class=\"form-control\" id=\"username\" placeholder=\"Username\" required\u003e\n              \u003c/div\u003e\n              \u003cdiv class=\"form-group\"\u003e\n                \u003cinput v-model=\"password\" type=\"password\" class=\"form-control\" id=\"password\" placeholder=\"Password\" required\u003e\n              \u003c/div\u003e\n              \u003cbutton type=\"submit\" class=\"btn btn-block btn-primary\"\u003eSign in\u003c/button\u003e\n            \u003c/form\u003e\n          \u003c/div\u003e\n          \n        \u003c/div\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/template\u003e\n\n\u003cscript\u003e\n  const $ = window.jQuery // JQuery\n\n  export default {\n\n    data () {\n      return {\n        email: '', username: '', password: ''\n      }\n    }\n\n  }\n\u003c/script\u003e\n\n\u003cstyle scoped\u003e\n  #auth-container {\n    margin-top: 50px;\n  }\n\n  .tab-content {\n    padding-top: 20px;\n  }\n\u003c/style\u003e\n```\n\nI am using **Sublime Text 3** which has not pre-installed **Vue Markdown** so install\n**Vue Component** package in **Sublime Text**\n\nIn the above snippet we use ```v-model``` was uesd for two way binding of all input\nfields. This means that whatever is entered in the input fields can be accessed on\njavascript side using ```this.field_name```\n\nWe also use ```@submit.prevent``` that listens form submitting and calls\nthe specified functions (which will be implemented soon).\n\nSince we are using **bootstrap** we initialize ```$``` $ that points to the globally registered window.jQuery for using ```jquery``` instead of installing ```jquery``` from ```npm```\n\nNow we will use **jQuery AJAX** methods to communicate with **django server**\n\nDon’t forget to include bootstrap’s CSS and JavaScript in the main ```index.html``` \npage which is located in **chatire-frontend** folder\n\n```\n# index.html file\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003cmeta charset=\"utf-8\"\u003e\n    \u003cmeta name=\"viewport\" content=\"width=device-width,initial-scale=1.0\"\u003e\n    \u003ctitle\u003echatire-frontend\u003c/title\u003e\n    \u003clink rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/css/bootstrap.min.css\" integrity=\"sha384-Zug+QiDoJOrZ5t4lssLdxGhVrurbmBWopoEl+M6BdEfwnCJZtKxi1KgxUyJq13dy\" crossorigin=\"anonymous\"\u003e\n    \u003cstyle\u003e\n      .nav-tabs .nav-item.show .nav-link, .nav-tabs .nav-link.active {\n        outline: none;\n      }\n    \u003c/style\u003e\n  \u003c/head\u003e\n\n  \u003cbody\u003e\n\n    \u003c!-- Scripts --\u003e\n    \u003cscript src=\"https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js\"\u003e\u003c/script\u003e\n    \u003cscript src=\"https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js\" integrity=\"sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n    \u003cscript src=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta.3/js/bootstrap.min.js\" integrity=\"sha384-a5N7Y/aK3qNeh15eJKGWxsqtnX/wWdSZSKp+81YjTmS15nvnvxKHuzaWwXHDli+4\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n    \u003cdiv id=\"app\"\u003e\u003c/div\u003e\n    \u003c!-- built files will be auto injected --\u003e\n\n  \u003c/body\u003e\n\n\u003c/html\u003e\n```\n\n# Auth Token\nWe have to let users login or sign up and then redirect them to the ```Chat``` route\nTo achieve that we have to implement the ```signIn``` and ```signUp``` methods we \nspecified earlier.\n\nIn **UserAuth.vue**\n```\n\u003cscript\u003e\n  const $ = window.jQuery // JQuery\n\n  export default {\n\n    data () {\n      return {\n        email: '', username: '', password: ''\n      }\n    },\n\n    methods: {\n      signUp () {\n        $.post(\"http://localhost:8000/auth/users/create/\", this.$data, (data) =\u003e {\n          alert(\"Your account has been created. You will be Signed In automatically!\")\n          this.signIn()\n        })\n        .fail((response) =\u003e {\n          alert(response.responseText)\n        })\n      },\n\n      signIn () {\n        const credentials = {username: this.username, password: this.password}\n\n        $.post(\"http://localhost:8000/auth/token/create/\", credentials, (data) =\u003e {\n          sessionStorage.setItem('authToken', data.auth_token)\n          sessionStorage.setItem('username', this.username)\n          this.router.push('/chats')\n        })\n        .fail((response) =\u003e {\n          alert(response.ResponseText)\n        })\n      }\n    }\n\n  }\n\n\u003c/script\u003e\n```\n\n```methods``` contains both of the methods and send ajax post request to djoser \nendpoint for creating a new user.\n\nBefore hitting the **Sign In** button make sure that you run ```npm run dev``` and ```python manage.py runserver ```. You will get an error in the console...\n\n```\nCross-Origin Request Blocked: The Same Origin Policy disallows reading the remote \nresource at http://localhost:8000/auth/users/create/. (Reason: CORS header \n‘Access-Control-Allow-Origin’ missing).[Learn More]\n```\n\n# CORS\nBasically CORS is a mechanicsm that subverts the same origin policy. The same origin policy is what prevents a website on a different domain from making a XmlHttpRequest (Ajax) to another website/webservice. You can use CORS to weaken the security mechanicsm a little and tell the webserver that it’s safe to allow Ajax requests from a particular domain(s).\n\nThis is happening due to our **AJAX** request being sent from ```localhost:8080/```\nto ```127.0.0.1:8000/``` In our case, even though both webservers are running on \nlocalhost, due to the fact that they’re on different ports (8080 and 8000) they’re \nseen as different domains.\n\n**For the domains to match the scheme (http or https), hostname (localhost) and the port must match.**\n\nSo how do we enable CORS in our django application? There is third-party app we can \ninstall to do that called [django-cors-headers](https://github.com/ottoyiu/django-cors-headers)\n\n```\npip install django-cors-headers\n```\n\nadd it your ```INSTALLED_APPS```\n\n```\nINSTALLED_APPS = [\n    'django.contrib.admin',\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.messages',\n    'django.contrib.staticfiles',\n\n    # packages\n    'rest_framework',\n    'rest_framework.authtoken',\n    'djoser',\n    'corsheaders',\n]\n```\n\nInclude the middleware, (Make sure it comes before\ndjango.middleware.common.CommonMiddleware)\n\n```\nMIDDLEWARE = [\n    'django.middleware.security.SecurityMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n\n    # django-cors-headers middleware comes before CommonMiddleware\n    'corsheaders.middleware.CorsMiddleware',\n\n    'django.middleware.common.CommonMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'django.contrib.messages.middleware.MessageMiddleware',\n    'django.middleware.clickjacking.XFrameOptionsMiddleware',\n]\n```\n\nFinally set ```CORS_ORIGIN_ALLOW_ALL = True``` in ```settings.py```\n\nNote that this enables CORS for all domains. This is fine for development but when \nyou’re in production you only want to allow certain domain(s) this can be controlled \nwith:\n\nExample:\n\nCORS_ORIGIN_WHITELIST = (\n    'google.com',\n    'hostname.example.com',\n    'localhost:8000',\n    '127.0.0.1:9000'\n)\n\n**Behnind the scenes, django-cors-headers uses a Middleware to add appropriate headers to each request that tells Django that the request is safe and it should be allowed.**\n\n**Try sign up by filling form and hit the button, you will get an alert saying your\naccount has been created**\n\nHead over to [127.0.0.1:8000/admin](http://127.0.0.1:8000/admin) and after logging \nin head to users and you find a new user has been created. In admin site head to\n**Token** there you will find a token has been created for the new user.\n\n# Logout\nIf you haven't noticed I will remind you that we used ```sessionStorage``` which\nmeans that whenever a user opens a new browser window or restarts the browser he\nwill be asked to sign in again in that window.\n\nInstead we can use ```localStorage``` which enables all these features in the browser\nwindow.\n\nJust replace ```sessionStorage``` to ```localStorage``` in ```UserAuth.vue``` file this way you can also implement a function that removes the ```authToken``` from storage using ```localStorage.removeItem('authToken')```\n\n**UserAuth.vue**\n```\nsignIn () {\n        const credentials = {username: this.username, password: this.password}\n\n        $.post(\"http://localhost:8000/auth/token/create/\", credentials, (data) =\u003e {\n          localStorage.setItem('authToken', data.auth_token)\n          localStorage.setItem('username', this.username)\n          this.router.push('/chats')\n        })\n        .fail((response) =\u003e {\n          alert(response.ResponseText)\n        })\n      }\n```\n\n# Chat Application With Django\nSo far our project has used djoser for user authentication backend and then \nconnecting with frontend ```vue.js``` application to it.\n\nIn this part we will create ```APIs``` using **django-rest-framework** for providing\nendpoints to start new chat sessions, join chat sessions, post new messages, and \nfetch a chat session's history.\n\n1. When a user sends a message, this message would be forwarded to django through the API.\n\n2. After django has received the message, It would also be forwarded to RabbitMQ.\n\n3. RabbitMQ uses an exchange to broadcast the messages to multiple queues. The queues are communication channels that would eventually deliver the messages to the clients. The Workers are background processes that do the actual work of broadcasting and delivering messages.\n\n## Implementation\n\nIn this part, our goal is to implement the API with django rest framework. The API would allow users start new chat sessions, join existing sessions and send messages. It would also allow us retrieve messages from a chat session.\n\nLet’s start a new django app called chat\n\n```\npython manage.py startapp chat\n```\n\nAdd the new app to ```INSTALLED_APPS```\n\nNow we will create a model for our app. This model will store chat data like messages, chat sessions and associated users.\n\n**chat/models.py**\n```\nfrom django.db import models\nfrom django.contrib.auth import get_user_model\n\nfrom uuid import uuid4\n\nUser = get_user_model()\n\ndef deserialize_user(user):\n\t\"\"\"Deserialize user instance to JSON\"\"\"\n\treturn {\n\t\t'id': user.id, 'username': user.username, 'email': user.email,\n\t\t'first_name': user.first_name, 'last_name': user.last_name\n\t}\n\n\nclass TrackableDateModel(models.Model):\n\t\"\"\"Abstract model to track the creation/update date for a model\"\"\"\n\n\tcreated_date = models.DateTimeField(auto_now_add=True)\n\tupdated_date = models.DateTimeField(auto_now=True)\n\n\tclass Meta:\n\t\tabstract = True\n\n\ndef _generate_unique_uri():\n\treturn str(uuid4()).replace('-', '')[:15]\n\n\nclass ChatSession(TrackableDateModel):\n\t\"\"\"A chat session. The uri's are generated by taking\n\tthe first 15 characters from a UUID\"\"\"\n\n\towner = models.ForeignKey(User, on_delete=models.PROTECT)\n\turi = models.URLField(default=_generate_unique_uri)\n\n\nclass ChatSessionMessage(TrackableDateModel):\n\t\"\"\"Store messages for a session\"\"\"\n\n\tuser = models.ForeignKey(User, on_delete=models.PROTECT)\n\tchat_session = models.ForeignKey(\n\t\tChatSession, related_name='messages', on_delete=models.PROTECT\n\t)\n\tmessage = models.TextField(max_length=2500)\n\n\tdef to_json(self):\n\t\t\"\"\"Deserialize message to JSON\"\"\"\n\t\treturn {'user': deserialize_user(self.user), 'message': self.message}\n\n\nclass ChatSessionMember(TrackableDateModel):\n\t\"\"\"Store all users in a chat session\"\"\"\n\n\tchat_session = models.ForeignKey(\n\t\tChatSession, related_name='members', on_delete=models.PROTECT\n\t)\n\tuser = models.ForeignKey(User, on_delete=models.PROTECT)\n```\n\n```uuid``` provides ```uudi4``` which gives us a unique uuid object with ```-``` in \nbetween which can be converted to str and replace those hypens. We only use the first\n15 unique characters.\n\nThe next step is to create views (API endpoints) that would be used by our Vue app \nto manipulate data on the server.\n\nWe can easily make use of django rest framework to create them (We won’t make use of \nserializers since our models are pretty simple). Let’s do that now in views.py\n\nNow let's create views for chats\n\n```\nfrom django.shortcuts import render\nfrom django.contrib.auth import get_user_model\n\nfrom .models import (\n  deserialize_user, ChatSession, ChatSessionMessage, ChatSessionMember\n)\n\nfrom rest_framework.views import APIView\nfrom rest_framework.response import Response\nfrom rest_framework import permissions\n\nclass ChatSessionView(APIView):\n  \"\"\"Manage Chat Session\"\"\"\n\n  permission_classes = (permissions.IsAuthenticated,)\n\n  def post(self, request, *args, **kwargs):\n    \"\"\"create a new chat session\"\"\"\n    user = request.user\n\n    chat_session = ChatSession.objects.create(owner=user)\n\n    return Response({\n      'status': 'SUCCESS', 'uri': chat_session.uri,\n      'message': 'New chat session created'\n    })\n\n  def patch(self, request, *args, **kwargs):\n    \"\"\"Add a user to a chat session\"\"\"\n    User = get_user_model()\n    uri = kwargs['uri']\n    username = request.data['username']\n    user = User.objects.get(username=username)\n\n    chat_session = ChatSession.objects.get(uri=uri)\n    owner = chat_session.owner\n\n    if owner is not user:  # Only allow non owners join the room\n      chat_session.members.get_or_create(\n        user=user, chat_session=chat_session\n      )\n\n    owner = deserializer_user(owner)\n    members = [\n      deserialize_user(chat_session.user)\n      for chat_session in chat_session.members.all()\n    ]\n    members.insert(0, owner)  # make the owner first member\n\n    return Response({\n      'status': 'SUCCESS', 'members': members,\n      'message': f\"{user.username} joined chat session\",\n      'user': deserialize_user(user)\n    })\n\n\nclass ChatSessionMessageView(APIView):\n  \"\"\"Create / Get chat session messages\"\"\"\n  permission_classes = (permissions.IsAuthenticated,)\n\n  def get(self, request, *args, **kwargs):\n    \"\"\"return all messages in a chat session\"\"\"\n    uri = kwargs['uri']\n    chat_session = ChatSession.objects.get(uri=uri)\n    messages = [\n      chat_session_message.to_json()\n      for chat_session_message in chat_session.messages.all()\n    ]\n\n    return Response({\n      'id': chat_session.id, 'uri': chat_session.uri,\n      'messages': messages\n    })\n\n  def post(self, request, *args, **kwargs):\n    \"\"\"create a new message in a chat session.\"\"\"\n    uri = kwargs['uri']\n    message = request.data['message']\n\n    user = request.user\n    chat_session = ChatSession.objects.get(uri=uri)\n\n    ChatSessionMessage.objects.create(\n      user=user, chat_session=chat_session, message=message\n    )\n\n    return Response({\n      'status': 'SUCCESS', 'uri': chat_session.uri, 'message': message,\n      'user': deserialize_user(user)\n    })\n```\n\nNow let's add urls\n\n```\nfrom django.urls import path\n\nfrom .views import (\n  ChatSessionView, ChatSessionMessageView\n)\n\nurlpatterns += [\n  path('chats/', ChatSessionView.as_view()),\n  path('chats/\u003curi\u003e/', ChatSessionView.as_view()),\n  path('chats/\u003curi\u003e/messages/', ChatSessionMessageView.as_view()),\n]\n```\n\nAlso include chat urls in base urls\n\n```\nurlpatterns += [\n    path('auth/', include('djoser.urls')),\n    path('auth/', include('djoser.urls.authtoken')),\n    path('api/', include('chat.urls')),\n]\n```\n\nOur endpoints are ready and any AUTHENTICATED user make requests to them\n\nLet’s try it out in **terminal** or **cmd**:\n\n```\n# command\ncurl -X POST http://127.0.0.1:8000/auth/token/create/ --data \"username=admin\u0026password=trydjango\"\n\n# output\n{\"auth_token\":\"6e6b6b6f4f1efe2e3f88db8dbec8da74cc556cf6\"}\n\n# put auth_token in next command\ncurl -X POST http://127.0.0.1:8000/api/chats/ -H \"Authorization: Token 6e6b6b6f4f1efe2e3f88db8dbec8da74cc556cf6\"\n\n# output\n{\"status\":\"SUCCESS\",\"uri\":\"467f53e415044c0\",\"message\":\"New chat session created\"}\nF:\\coder\\django_chat\\chat\u003e\n\n# create auth token for another user\ncurl -X POST http://127.0.0.1:8000/auth/token/create/ --data \"username=alex\u0026password=trydjango\"\n{\"auth_token\":\"169fcd5067cc55c500f576502637281fa367b3a6\"}\n\n# use uri in next command\ncurl -X PATCH http://127.0.0.1:8000/api/chats/467f53e415044c0/ --data \"username=alex\" -H \"Authorization: Token 169fcd5067cc55c500f576502637281fa367b3a6\"\n\n# output\n'Authorization: Token 9c3ea2d194d7236ac68d2faefba017c8426a8484'\n{\"status\":\"SUCCESS\",\"members\":[{\"id\":1,\"username\":\"admin\",\"email\":\"admin@gmail.com\",\"first_name\":\"\",\"last_name\":\"\"},{\"id\":2,\"username\":\"alex\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"}],\"message\":\"alex joined that chat\",\"user\":{\"id\":2,\"username\":\"alex\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"}}\n```\n\nLet's send some messages...\n\n```\n# command to send message from the auth token generated by usernam = admin\ncurl -X POST http://127.0.0.1:8000/api/chats/63c5a282c5b640d/messages/ --data \"message=Hello there\" -H \"Authorization: Token\n6e6b6b6f4f1efe2e3f88db8dbec8da74cc556cf6\"\n\n# output\n{\"status\":\"SUCCESS\",\"uri\":\"63c5a282c5b640d\",\"message\":\"Hello there\",\"user\":{\"id\":1,\"username\":\"admin\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"}}\n\n# command to send message from alex user using alex user token\ncurl -X POST http://127.0.0.1:8000/api/chats/63c5a282c5b640d/messages/ --data \"message=Ohh hey there admin whats up\" -H \"Authorization: Token 0e7497a938f06c83f6f07853480e24ad0448e188\"\n\n# output\n{\"status\":\"SUCCESS\",\"uri\":\"63c5a282c5b640d\",\"message\":\"Ohh hey there admin whats up\",\"user\":{\"id\":3,\"username\":\"archit\",\"email\":\"archit@services.com\",\"first_name\":\"\",\"last_name\":\"\"}}\n\ncurl http://127.0.0.1:8000/api/chats/63c5a282c5b640d/messages/ -H \"Authorization: Token 6e6b6b6f4f1efe2e3f88db8dbec8da74cc556cf6\"\n\n# messages history\n{\"id\":4,\"uri\":\"63c5a282c5b640d\",\"messages\":[{\"user\":{\"id\":1,\"username\":\"admin\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"},\"message\":\"Hello there\"},{\"user\":{\"id\":1,\"username\":\"admin\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"},\"message\":\"Hello there\"},{\"user\":{\"id\":3,\"username\":\"archit\",\"email\":\"\",\"first_name\":\"\",\"last_name\":\"\"},\"message\":\"Ohh hey there admin whats up\"}]}\nF:\\coder\\django_chat\\chat\u003e\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexmhack%2Fdjango_chat","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexmhack%2Fdjango_chat","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexmhack%2Fdjango_chat/lists"}