Developer: Aleksander Kisielewicz
View live api here đź’»
TravelShutter API was developed as a part of Portfolio Project #5 (advanced front-end) for Diploma in Full Stack Software Development at Code Institute.
Project purpose was to build a back-end application that provides data and full CRUD (create, read, update, delete) functionality to React front-end application.
- Deployed front-end: travel-shutter.herokuapp.com
- Front-end repo: github
- Project
- Logic and features
- Technology
- Testing
- Bugs/known issues
- Deployment
- Possible future development
- Credits
Project's Kanban board @GitHub Projects
Project's Table view @GitHub Projects
To keep track of progress, I used a kanban board divided into following sections: "to do", "in progress" "done" and "future enhancements" that allowed to visualize all tasks and prioritize next steps.
By using agile methodology, I was able to stay organized and focused on delivering the most important features, while also allowing flexibility for future development.
Milestone | User story |
---|---|
Profile app | #1 As a user, I want to be able to create a profile, so I can provide information about myself. |
Profile app | #2 As a user, I want to be able to edit my profile, so I can update my name, bio, and Instagram handle. |
Profile app | #3 As a user, I want to be able to upload an image for my profile picture, so I can personalize my profile. |
Profile app | #4 As a user, I want my profile to display the date and time it was created and edited so I can see when my profile was established and updated. |
Profile app | #5 As a user, I want my default profile picture to be set if I haven't uploaded a custom image, so my profile always has an image present. |
Profile app | #6 As a site admin, I want profiles to be automatically created when users sign up for an account, so I don't have to manually create it. |
Post app | #7 As a user, I want to be able to create a new post by providing a title, category, optional EXIF data, post content, and an image. |
Post app | #9 As a user, I want to be able to view the details of a specific post, including its title, category, creation time, and other optional fields. |
Post app | #10 As a user, I want to be able to update my posts and be able to delete them. |
Post app | #11 As a user, I want to be able to filter posts by provided fields, so that I can see posts related to specific criteria. |
Post app | #12 As a user, I want to be able to search for posts by their title or content, so that I can find posts that contain specific keywords. |
Post app | #13 As a user, I want to be able to upload an image for a post and have it displayed along with other post details. |
Post app | #22 As a user I want to be able to add tags to my posts and be able to display tagged posts so I can easily find the content that I'm interested in. |
Comments app | #14 As a user, I want to be able to add a comment to a specific post. |
Comments app | #15 As a user, I want to be able to edit the comments that I have posted. |
Comments app | #16 As a user, I want to be able to delete a comment that I have posted. |
Comments app | #17 As a user, I want to be able to see the total number of comments I have posted. |
Comments app | #18 As a user, I want to be able to view the details of a specific comment, including its content, creation time, and the associated post. |
Likes app | #19 As a user, I can post a "like" or remove it for a specific post. |
Likes app | #20 As a user, I can view the list of likes that posts received with details such as users who added likes, and time added. |
Followers app | #21 As a user, I want to be able to follow other users and see who is following me.) |
Followers app | #23 As a user, I want to be able how many users follow me, and also how many users I follow, so I can keep track of the popularity of my profile.) |
Project uses cloud-based PostgreSQL database provided by ElephantSQL as a service. ElephantSQL is known for its ease of use, reliability, and is a popular choice for Django projects that requires PostgreSQL database. It offers web interface with console for SQL queries. Database URL including API key is stored as environmental variable in heroku.
To generate model diagrams I used django-extensions with python library pygraphviz. They show relationship between models.
All django apps:
Model | Description |
---|---|
Profile | The Profile model represents a user profile. It is associated with the User model through a one-to-one relationship. The model includes fields such as name, bio, equipment, and instagram to capture relevant informaiton for further frond-end use. Time fields are also present to track timestamps. Default profile image is provided if user didn't upload his own. |
Post | This model represents a website post and contains fields for the post's title, owner, category, tags, image, location, content, creation and update times. |
Comments | This model represents a comment on a website's post and contains fields for the post it belongs to, the commenter's name, comment's body, and creation/update time. |
Likes | This model represents likes on a website's post and contains fields for the post it belongs to, the owner and timestamp. |
Followers | This model represents the relationship between user profiles. It allows users to follow each other by establishing a many-to-many relationship. |
Model profiles
Model posts
Model comments
Model likes
Model followers
- Python - high-level, imperative, general-purpose programming language.
- Markdown - markup language used to write README and TESTING documents.
- Cloudinary - cloude-based image and video API
- Django - python-based web framework with MTV architectural pattern
- Django Rest Framework - powerful and flexible toolkit for building Web APIs.
- ElephantSQL - PostgreSQL database as a service
- Git - Git was used for version control by utilizing the Gitpod terminal to commit to Git and Push to GitHub
- GitHub - GitHub is used to store the project's code after being pushed from Git
- Heroku - online app used to deploy project
- os - built-in Pythod module - used to save and import env variables
- cloudinary - cloud hosting used to store pictures
- dj3-cloudinary-storage - provides django integration with Cloudinary service
- dj-database-url - utility that allows configure environment variable to a connection string that includes the database engine
- django-allauth - integrated django accounts management
- django-cors-headers - handles the server headers required for cross-origin resource sharing (CORS)
- Django Filters - reusable Django application allowing users to declaratively add dynamic QuerySet filtering from URL parameters
- gunicorn - Python WSGI HTTP Server for UNIX
- oauthlib - framework for implementing open standard for authorization
- psycopg2 - PostgresSQL database adapter for Python language
- PyJWT - Python library for encoding, decoding and veryfying JSON Web Tokens
- pytz - library that provides support for working with time zones, converts the dates between zones
- requests-oauthlib - OAuth library suppor for python requests
- sqlparse - non-validating SQL parser for Python. It provides support for parsing, splitting and formatting SQL statements.
- pygraphviz - used to generate visualization of database model
- PyJWT - JSON Web Token implementation in Python
- Pillow - Pillow adds image processing capabilities to Python interpreter
- Issue: #24 Post serializer issue with profile_image field
An issue was found in PostSerializer class in posts/serializers.py. The read-only field profile_image for the PostSerializer class contains the wrong value "profile.profile.image.url". This didn't allow the serializer to access the URL of the profile image belonging to the owner of the post and display the image as intended.
Bug was fixed by changing profile_image field to serializers.ReadOnlyField(source="owner.profile.image.url").
Details of manual testing can be found in TESTING.md file.
App was deployed to heroku for the first time when django installation was completed to make sure that everything is working correctly.
- Navitate to ElephantSQL website, log in to your account
- In top-right corner click on green button "Create New Instance".
- Enter database name, leave plan field as is, optionaly enter tags.
- Select region, click on "Review" and then on "Create instance".
- Go to your dashboard, find newly created database instance, click on it.
- Copy URL starting with "postgress://"
- Paste this URL into env.py file as DATABASE_URL value and save the file.
os.environ["DATABASE_URL"] = "postgres://yourLinkFromDatabaseDashboard"
- Navigate to https://cloudinary.com/ and log in to your account.
- Navigate to dashboard/console https://console.cloudinary.com/console/ and copy your API link starting with "cloudinary://".
- Paste copied url into env.py file as CLOUDINARY_URL value and save the file.
os.environ["CLOUDINARY_URL"] = "cloudinary://yourLinkFromCloudinaryDashboard"
In order to protect django app secret key it was set as anviroment variable and stored in env.py. Please change your password accordingly.
os.environ["SECRET_KEY"] = "yourSecretKey"
Note: Repository was created using Code Institute template: https://github.com/Code-Institute-Org/ci-full-template
-
Login to Github and navigate to repository: https://github.com/alexkisielewicz/drf-travelshutter
-
Click on "Fork button" in upper-right corner and create a new form in your own account.
-
Open your repository in local IDE or using Gitpod. Preferred way is to used Chrome Gitpod Extension. When you install extension, green "Gitpod" button appears in your repository. Click on it to cread new workspace.
-
Go to workspace terminal and install all requirements using command: "pip install -r requirements.txt". All te packages will be installed. requirements.txt content:
asgiref==3.7.2 cloudinary==1.33.0 dj-database-url==0.5.0 dj-rest-auth==2.1.9 Django==3.2.19 django-allauth==0.44.0 django-cloudinary-storage==0.3.0 django-cors-headers==4.0.0 django-filter==23.2 djangorestframework==3.14.0 djangorestframework-simplejwt==5.2.2 gunicorn==20.1.0 oauthlib==3.2.2 Pillow==9.5.0 psycopg2==2.9.6 PyJWT==2.7.0 python3-openid==3.2.0 pytz==2023.3 requests-oauthlib==1.3.1 sqlparse==0.4.4
-
Local env.py file should be configured as on example below:
import os # Env vars os.environ["DEV"] = 1 os.environ["DATABASE_URL"] = "postgres://yourLinkCopiedFromElephantSQLDashboard" os.environ["SECRET_KEY"] = "YourSecretKey" os.environ["CLOUDINARY_URL"] = "cloudinary://yourLinkCopiedFromCloudinaryDashboard"
-
In order to save django changes in database migration needs to be made.
-
Use terminal commands:
python3 manage.py makemigrations python3 manage.py migrate
-
Create superuser to access admin area using terminal command (email is optional, password won't be visible when typing, confirm password twice):
python3 manage.py createsuperuser
-
App can be run in gitpod environment using terminal command:
python3 manage.py runserver
-
Go to Heroku and follow further instructions below.
-
Navigate to https://heroku.com/ login to your account and open dashboard. Click button "New" and select "Create new app" button.
-
Enter app name, I used "drf-travelshutter", chose your region and click on "Create app" button.
-
Click on newly created app and go to "Deploy" tab and then to "Deployment method" section. Authorize and connect your GitHub account, then find and select your repository.
-
Go to the "Settings" tab, click on "Reveal Config Vars" and add the following keys and values (all values should be strings without any quotation marks):
Key Value CLOUDINARY_URL cloudinary url beginning with cloudinary:// DATABASE_URL postgress url beginning with postgress:// DISABLE_COLLECTSTATIC 1 SECRET_KEY YourSecretKey, the same as in env.py ALLOWED_HOST yourappname.herokuapp.com -
Procfile required to run project on Heroku was already created but if you change your app's name please make sure that this change is reflected in Procfile. It can be found in your project's main directory. In my case Procfile looks as below:
release: python manage.py makemigrations && python manage.py migrate web: gunicorn drf_travelshutter.wsgi
-
After adding environmental variables and editing Procfile project is ready for deployment. In Heroku app's dashboard navigate to "Deploy" tab, scroll down to "Manual deploy" section. Select main branch from dropdown menu and click on "Deploy Branch".
-
After built is done, you should be able to see the button with the link leading to deployed app. In my case http://drf-travelshutter.herokuapp.com.
If I had more time or decide to develop app further I would add/improve following functionalities that I moved to olumn on project board:
- #22 As a user I want to be able to add tags to my posts and be able to display tagged posts so I can easily find the content that I'm interested in.
This project was built based on the Code Institute walkthrough project - Django Rest Framework for front-end Moments app.
- Code Institute course and learning platform
- The book "Python Crash Course, 2nd Edition: A Hands-On, Project-Based Introduction To Programming"
- StackOverflow
- Django - Django documentation.
- DjangoRestFramework - DRF documentation.
- My Mentor Jubril Akolade for helpful feedback and guidance at all stages of the project.
- Code Institute Slack Community for being invaluable knowledge base.