DasUnicorn / WordWeave

Reddit style news site
0 stars 1 forks source link

Weaver

Weaver is Reddit style news site. Users can create Threads on diverse topics and sparking discussions. Each Thread functions as a dynamic structure where users can share insights, opinions, and reactions through comments. With the ability to upvote/downvote Threads and comments, users actively shape the narrative and show their support or dislike.

Behind the scenes, Weaver is powered by Python, using a Django web framework. The user interface is crafted using Boostrap CSS and JavaScript. Furthermore, Weaver is deployed on Heroku, a cloud platform as a service (PaaS).

You can check out the live-site.

Mock Up

Content

Technologies Used

Languages Used

Python, HTML/CSS, Java Script

Frameworks, Libraries & Programs Used

User Experience and Workflow

Target Audience

The target audience for Weaver includes creators, enthusiasts, and curious minds with a focus on engaging young and hip generations through its modern and vibrant design. These individuals are passionate about engaging in conversations on the platform or sharing ideas in the comment section.

Epics

Sadly GitHub does not support epics. Therefore Epics have been created as a separate Issue, containing a list of all User Stories belonging to this Epic. They have the label "epic" to filter for them.

User stories

Features in this project are structured through user stories. Each User Story contains:

Workflow

In the development process, a Kanban board in form of a github project is used to manage the tasks and track their progress. Initially, all issues are collected and placed in the backlog. During each iteration, a set number of issues are selected to be developed and assigned to the current milestone. These selected issues are then moved to the 'To Do' column on the Kanban board, indicating that they are ready to be worked on.

When working on the tasks begins, the status of the issues is updated to 'In Process'. This signifies that active development is underway. Once the development work is completed, the issues move to the 'Testing' column, where they undergo thorough testing to ensure the acceptions criterias are met.

If an issue passes testing successfully, it is considered 'Done' and is moved to the final column on the Kanban board.

If an issue encounters blockers or dependencies that prevent progress, it is moved to the 'Waiting' column. Here, it remains until the blockers are resolved, allowing work to resume.

Throughout its journey, from 'To Do' to 'Testing' and ultimately 'Done', detailed information including comments, Git commits, and testing results is added to each issue. This approach ensures transparency regarding the path and work undertaken for every issue.

Kanban-Board

Design

The design process began with the creation of three concepts: a retro-inspired theme featuring nostalgic colors and forms, a modern and elegant approach with sleek lines and refined aesthetics, and a hip neon profile.

These concepts were presented to other people for feedback and evaluation. Their insights and preferences were carefully considered for each design. After thorough deliberation, the trendy cool neon design was the favored choice. Its vibrant colors, dynamic elements, and modern flair resonated most strongly with the audience.

screenshot trendy neon design idea

Wireframes

Timeline

Desktop: \ Wireframe Desktop Timeline \ Mobile: \

Wireframe Mobile Timeline

Profile

Desktop: \ Wireframe Desktop profile \ Mobile: \

Wireframe Mobile profile

Features

Existing Features

Navigation Bar

The Navigation Bar guides the User througout the platform.

Visitors

People who haven't created a user account yet have the option to sign in. People with user accounts can use the login functionality.

Navigation Bar on Mobile
Signed-In Users

For people that have signed in, the Navigation Bar gives the Users easy acces to their profile.

Navigation Bar for Signed in Users
Admins

Admins of the platform can reach the django admin panel easily through the Navigation bar.

Navigation Bar for Signed in Admins

User Account:

The User Accounts in this project are managed by the AllAuth Django package.

User Sign up

Users can register on the page with a username, an optional email, and password. After registration all their information is stored in the database.

Sign Up Form
User Login

Registered users can log in to their accounts using their credentials.

Login Form
User Logout

Logged-in users can log out of the site by clicking the logout link in the navigation bar. They have to confirm their decision.

Sign out Confirmation
change Password

Registered users can reset their password.

Change Password
Reset Password, through mail

If a user has entered a valid email adress, they can reset their password by mail with a verification link. This is especcilly usefull when the user has fergotten their password.

Reset Password By Mail
Delete User Account

Users have the option to delete their accounts, removing all associated content from the platform.

Access Settings

For easier acces to all options, settings are displayed on an additional page, making it easier for a user to find all possibile Account Options.\

Settings

Profile:

Each User on the platform has a User Profile.

Profile Picture and Bio

Each user has a profile where they can set a profile picture and update their bio text. After signing up the user starts with a default picture and default bio text.\

Profile

Update Profile \

Default User Profile
User Content Display

The profile displays all threads/posts created by the user. Threadlist from Users Profile \

Threadlist from Users Profile
Vote Collection

Users can collect votes on their posts, threads, and comments. The total number of votes collected across all content is shown on the profile for each user.\

Vote from a Profile

Threads, Comments, Votes:

On this platform Users engage by writing Threads. Each Thread can be commented. Threads, as well as comments can be up- and down voted by Users.

Create Threads

Logged-in users can create threads on the platform. Threads appear in the global timeline and can be commented on by other logged-in users.\

Write Thread
Create Comments

Logged-in users can create comments on the platform. Comments appear below the thread they relate to.\

Comment Form
Upvote and Downvote

Users can upvote or downvote threads and comments to give and collect points on the platform.\

Vote Option next to a Thread
Edit Threads

Logged-in users can edit their threads on the platform.\

Edit and delete buttons
Edit Comments

Logged-in users can edit their comments on the platform.\

Edit, Delete buttons Edit Comment
Delete Threads and Comments

Logged-in users can delete their threads and comments. Confirmation is asked before the deletion is executed.\

Delete Comment Delete Thread
Change or Delete Votes

Logged-in users can delete or change their votes on threads and comments. If the User is logged in, their vote for each thread is displayed with a yellow background behind the up or downvote icon. If the opposite icon is pressed, the vote changes, if the current vote is pressed again, it is removed.\

Vote Option next to a Thread

Tags:

Each Thread can be created with tags. Tags can be followed by users to create personal timelines.

Tag Site

Each Tag has their own site, which desplayed all threads created with that tag.

Tag Site
Follow Tags

On Tag Sites, the user has the option to follow a tag by pressing the botton on top of the site.\

Follow Tag
Unfollow Tags

On Tag Sites, the user has an option to unfollow tags, if they follow them.\

Unfollow Tag
Overview over all tags you follow

By navigating through the profile setting, a logged-in User can get to a view that shows them all tags they are following. This gives them an easier place to remove them.\

All Tags

Global and Tag-based Timeline:

Global Timeline

The global timeline is visible to all Users and Visitors, showcasing threads from across the platform.

Global Timeline
Personalized Tag Timeline

Users can follow tags, and threads with these tags appear in their personalized tag-based timeline for a tailored browsing experience.

Tag Based Timeline
Pagination

For a better load time and usage with multiple threads, the timeline has a pagination feature.\

Pagination

Messages

Users get notified about changes on the platform through the django message system.\

All Tags

Django Admin Panel

Inside the Django Admin panel, Administrators have acces to the models of the django project.

All Tags

Info Page

An information page let's intrested visitors know what Weaver is all about.

Info Page

Features Left to Implement

Moderation:

Dark Mode:

Accessibility

Fonts

The font 'Permanent Marker' was chosen as the font for the logo as well as logo related statement text. It is legible, but also rough and gritty. Breaking the clean visual of the site.

'Alatsi' was chosen for the Headings and Roboto for the general text. Both are easily readable and clean in their optic.

Colors

The website's style and vibe are defined by its color scheme. Chosen to resemble a neon spectrum, these colors are selected to provide strong contrast when combined.

001A23, #FFFFFF, #BAFF2A, #F52789, #FFFF33

color scheme

Data

Database schema

The Database was planned as the following:

Database Schema

After realizing this project, the database structure is the following:

Current Database Schema

Current Database Schema, exported with django-extensions

Security

I try to keep things in my Django project as secure as possible. I made sure that only logged-in users could do certain actions in the app. I did this by using the '@login_required' parameter in Django. For the class-based views, I relied on the LoginRequiredMixin mixin to make sure only authenticated users could access certain parts of the app.

If someone tries to do logged in required actions without logging in, they get redirected to the sign-in page.

The safety of user registration and login processes by integrating the AllAuth Django extension. This extension provides a robust framework for managing user authentication securely, offering features such as secure password storage and authentication workflows.

Sensitive information (such as the email adress) remains accessible only to authorized individuals, like admins an the owner of the data. Users are restricted from viewing or accessing sensitive data belonging to other users. This is due to the database, which requires a login.

Testing

Lighthouse Test

The Lighthouse Test results show excellent results:

Lichthouse test Results Lighthouse Test Results Profile

Jigsaw CSS Validator

The Jigsaw CSS Validator throws one error: According to the test the Property text-wrap: pretty doesn't exist. In reality this is a fairly new css property. It is not yet implemented for all browser. (see below) Jigsaw Result Can I use, screenshot Screenshot From caniuse.com

W3C Validator

The W3C HTML Validator shows no errors. HTML Check HTML Check

JS Hint Validator

The JS Hint Validator shows no errors. JS Hint Result

Accessibility

The result of the WAVE Web Accessibility Evaluation Tool shows no Errors. Wave Check Wave Check

PEP8

The Pep8 CI Linter was used, returning the following results:

App File CI Linter Result
authentication forms.py All clear, no errors found
models.py All clear, no errors found
urls.py All clear, no errors found
views.py All clear, no errors found
tests/test_forms.py All clear, no errors found
tests/test_models.py All clear, no errors found
tests/test_urls.py All clear, no errors found
tests/test_views.py All clear, no errors found
follow models.py All clear, no errors found
urls.py All clear, no errors found
views.py All clear, no errors found
weave_manager forms.py All clear, no errors found
models.py All clear, no errors found
urls.py All clear, no errors found
views.py All clear, no errors found
tests/test_form.py All clear, no errors found
tests/test_models.py All clear, no errors found
tests/test_view.py All clear, no errors found
tests/test_voting.py All clear, no errors found

Manual Testing

To ensure the functionality of the site on top of the written tests: All main features are tested manually.

