CS412
Fall 2025

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:


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:

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.

  1. Revise the Photo model, to add an additional attribute called image_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_url attribute, as we need this for backwards-compatibility with existing Photo.

    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 the image_url attribute (if it exists), or else the URL to the image_file attribute, i.e., image_file.url.

    Revise the __str__ method to be consistent with the way the actual image is stored, i.e., image_url vs. image_file.

    Recall that after you change models, you will need to run the makemigrations script and the migrate command to update your database.

    Important:

    • Before you can go on to step 2 (displaying a Post with Photos stored by image_file), you will need to add at least 1 Photo (and maybe even 2) to your database using the admin tool to upload the file.

    • When you add an Photo to the database, you will need to also associate it with a Post object. Take note of which Post (for which Profile) this is, so that you can test that the Photo(s) display properly (see below).

  2. Displaying a post. You might need some revisions to the code that displays Posts and Photos, e.g. the show_post.html page. Revise to ensure that you are using the get_image_url method 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.

  1. In the CreatePostForm, revise to remove the image_url. While it is still part of the model for backwards-compatibility, it should no longer display for the user to enter a URL.

  2. In the create_post.html template, 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.

  3. In the CreatePostView class, you will need to modify the code in the form_valid method. Previously, you retrieved the image_url from the request.POST data and used that to create a Photo object. Comment this part out.

    In it’s place, you will need to read the data from self.request.FILES. Try reading files = 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 save Photo objects.

  4. 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 the show_post page.

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

  1. Create a new form class UpdateProfileForm which inherits from forms.ModelForm.

    Be sure to specify the inner-class Meta, which relates this form to the Profile model. Specify the list of fields that this form should set (i.e., all of the data attributes of the Profile class, except NOT the user’s username and join_date, which should not be changeable).

  2. Create a class-based view called UpdateProfileView, which inherits from the generic UpdateView class. Be sure to specify the form this create view should use, i.e., the UpdateProfileForm. Also, specify the name of the template to use to render this form, which must be called mini_insta/update_profile_form.html.

  3. 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 UpdateView class, which will update the Profile record 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:

  4. Edit the mini_insta project’s urls.py file. Create a URL mapping to route requests from the URL pattern 'profile/<int:pk>/update' to the UpdateProfileView view. Name this URL update_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 Profile record. Change something in the form, and use the submit button to submit it to the server.

    A complication: Implementing the get_absolute_url method

    Test out this URL again. Now when you submit the create_post_form.html template, 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_url on the Profile model class. Within that method, you will need to return the URL corresponding to the Profile that was updated. For example, if we just updated a Profile with 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 Profile link or button to the show_profile.html template, 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:

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.

  1. Create a class DeletePostView, which inherits from the generic DeleteView class. This base class will do most of what we want, but we will need to override some methods below. Set the model and template_name attributes.

    Override the get_context_data method, which will provide the context data needed to support the delete_post_form.html. Specifically, this context must provide the variables:

    • post, which is a reference to the Post to be deleted.

    • profile, which is the Profile of the user who made the Post.

    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 a Post is deleted, the user should be redirected to the profile page of the user whose Post was deleted.

  2. Create the template file delete_post_form.html. This template will display the Post that will be deleted, and contain 2 small forms:

    • One to confirm the delete, which will send a POST back to the same URL at which you are trying to do the delete.

    • One to cancel the delete, which will send a GET to URL to redisplay the profile page.

      Hint: you will need to set the action attribute 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:

  3. Create a new URL pattern to trigger the delete Post process. Use this URL pattern: post/<int:pk>/delete, and associate this URL with your DeletePostView class.

    A concrete example of such a URL would be:

    http://localhost:8000/mini_insta/post/11/delete

    which means to delete the Post with primary key of 11.

  4. Within your show_post.html template, you will need to add a link (titled delete). 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 post is the name of Post object within the context of the template that displays the Post.

  5. Test that the new delete link works – it should show up in the show_post page. 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 the Profile page for the person whose Post was deleted.

  6. Repeat steps 1-5 for the update operation. Create a class UpdatePostView which inherits from the generic UpdateView class, create a template called update_post_form.html with confirmation/cancel options, and a URL pattern: post/<int:pk>/update, and associate this URL with your UpdatePostView class.

    The requirement for the update Post feature is to be able to update the caption text of the Post. After updating a Post, the user should be redirected to the show_post page for that Post.

  7. 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:

Deployment to cs-webapps

  1. Deploy your web application to the cs-webapps.bu.edu.

Follow the deployment instructions here.

  1. Test your web application on cs-webapps.bu.edu to ensure that everything works correctly.

  2. 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!

  1. 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.

  2. 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.txt in the root of your project (e.g., django directory). 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`
    
  3. 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: