HW4 - Seddit
Due Date: Tuesday 4/29 11:59PM
For this assignment, you’ll be creating a Reddit clone (hence the terrible name “Seddit”) using Django! Seddit will have the following pages:
- User log in and sign up
- Homepage
- Create post
- Post view (including commenting, upvotes, and deletion)
- Subseddits (basically sub forums if you’re not familiar with Reddit)
No code will be given, you will need to develop everything from scratch! As a starting point, you may find it useful to follow or adapt the code from the Django Votr guide.
The overall task can be broken up into a few large steps:
- Project setup
- Define and create models
- Implement user authentication
- Implement endpoints
You will primarily graded on functionality. That is, does everything work as intended? Edge cases and errors will not be graded unless the write explicitly mentions that edge case or error.
Project Setup
First, you’ll need to generate a Django project. Create a folder named seddit
and start a Django project within it:
mkdir seddit
django-admin startproject seddit seddit
Now, navigate to the seddit
folder and create an app called forum
, which is where you will be implementing all your logic:
cd seddit
python manage.py startapp forum
Model
You will need to define your database models before implementing any views. There will be at least four models to implement (potentially more if you are attempting to build any extra credit): Post, Tag, Upvote, and Comment. Define these in forum/models.py
. You may find it useful to add these models to the Django admin app to create test data. The tables should be defined as follows:
Post
This object will be our representation of a forum post.
- user: a foreign key to the built in Django User
- title: the title of the post (CharField)
- content: the content of the post (CharField)
- created_at: an auto timestamp of the creation of the post (DateTimeField)
- updated_at: an auto timestamp of when the post was last updated (DateTimeField)
Tag
Posts can have tags, similar to hashtags on Twitter. Each tag will act as a subseddit itself, see the subseddit section below.
- post: a foreign key to Post
- tag: the name of the tag (CharField)
- There should be a uniqueness constraint on (post, tag). That is, no post can have the same tag twice.
Upvote
Upvotes represent a user’s upvote on a post.
- post: a foreign key to Post
- user: a foreign key to User
- There should be a uniqueness constraint on (post, user). That is, no user can upvote the same post more than once.
Comment
Posts can have comments.
- post: a foreign key to Post
- user: a foreign key to User who made the comment
- content: the content of the comment (CharField)
- created_at: an auto timestamp of the creation of the post (DateTimeField)
- updated_at: an auto timestamp of when the post was last updated (DateTimeField)
Tasks
At this point, you may find it useful to first create a skeleton of the needed routes before proceeding. The order of these tasks are laid out in what I think is the most intuitive order to tackle things, but you might find it easier to do things in a different order.
User Log In and Sign Up
This should have the same functionality as the Django Votr application: login, logout, and signup.
Login
This endpoint should be the route /login
. When a GET request is made, it should display a form for the user to login. This form should have a username and password field and make a POST request to /login
when submitted.
When a POST request is made, if their credentials are valid, it should authenticate the user, login them in, and redirect to the homepage. An error message should be displayed to the user if their credentials are invalid, otherwise, an HTTP 500 error should be raised.
Signup
This endpoint should be the route /signup
. When a GET request is made, it should display a form for the user to signup. This form should have a username and password field and make a POST request to /signup
when submitted.
When a POST request is made, it should attempt to create a new user with the provided username and password. If username or password are not provided, display an error message prompting the user to fill in the missing field. If the username is taken, display an error message to the user saying the username is taken. If user creation is successful, display a message saying user creation was successful.
Logout
This endpoint should log the user out when a POST request is made to /logout
.
Homepage
This is the homepage. It should serve a GET request to /
.
- Your homepage should display a list of the 10 most recently created posts.
- Each post should display its creation date, title, author, and tags.
- Each post’s title should be a link to that post’s detail page.
- If there are no recent posts, display something along the lines of “No posts to show.”
- If a user is logged in, add a link to the create post page.
Create Post
Create post should serve both GET and POST to /create_post
. Both of these endpoints should be authenticated, i.e.
a user must be logged in.
- When a GET request is made, render a form to create a post. There should be an input for title, tags, and content.
- You may assume a specific format for tags, e.g. a comma separated list.
- This form should make a POST request to
/create_post
when submitted.
- When a POST request is made, the view should properly create a new
Post
in the database.- Once the post is created, it should redirect the user to the post detail page for the new post.
Post Detail
This endpoint will likely be the most involved. It may be easiest to come back to the page as you implement other endpoints.
Post detail should serve GET to /post/<int:post_id>
. The page should display:
- The title, creation time, author, and content of the post.
- The tags of the post.
- The number of upvotes the post has.
- A list of comments the post has, in descending creation date order.
- Each comment should display the username and comment itself.
In addition, the page should provide functionality for the following:
- A button to upvote the post.
- This button should make a POST request to
/post/<int:post_id>/upvote
.
- This button should make a POST request to
- If the user who created the post is logged in, display a “delete post” button.
- This button should make a POST request to the
/post/<int:post_id>/delete
endpoint.
- This button should make a POST request to the
- A form to submit a comment on the post. It should have a field for the comment itself and a button to submit the comment.
- The form should make a POST request to
/post/<int:post_id>/comment
. If successful, the comment should appear on the page afterwards.
- The form should make a POST request to
Post Comments
Post comment should be a POST request to /post/<int:post_id>/comment
. This endpoint should be authenticated. It should create a Comment
in the database and then redirect the user back to the detail page for the post, meaning that the user should see their comment afterwards.
Upvoting Posts
Upvoting post should be a POST request to /post/<int:post_id>/upvote
. This endpoint should be authenticated. It should create aVote
in the database and then redirect the user back to the detail page for the post. If a vote already exists for that user and post, you do not have to surface any errors.
Deleting Posts
Delete post should be a POST request to /post/<int:post_id>/delete
. This endpoint should be authenticated and additionally should delete the corresponding post only if the authenticated user owns it. It should redirect to the homepage afterwards.
Subseddits
Subseddits should be a GET request to /s/<subseddit>
. The purpose of this page is to be something similar to subreddits. The page for each subseddit should only include posts with a tag equal to the subseddit
. It may be helpful to finish the above first, then copy your index.html
as a starting point.
Extra Credit
Extra credit for this assignment is open ended. Generally, any additional functionality will count! Some ideas (in roughly easiest to hardest):
- Making the webapp pretty, i.e. adding a nav bar, a theme, etc
- Searching post titles
- User profiles
- Deploying to production!