Feature Expected Outcome Testing Performed Result Pass/Fail
Sign Up When the User is signing up with valid credentials, an account should be created. After Signing up, the User is logged in. Signing up with username = test, email = test@test.de, password = Secure123! The User is logged in. An Account has been created. Pass
Invalid Sign Up When the User is signing in with invalid credentials, they get informed about the invalid data. Signing up with username = superlongusername123456789superlong, email = test(at)test.de, password = 123 The User gets informed about an invalid email and password. The Username gets shorten to the appropriate length after creation. Pass
Login Can login in with the correct password and username. Login with username = test, password = Secure123! User is logged in. pass
Invalid Login Users can't login with invalid credentials. Login with username = test, password = InSecure123! The user is not logged in. Pass
Logout After Confirming to logout, the user gets logged out. Pressing Button to confirm the logout. User is logged out. Pass
User Profile Logged in Users can reach their Profile by pressing Profile in the Navbar. Logging in. Pressing Profile. The profile of the logged in user opens. Pass
Update Profile Users can update their bio and profile pic by selecting both under Your settings -> Update Profile. Logging in. Navigation to change profile. Update Bio and picture. Bio and picture changes to new data Pass
Clear Profile Picture and Bio When changing the profile bio to empty and clear the profile picture, both should be removed. Clearing profile picture from form and leave the bio empty. Profile picture is removed, default profile picture is displayed. Bio is removed. Pass
Changing Password Setting a new password results in new login credentials. Changing password. Logout. Login with old credentials. Login with new credentials. Login with old password does not work, Login in with new password is successful. Pass
Add email Adding a new email with Your Settings -> Update email should result in connecting a new email with the user. Adding a new email. Email successfull displayed. Pass
Reset password by mail When pressing the "forgotten password" option and entering an email, a verification email is send. In this email a link can be pressed to reset the password. Entering an email adress and reset a password. An email with an link to reset the password arrives. pressing the link gives the option to rest a password. Pass
Delete Profile After confirming the deletion a user account should get deleted. All threads, comments and votes made by the user should get deleted with it. Confirming the Delete of User profile. User is logged out. Account is delted. All threads, comments and votes by this user are gone. Pass
Thread Creation Valid Data should create a new thread. The thread gets displayed in the global timeline under the users threads and on the site of the uses tag. If the user follows the used tag, the thread gets shown in the tag based timeline. create a thread. Title = "This is a test", content = "This should work.", tags = "test". Follow the tag test. The thread is created. The thread shows in the global timline, tagbased timelin, on my profile and on the tag site of test. Pass
Invalid Thread Creation Invalid threads should not be accepted. Tryingt to create an empty thread. fields that can not be empty show errors. Pass
Create Thread with picture When creating a thread with a picture, the picture should be shown in the thread detail. Creating a thread with a picture. The picture shows up in the thread detail. Pass
Change Picture in thread When a thread is edited and a picture is changed. The new picture is shown in the thread detail. Creating a thread with picture 1. Edit the thread to picture 2. Picture 2 is shown in the thread detail. Pass
Clear Picture in thread When a picture is cleared from a thread, it should be removed from the thread detail. Creating a thread with picture. Remove Pic. Picture is remove from thread. Pass
Markdown in threads When using markdown formatting in thread content, the correct markdown styling is displayed. A thread with the content "#This is a test / Does this work?" is created. Markdown styling is shown in the thread detail site. Pass
Leaving a Comment Logged in Users can leave a comment under a thread. Opening a thread. Filling out the comment form. submit the form. The comment gets displayed under the thread. Pass
Markdown for Comments Comments have markdown styling. Trying "## Hey / Does this work?" in the body of the of the comment. submit comment. Markdown formatting is displayed. Pass
Tag Site When pressing on a tag, logged in users should see a follow and unfollow option. All threads with this tag sgould be displayed. Clicking on a tag. The tag sites with the unfollow/follow button opens. All threads with this tag are displayed. Pass
Follow a tag When a user is not following a tag the option "follow this tag" is presented on the tag site. A click makes the user follow the tag. All threads with this tag now appear in the tag based timeline. Clicking "follow this tag" on tag site. button changes to "unfollow this tag", seeing all threads with this tag in the tag based timeline. Pass
Unfollow a tag When a user unfollows a tag, all threads with this tag are getting removed from the tag based timeline. Clicking "unfollow ths tag" on tag site. No threads with this tag show in the tag based timeine. Button changes to "follow this tag" Pass
Global Timeline The global timeline shows all threads. Entering global timeline. It shows all threads. Pass
Info for unregistered User Users who haven't sign up yet should get a cool header, as well as a info what weaver is all about. Header on the landing page is shown. Login. Header is removed. Header is only visible for not logged in users. Pass
Tag based Timeline. Users should have the option to visit the tag based timeline after logging in. The tag based timeline only shows threads containg tags a user is following. Login. Choose Tagbased Timeline. The List of threads only contain threads with the tags the user follows. Pass
Upvoting Thread After pressing the arrow up next to the thread / above the vote count, the vote should count should move 1 up and the arrow up get a yellow background. Pressing the arrow up. The vote counts +1, the arrow up gets a yellow background. Pass
Downvoting Thread After pressing the arrow down, the vote should count -1 and the down arrow should get a yellow background highlight. Pressing the arrow down. The vote vount is -1, the arrow down has a yellow background. Pass
Changing the vote from Upvote to Downvote When the user decides to change their vote from an Up to a Downvote, the application should react accordingly. Upvoting a thread. Downvoting a thread. The vote count removed the upvote and entered a downvote. Now the downvote has a yellow background. Pass
Changing from Downvote to Upvote When the user decides to change their vote from a Downvote to an Upvote, the application should react accordingly. Downvoting a thread. Upvoting a thread. The count removed the Down vote and adds the upvote. the upvote has a yellow background. Pass
Removing an upvote on a thread. By pressing on an already made upvote, the vote should be removed. Upvoting. Upvoting again. the vote is removed. No arrow has a yellow background. Pass
Removing a downvote on a thread. By pressing on an already made downvote, the vote should be removed. Downvoting. Downvoting again. the vote is removed. No arrow has a yellow background. Pass
Upvoting comment After pressing the arrow up next to the comment / above the vote count, the vote should count should move 1 up and the arrow up get a yellow background. Pressing the arrow up. The vote counts +1, the arrow up gets a yellow background. Pass
Downvoting comment After pressing the arrow down, the vote should count -1 and the down arrow should get a yellow background highlight. Pressing the arrow down. The vote vount is -1, the arrow down has a yellow background. Pass
Changing the vote from Upvote to Downvote on a comment When the user decides to change their vote from an Up to a Downvote, the application should react accordingly. Upvoting a comment. Downvoting a comment. The vote count removed the upvote and entered a downvote. Now the downvote has a yellow background. Pass
Changing from Downvote to Upvote on a comment When the user decides to change their vote from a Downvote to an Upvote, the application should react accordingly. Downvoting a comment. Upvoting a comment. The count removed the Down vote and adds the upvote. the upvote has a yellow background. Pass
Removing an upvote on a comment. By pressing on an already made upvote, the vote should be removed. Upvoting. Upvoting again. the vote is removed. No arrow has a yellow background. Pass
Removing a downvote on a comment. By pressing on an already made downvote, the vote should be removed. Downvoting. Downvoting again. the vote is removed. No arrow has a yellow background. Pass
Administrators can reach the admin panel Administrators have the option to reach the admin panel over the navigation bar. Login with superuser account. Click "Admin panel" in navbar. The admin panel opens. Pass

