Assignment 5: Web Application with Models, Forms, and Images
due by 9:00 p.m. EDT on Friday 10/10/2025
Learning Objectives
After completing this assignment, students will be able to:
-
Use the Django ImageField to store and retrieve image files and their associated database records.
-
Use HTML forms to upload a image files to Django, including setting foreign keys to create 1-to-many relationships.
-
Use HTML forms to display images stored in the Django media directory.
-
Implement update and delete operations by inheriting from generic views, and creating appropriate URL routing in response to update and delete operations.
Pre-requisites: Assignments 4
Assignment 5 builds upon the case study you began in Assignment 3.
You must have completed Assignment 4 before you attempt Assignment 5.
This assignment requires the Python Imaging Library, Pillow to be installed.
If you have not already installed it in your virtual environment do so now:
# pipenv install Pillow
Case Study: Mini Insta
This assignment is part of an in-depth case study to develop a data-enabled web application. In the entire case-study, you will simulate the core features of the Instagram social networking application. Over the course of 5 parts, you will implement:
- Viewing, creating, and updating user profiles
- Viewing and creating posts
- Uploading images
- Viewing and adding followers
- Developing a feed to show posts from Profiles one is following
- Incorporating user accounts, authentication (login), and registration
This assignment is the third part of the case study.
Here is a sample implementation: MiniInsta part 3.
You do not need to match the data of this example, or even the way it is formatted. The look and feel of the application, as well as the data you dispaly, is entirely up to you.
Preliminaries
In your work on this assignment, make sure to abide by the collaboration policies of the course.
If you have questions while working on this assignment, please post them on Piazza! This is the best way to get a quick response from your classmates and the course staff.
For each problem in this problem set, we will be writing or evaluating some Python code. You are encouraged to use the VS Code IDE which will be discuss/presented in class, but you are welcome to use another IDE if you choose.
Important Guidelines: Comments and Docstrings
-
Refer to the class Coding Standards for important style guidelines. The grader will be awarding/deducting points for writing code that conforms to these standards.
-
Every program file must begin with a descriptive header comment that includes your name, username/BU email, and a brief description of the work contained in the file.
-
Every function/method must include a descriptive docstring that explains what the function does and identifies/defines each of the parameters to the function.
Continue working on the mini_insta Application
Continue to do this work within your existing Django project, within the mini_insta.
application that you worked on in Assignment 4.
Task 1: Revising the Photo model; uploading Photos
In the previous iteration of this assignment (i.e., assignment 4), we created a model
for a Photo and stored the image_url associated with an image stored elsewhere on the
World-Wide-Web. In this iteration of the assignment, we will add storage for image
objects within the Django media directory.
-
Revise the
Photomodel, to add an additional attribute calledimage_file. This attribute will refer to an image file (not a URL) that is stored in the Django media directory.**Do not remove the
image_urlattribute, as we need this for backwards-compatibility with existingPhoto.Add an accessor method called
get_image_url, which will return the URL to the image. This URL will either be the URL stored in theimage_urlattribute (if it exists), or else the URL to theimage_fileattribute, i.e.,image_file.url.Revise the
__str__method to be consistent with the way the actual image is stored, i.e.,image_urlvs.image_file.Recall that after you change models, you will need to run the
makemigrationsscript and themigratecommand to update your database.Important:
-
Before you can go on to step 2 (displaying a
PostwithPhotos stored byimage_file), you will need to add at least 1Photo(and maybe even 2) to your database using theadmintool to upload the file. -
When you add an
Phototo the database, you will need to also associate it with aPostobject. Take note of whichPost(for whichProfile) this is, so that you can test that thePhoto(s) display properly (see below).
-
-
Displaying a post. You might need some revisions to the code that displays
Posts andPhotos, e.g. theshow_post.htmlpage. Revise to ensure that you are using theget_image_urlmethod to access the image’s URL.Verify that it works for both:
-
one the
Posts for which you stored an image URL. -
one the
Posts for which you uploaded an actual image.
-
Revise the process for creating a Post. Specifically, you will need to revise
the CreatePostForm, the create_post.html template, and the CreatePostView.
-
In the
CreatePostForm, revise to remove theimage_url. While it is still part of the model for backwards-compatibility, it should no longer display for the user to enter a URL. -
In the
create_post.htmltemplate, you will need to to create a form field to be able to select and upload one or more actual image files. For example:
Use the form
input type="file", as well as the attribute"multiple"to be able to select more than one. Be sure to give this field a name, so that you can look for it in the form processing code (below).Be sure to include the attribute
enctype="multipart/form-data"in the<form>tag, so that the form will be able to send the image data over HTTP. -
In the
CreatePostViewclass, you will need to modify the code in theform_validmethod. Previously, you retrieved theimage_urlfrom therequest.POSTdata and used that to create aPhotoobject. Comment this part out.In it’s place, you will need to read the data from
self.request.FILES. Try readingfiles = self.request.FILES.getlist('files'), which will return a list of 0 to many files. You can process this with a loop to create and savePhotoobjects. -
Test everything! Start at this URL pattern:
'http://127.0.0.1:8000/mini_insta/. Go to any profile, and then use the create post form to upload an image. Test that the image gets stored in Django, and finally that it displays on theshow_postpage.
Important: Add files to git!
-
You’ve just reached a good stopping point.
-
This is an excellent time to add your files to git, commit your changes, and push your changes to GitHub before anything gets F@&#ed up.
Task 2: Updating an existing Profile
-
Create a new form class
UpdateProfileFormwhich inherits fromforms.ModelForm.Be sure to specify the inner-class
Meta, which relates this form to theProfilemodel. Specify the list offieldsthat this form should set (i.e., all of the data attributes of theProfileclass, except NOT the user’susernameandjoin_date, which should not be changeable). -
Create a class-based view called
UpdateProfileView, which inherits from the genericUpdateViewclass. Be sure to specify the form this create view should use, i.e., theUpdateProfileForm. Also, specify the name of the template to use to render this form, which must be calledmini_insta/update_profile_form.html. -
Create the template file
mini_insta/update_profile_form.html, to render the HTML form.You may use your discretion/imagination about how this template should display the form fields, but you must include labels for each field to show what input is expected. Upon submission, your form will be handled by the generic
UpdateViewclass, which will update theProfilerecord for this model and store the update in the database.On this page, include a ‘cancel’ button, which should stop the update operation and return to the profile page. For example:

-
Edit the
mini_instaproject’surls.pyfile. Create a URL mapping to route requests from the URL pattern'profile/<int:pk>/update'to theUpdateProfileViewview. Name this URLupdate_profile.Test your URL! Try this URL pattern:
'http://127.0.0.1:8000/mini_insta/profile/1/update(or a similar URL with a different primary key).You should see a form to update the profile, and it should be pre-filled with the existing data for this
Profilerecord. Change something in the form, and use the submit button to submit it to the server.A complication: Implementing the
get_absolute_urlmethodTest out this URL again. Now when you submit the
create_post_form.htmltemplate, you should see an error:No URL to redirect to. Either provide a url or define a get_absolute_url method on the Model.To solve this problem, you will need to implement the special method
get_absolute_urlon theProfilemodel class. Within that method, you will need to return the URL corresponding to theProfilethat was updated. For example, if we just updated aProfilewith primary key of 5, we should return the URL/mini_insta/profile/5.Upon submission you should be routed back to the profile page, on which you should see the update.
If you have errors, resolve them now before continuing on to the next part.
Finally, add an
Update Profilelink or button to theshow_profile.htmltemplate, so that you can click that link and reach the update form. For example:
Important: Add files to git!
-
You’ve just reached a good stopping point.
-
This is an excellent time to add your files to git, commit your changes, and push your changes to GitHub before anything gets F@&#ed up.
Task 3: Updating and Deleting Posts
In this part, you will create a way for to the user to update or delete a Post.
This will involve:
-
Links (or buttons) on the
Postpage labeledupdateanddelete. -
A view to handle the each of these operations.
-
A template to show a confirm/cancel option (form).
-
A
urlto trigger each operation.
For example, notice the links for update and delete:

These buttons (actually links that look like buttons) link will connect to the URLs for
the DeletePostView and UpdatePostView, respectively.
-
Create a class
DeletePostView, which inherits from the genericDeleteViewclass. This base class will do most of what we want, but we will need to override some methods below. Set themodelandtemplate_nameattributes.Override the
get_context_datamethod, which will provide the context data needed to support thedelete_post_form.html. Specifically, this context must provide the variables:-
post, which is a reference to thePostto be deleted. -
profile, which is theProfileof the user who made thePost.
Override the
get_success_url(self)method, to return the URL to which the user should be redirected after a successful delete operation. Specifically, when aPostis deleted, the user should be redirected to the profile page of the user whosePostwas deleted. -
-
Create the template file
delete_post_form.html. This template will display thePostthat will be deleted, and contain 2 small forms:-
One to confirm the delete, which will send a
POSTback to the same URL at which you are trying to do the delete. -
One to cancel the delete, which will send a
GETto URL to redisplay the profile page.Hint: you will need to set the
actionattribute of the form to the URL to show the profile page. You will need to create a URL that returns to the profile page, but you have created this URL elsewhere in your code. Think about where you did this previously!
For example:

-
-
Create a new URL pattern to trigger the delete
Postprocess. Use this URL pattern:post/<int:pk>/delete, and associate this URL with yourDeletePostViewclass.A concrete example of such a URL would be:
http://localhost:8000/mini_insta/post/11/deletewhich means to delete the
Postwith primary key of 11. -
Within your
show_post.htmltemplate, you will need to add a link (titleddelete). Within this link, you will need to create the correct URL pattern to trigger the URL defined in the previous step.{% url 'delete_post' post.pk %}where
postis the name ofPostobject within the context of the template that displays thePost. -
Test that the new delete link works – it should show up in the
show_postpage. Now try to click the link. Check that it generates the correct URL (for example:http://localhost:8000/mini_insta/post/11/delete).If it does not generate a correct URL for the delete operation, go back and fix that now.
After deleting a
Post, the user should be redirected to theProfilepage for the person whosePostwas deleted. -
Repeat steps 1-5 for the update operation. Create a class
UpdatePostViewwhich inherits from the genericUpdateViewclass, create a template calledupdate_post_form.htmlwith confirmation/cancel options, and a URL pattern:post/<int:pk>/update, and associate this URL with yourUpdatePostViewclass.The requirement for the update
Postfeature is to be able to update the caption text of thePost. After updating aPost, the user should be redirected to theshow_postpage for thatPost. -
Test everything!!
Important: Add files to git!
-
You’ve just reached a good stopping point.
-
This is an excellent time to add your files to git, commit your changes, and push your changes to GitHub before anything gets F@&#ed up.
Optional Challenge
Posts could have 0 to many Photos associated with them.
For an additional challenge, make it possible to add/remove individual
Photos from a Post.
Hints:
-
First, work on deleting a
Photo(one at a time). You will need a separate URL and a view to handle this operation. -
Next: try adding additional
Photos (one or several at a time). You will need a separate URL and a view to handle this operation.
Deployment to cs-webapps
- Deploy your web application to the
cs-webapps.bu.edu.
Follow the deployment instructions here.
-
Test your web application on
cs-webapps.bu.eduto ensure that everything works correctly. -
Resolve any deployment issues.
Submitting Your Work
10 points; will be assigned by the autograder, verifying that you have submitted the correct files/URL, and testing that you website exists at the specified URL. 90 points; will be testing your application and code review
Log in to GradeScope to submit your work.
Be sure to name your files correctly!
-
Create a text file within your main django directory called
mini_insta_url.txt, containing the URL to your web page, and nothing else.For example:
https://cs-webapps.bu.edu/azs/cs412/mini_insta/.This file will be used by the autograder to locate your web page, so you must get the URL exactly correct, and you must not include any other text or code in the file.
-
Add the teaching staff as collaborators to your GitHub repository with
bu-cs412. Read-only access is fine.Create a text file called
github_url.txtin the root of your project (e.g.,djangodirectory). Paste your GitHub URL in the file.Add these files to your git repository using
`git add -A`.
Commit this to your git repository, using
`git commit -m "Added mini_insta_url.txt"`
Push it to GitHub, using
`git push origin main`
-
Log in to GradeScope to submit your work.
In the Gradescope upload page, upload these two files:
-
mini_insta_url.txt -
github_url.txt
-
Notes:
-
Upload these files to Gradescope before the deadline.
-
When you upload, the autograder script will process your file(s).
-
You may resubmit as many times as you like before the deadline, and only the grade from the last submission will be counted.