/project5-drf-api

DRF API for 5th project

Primary LanguagePython

The Red Crayon - API

The Red Crayon is a News platform for the artistic world. Users can read the latest articles on what is occurring in the art scene, as well as interact with other users via posts, comments, and follows. This section of the project is the backend API database built to support the ReactJS frontend, and it is powered by the Django Rest Framework.

DEPLOYED BACKEND API RENDER LINK

DEPLOYED FRONTEND RENDER LINK - LIVE SITE

DEPLOYED FRONTEND REPOSITORY

Table of Contents

User Stories:

All User Stories have been documented in their own file, the link for which can be found HERE.

I have included links to the GitHub Issues for this project, as well as the KANBAN board.

Database:

SQL Database model

Testing:

Validator Testing:

All files passed through PEP8 without error.

PEP8

Manual Testing:

  1. Manually verified each url path created works & opens without error.
  2. Verified that the CRUD functionality is available in each app via the development version: Articles, Events, Comments, Followers, Likes, Posts, Profiles
  • Checked this by going to each link.
  • Creating a new item.
  • Checking new item URL path.
  • Editing the item (not available for Likes, Followers or Users)
  • Deleting the item (Not available for Users or Profiles)
  1. Ensured search feature for Posts, Events & Articles apps returns results. Results not filtered for events:
  • Checked the views file for Events. Filter & search field functions were not indented correctly. Once amended, the search bar produced the desired results.
  1. Repeated the steps for the deployed API, and all pages except /profiles would load.
  • checked the code, and was unable to find an error, other than the "Server Error (500)" on the deployed link.
  • Reached out to Tutor support, and Ger was able to detect that the issue was with the database model.
  • reset the database with the following commands:
python3 manage.py migrate profiles zero
  • upon completion, & migrating the database once again , all links were now viable on the Heroku deployed link.
  1. Frontend App throws a 500 error when saving the posts form.
  • Logged in to admin panel of deployed API app. The same error arises.
  • migrated the posts app back to zero, and made the migrations again. The issue persists.
  • backed up the database python manage.py dumpdata > db.json, & then ran the following commands:
curl https://cli-assets.heroku.com/install.sh | sh
heroku login -i
heroku pg:info -a project5-drf-api
heroku pg:reset -a project5-drf-api
  • deleted 0001_initial.py files & __pycache__ from the migration folders in all apps.
  • Ran the migration commands again:
python3 manage.py makemigrations
python3 manage.py migrate
  • created a new super user to test functionality
python3 manage.py createsuperuser
  • Was now able to create a post via the deployed admin panel.
  • upon returning to the development version of the app, we were now unable to login or create a new user
  • clearing the browser cookies & cache, as well as relaunching the gitpod workspace resolved this.

Unfixed Bugs

  • None so far.

Technologies Used:

Main Languages Used:

  • Python

Frameworks, Libraries & Programs Used:

  • Django
  • Django RestFramework
  • Cloudinary
  • Heroku
  • Pillow
  • Django Rest Auth
  • PostgreSQL
  • Cors Headers
  • DrawSQL: An interactive ERD platform that allows you to set up your database tables, & build the connections between them for a visual layout.

Deployment:

Project creation:

  1. Create the GitHub repository.
  2. Create the project app on Heroku.
  3. Add the Postgres package to the Heroku app via the Resources tab.
  4. Once the GitHub repository was launched on GitPod, installed the following packages using the pip install command:
'django<4'
dj3-cloudinary-storage
Pillow
djangorestframework
django-filter
dj-rest-auth
'dj-rest-auth[with_social]'
djangorestframework-simplejwt
dj_database_url psycopg2
gunicorn
django-cors-headers
  1. Created the Django project with the following command:
django-admin startproject project_name .
  1. Navigated back to Heroku, and under the Settings tab, added the following configvars:
  • Key: SECRET_KEY | Value: hidden
  • Key: CLOUDINARY_URL | Value: cloudinary://hidden
  • Key: DISABLE_COLLECTSTATIC | Value: 1
  • Key: ALLOWED_HOST | Value: api-app-name.herokuapp.com
  1. Add two additional configvars once the ReactApp has been created:
  1. Created the env.py file, and added the following variables. The value for DATABASE_URL was obtained from the Heroku configvars in the previous step:
import os

os.environ['CLOUDINARY_URL'] = 'cloudinary://hidden'
os.environ['DEV'] = '1'
os.environ['SECRET_KEY'] = 'hidden'
os.environ['DATABASE_URL'] = 'postgres://hidden'

In settings.py:

  1. Add the following to INSTALLED_APPS to support the newly installed packages:
'cloudinary_storage',
'django.contrib.staticfiles',
'cloudinary',
'rest_framework',
'django_filters',
'rest_framework.authtoken',
'dj_rest_auth',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
'dj_rest_auth.registration',
'corsheaders',
  1. Import the database, the regular expression module & the env.py
import dj_database_url
import re
import os
if os.path.exists('env.py')
    import env
  1. Below the import statements, add the following variable for Cloudinary:
CLOUDINARY_STORAGE = {
    'CLOUDINARY_URL': os.environ.ger('CLOUDINARY_URL')
}

MEDIA_URL = '/media/'
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinartStorage'
  • Below INSTALLED_APPS, set site ID:
SITE_ID = 1
  1. Below BASE_DIR, create the REST_FRAMEWORK, and include page pagination to improve app loading times, pagination count, and date/time format:
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [(
        'rest_framework.authentication.SessionAuthentication'
        if 'DEV' in os.environ
        else 'dj_rest_auth.jwt_auth.JWTCookieAuthentication'
    )],
    'DEFAULT_PAGINATION_CLASS':
        'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
    'DATETIME_FORMAT': '%d %b %Y',
}
  1. Set the default renderer to JSON:
if 'DEV' not in os.environ:
    REST_FRAMEWORK['DEFAULT_RENDERER_CLASSES'] = [
        'rest_framework.renderers.JSONRenderer',
    ]
  1. Beneath that, added the following:
REST_USE_JWT = True
JWT_AUTH_SECURE = True
JWT_AUTH_COOKIE = 'my-app-auth'
JWT_AUTH_REFRESH_COOKIE = 'my-refresh-token'
JWT_AUTH_SAMESITE = 'None'
  1. Then added:
REST_AUTH_SERIALIZERS = {
    'USER_DETAILS_SERIALIZER': 'project_name.serializers.CurrentUserSerializer'
}
  1. Updated DEBUG variable to:
DEBUG = 'DEV' in os.environ
  1. Updated the DATABASES variable to:
DATABASES = {
    'default': ({
       'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    } if 'DEV' in os.environ else dj_database_url.parse(
        os.environ.get('DATABASE_URL')
    )
    )
}
  1. Added the Heroku app to the ALLOWED_HOSTS variable:
os.environ.get('ALLOWED_HOST'),
'localhost',
  1. Below ALLOWED_HOST, added the CORS_ALLOWED variable as shown in DRF-API walkthrough:
if 'CLIENT_ORIGIN' in os.environ:
    CORS_ALLOWED_ORIGINS = [
        os.environ.get('CLIENT_ORIGIN')
    ]

if 'CLIENT_ORIGIN_DEV' in os.environ:
    extracted_url = re.match(r'^.+-', os.environ.get('CLIENT_ORIGIN_DEV', ''), re.IGNORECASE).group(0)
    CORS_ALLOWED_ORIGIN_REGEXES = [
        rf"{extracted_url}(eu|us)\d+\w\.gitpod\.io$",
    ]
  1. Also added to the top of MIDDLEWARE:
'corsheaders.middleware.CorsMiddleware',
  • During a deployment issue, it was suggested by a fellow student, Johan, to add the following lines of code below CORS_ALLOW_CREDENTIALS:
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_HEADERS = list(default_headers)
CORS_ALLOW_METHODS = list(default_methods)
CSRF_TRUSTED_ORIGINS = [os.environ.get(
    'CLIENT_ORIGIN_DEV', 'CLIENT_ORIGIN',
)]
  • In addition, Johan also suggested to add the following import statement at the top of the settings.py file:
from corsheaders.defaults import default_headers, default_methods

Final requirements:

  1. Created a Procfile, & added the following two lines:
release: python manage.py makemigrations && python manage.py migrate
web: gunicorn project_name.wsgi
  1. Migrated the database:
python3 manage.py makemigrations
python3 manage.py migrate
  1. Froze requirements:
pip3 freeze --local > requirements.txt
  1. Added, committed & pushed the changes to GitHub
  2. Navigated back to heroku, and under the ‘Deploy’ tab, connect the GitHub repository.
  3. Deployed the branch.

Deploy to Render & ElephantSQL:

CREDITS:

Content:

  • The creation of this API database was provided through the step by step guide of the C.I. DRF-API walkthrough project.
  • All classes & functions have been credited.
  • Modifications have been made to the 'Profiles' & 'Posts' app models, and an additional two apps along with models, serializers & views have been created by me.
  • Oisin from Tutor support went above & beyond to assist me in resolving an issue with my database that prevented new posts from being created. The steps we took have been documented in point #5 of the Manual Testing section.

Media:

  • Default post image Photo by Artem Podrez from Pexels
  • Default profile image from Favicon