Automatic Testing

This project contains Unittests to automatically test the application.

Coverage Report, creates by coverage:

Name Stmts Miss Cover Missing
authentication/__init__.py 0 0 100%
authentication/admin.py 8 0 100%
authentication/apps.py 4 0 100%
authentication/forms.py 25 2 92% 13-14
authentication/migrations/0001_initial.py 8 0 100%
authentication/migrations/0002_alter_user_bio_alter_user_profile_pic.py 4 0 100%
authentication/migrations/0003_alter_user_profile_pic_alter_user_username.py 4 0 100%
authentication/migrations/0004_alter_user_bio_alter_user_profile_pic.py 4 0 100%
authentication/migrations/__init__.py 0 0 100%
authentication/models.py 10 0 100%
authentication/tests/__init__.py 0 0 100%
authentication/tests/test_forms.py 10 0 100%
authentication/tests/test_models.py 13 0 100%
authentication/tests/test_urls.py 10 0 100%
authentication/tests/test_views.py 59 0 100%
authentication/urls.py 4 0 100%
authentication/views.py 63 2 97% 71, 91
follow/__init__.py 0 0 100%
follow/admin.py 3 0 100%
follow/apps.py 4 0 100%
follow/migrations/0001_initial.py 7 0 100%
follow/migrations/__init__.py 0 0 100%
follow/models.py 10 1 90% 16
follow/tests/__init__.py 0 0 100%
follow/tests/test_views.py 0 0 100%
follow/urls.py 3 0 100%
follow/views.py 42 31 26% 9-30, 34-53, 61-62
manage.py 12 2 83% 12-13
weave_manager/__init__.py 0 0 100%
weave_manager/admin.py 6 0 100%
weave_manager/apps.py 4 0 100%
weave_manager/forms.py 24 0 100%
weave_manager/migrations/0001_initial.py 8 0 100%
weave_manager/migrations/0002_rename_thread_comment_thread_commentvote_threadvote.py 6 0 100%
weave_manager/migrations/0003_remove_comment_votes_remove_thread_votes.py 4 0 100%
weave_manager/migrations/0004_thread_votes_alter_commentvote_comment_and_more.py 6 0 100%
weave_manager/migrations/0005_comment_votes.py 4 0 100%
weave_manager/migrations/0006_alter_thread_slug.py 4 0 100%
weave_manager/migrations/0007_thread_picture.py 4 0 100%
weave_manager/migrations/__init__.py 0 0 100%
weave_manager/models.py 145 20 86% 33, 48-53, 90-93, 120, 155-158, 176, 188, 195-196, 204-205
weave_manager/tests/__init__.py 0 0 100%
weave_manager/tests/test_forms.py 65 0 100%
weave_manager/tests/test_models.py 66 0 100%
weave_manager/tests/test_views.py 53 6 89% 81-91
weave_manager/tests/test_voting.py 139 0 100%
weave_manager/urls.py 3 0 100%
weave_manager/views.py 182 73 60% 44-49, 52-58, 74-78, 86-87, 90-109, 140-151, 156-166, 214-220, 228-238, 243-256, 262-273
wordweave/__init__.py 0 0 100%
wordweave/asgi.py 4 4 0% 10-16
wordweave/settings.py 57 14 75% 35, 145, 216-220, 224-230
wordweave/urls.py 6 0 100%
wordweave/wsgi.py 4 4 0% 10-16
TOTAL 1101 159 86%

The tests run without any Errors:

Using python3 (3.12.1)
Found 46 test(s).
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
./home/lana/.cache/pypoetry/virtualenvs/wordweave-jm8Ce3Z9-py3.12/lib/python3.12/site-packages/django/core/handlers/base.py:61: UserWarning: No directory at: /home/lana/Projects/WordWeave/staticfiles/
  mw_instance = middleware(adapted_handler)
.............................................
----------------------------------------------------------------------
Ran 46 tests in 24.402s

OK
Destroying test database for alias 'default'...

Fixed Bugs

Cascading Deletes for Votes

The Situation:

When a user deletes their profile, all threads, comments and votes the user has made on the platform should get deleted with it. The current set up is as followed:


class Thread(models.Model):
    (...)

    def up_vote(self, user):
        # Check if the user has already voted for the thread
        if not self.thread_votes.filter(user=user).exists():
            self.votes = F('votes') + 1
            self.save()
            self.thread_votes.create(user=user, value=1)
        elif self.thread_votes.get(user=user, thread_id=self.id).value == -1:
            self.votes = F('votes') + 2
            self.save()
            vote = self.thread_votes.get(user=user, thread_id=self.id)
            vote.value = 1
            vote.save()
        # Here need to come an exception that gets handle to inform the user that they have already voted.

    def down_vote(self, user):
        # Check if the user has already voted for the thread
        if not self.thread_votes.filter(user=user).exists():
            self.votes = F('votes') - 1
            self.save()
            self.thread_votes.create(user=user, value=-1)
        elif self.thread_votes.get(user=user, thread_id=self.id).value == 1:
            self.votes = F('votes') - 2
            self.save()
            vote = self.thread_votes.get(user=user, thread_id=self.id)
            vote.value = -1
            vote.save()

class ThreadVote(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    value = models.SmallIntegerField()
    thread = models.ForeignKey(Thread, on_delete=models.CASCADE, related_name="thread_votes")
The Problem:

After Deleting a User, their votes (as instances of the Vote Model) get deleted, but the value "votes" of the Thread itselfs is never. Since the Votes for each thread is are the Thread.values that get displayed. The Votes in the website are never updated.

The Solution:

The goal is to create a function within the ThreadVote Model that updates the value of the associated thread whenever a ThreadVote is deleted.

I tried this by overwriting the delete() function.

class ThreadVote(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    created_on = models.DateTimeField(auto_now_add=True)
    value = models.SmallIntegerField()
    thread = models.ForeignKey(Thread, on_delete=models.CASCADE, related_name="thread_votes")

    def delete(self, *args, **kwargs):
        # Update the thread's vote count before deleting the vote instance
        if self.value == 1:
            self.thread.votes = F('votes') - 1
        elif self.value == -1:
            self.thread.votes = F('votes') + 1

        self.thread.save()
        super().delete(*args, **kwargs)

The issue arose because, contrary to expectations, an overwritten delete function is not utilized for cascading deletes. Following the recommendation in the Django Docs to use pre_delete resolved the issue effectively.

@receiver(pre_delete, sender=ThreadVote)
def update_thread_votes(sender, instance, **kwargs):
    if instance.value == 1:
        instance.thread.votes = F('votes') - 1
    elif instance.value == -1:
        instance.thread.votes = F('votes') + 1
    instance.thread.save()

Default Pictures get deleted

The Situation:

After signing up the user recieves a default profile picture. The moment any user changes their profile picture, it is gone for everyone.

The Problem:

With the storage of pictures in the cloud bucket, it was implemented that the old picture was deleted the moment one of the users deletes their profile picture by chooseing a new one, the default image gets deleted from the bucket.

The Solution:

To solve this problem the default picture was removed as a concept from the model and instead implemented in form of a fallback inside the template itself. The default profile picture is now safely stored inside the static files and can not be deleted by users.

Before:

<div class="pt-5 d-flex md-rows align-items-center w-100 max-w-75">
    <img src="https://github.com/DasUnicorn/WordWeave/raw/main/{{ user.profile_pic.url }}" alt="Profile Picture" class="profile-pic bg-light rounded-circle">
    <div class="bg-light text-dark w-75 p-2 m-3 text-center">
        <h1>{{ user.username }}</h1>
        <p>{{ user.bio }}</p>
    </div>
</div>

After:

<div class="pt-5 d-flex md-rows align-items-center w-100 max-w-75">
    {% if user.profile_pic %}
    <img src="https://github.com/DasUnicorn/WordWeave/raw/main/{{ user.profile_pic.url }}" alt="Profile Picture" class="profile-pic bg-light rounded-circle">
    {% else %}
    <img src="https://github.com/DasUnicorn/WordWeave/raw/main/{% static 'img/default.png' %}" alt="Profile Picture" class="profile-pic bg-light rounded-circle">
    {% endif %}
    <div class="bg-light text-dark w-75 p-2 m-3 text-center">
        <h1>{{ user.username }}</h1>
        <p>{{ user.bio }}</p>
    </div>
</div>

Deployment

Local Development

How to Clone

  1. Click the code button and copy the link of your preferred clone option.
  2. Open the terminal in your code editor and change the current working directory to the location you want to use for the cloned directory.
  3. Type 'git clone' into the terminal, paste the link you copied in step 1 and press enter.

More detailed steps are provided by github: github guide to clone a repository

How to Fork

To fork the repository:

  1. Log in (or sign up) to Github.
  2. Go to the repository for this project.
  3. Click the Fork button in the top right corner.

Deploy locally

Install poetry. To install the dependencies for this project, run:

poetry install

To navigate the project, use the django-admin is Django’s command-line utility for administrative tasks. This django docs outlines all it can do.

Usage

django commands follow the following pattern:

$ django-admin <command> [options]
$ manage.py <command> [options]
$ python -m django <command> [options]

Development

python manage.py runserver

Starts a lightweight development web server on the local machine.

Deployment Using Heroku

  1. Register for an account on Heroku or sign in.
  2. Create a new app.
  3. Name your App.
  4. Connect your github repository to Heroku app.
  5. Create a Live Database by adding the postgreSQL add-on.
  6. Create a Cloudfare Account and set up a R2 Bucket.
  7. Create and Set up an email account for verification mails.
  8. Set Config Vars for your cloudfare bucket (AWS_S3_SECRET_ACCESS_KEY), database (DATABASE_URL) and email(EMAIL_HOST_PASSWORD).
  9. Deploy from "deploy", or choose an automatic deploy option.

Credits