CS412
Fall 2025

Assignment 6: Using the Object Relational Manager

due by 9:00 p.m. EDT on Friday 10/17/2025

Learning Objectives

After completing this assignment, students will be able to:


Pre-requisites: Assignments 5

Assignment 6 builds upon the case study you began in Assignment 3.

You must have completed Assignment 5 before you attempt Assignment 6.

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 fourth part of the case study.

Here is a sample implementation: MiniInsta part 4.

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

Task 1: Additional data models: Follow, Comment and Like

Read before Create

  • In this section, we will add 3 new data models for Follows, Comments, and Likes.

  • In this assignment, we will use the Django Admin tool to create data for these models, but we will not implement features to create these through our web application. We will return to creating these data objects in Assignment 7.

  1. Define a new data model called Follow, which encapsulates the idea of an edge connecting two nodes within the social network (e.g., when one Profile follows another Profile).

    A Follow relation will associate 2 Profiles. Use these data attribute names:

    • profile (a foreign key) indicating which profile is being followed (i.e., the “publisher”).

    • follower_profile (a foreign key) indicating which profile is doing the following (i.e., the “subscriber”)

    • timestamp (a date time field) indicating the time at which the follower began following the other profile.

    Note: Two ForeignKeys to the same model

    • Django will complain about a reverse_accessor, because you have 2 ForeignKeys with the same model.

      To fix this, add the parameters related_name="profile" and related_name="follower_profile" to each ForeignKey, respectively.

    Write a __str__ method so that you can view this Follow relationship as a string representation. It would be helpful to include the display names or usernames of both Profiles in this string representation. For example for a Follow relationship between Angela Merkel and Taylor Swift, we could create this string representation: Angela Merkel follows Taylor Swift.

    Use the admin tool to add several Follow relationships. You don’t need a lot, but perhaps N Follows for N Profiles to get started. Leave at least 2 Profiles without followers (for testing purposes), and to be able test adding followers later (in next week’s assignment).

  2. Write the following accessor methods on the Profile class:

    • A get_followers method, which will return a list of those Profiles who are followers this profile (i.e., subscribers who will see Posts from this profile). Providing this method will make it possible to call the method (among other places) in the template, i.e., to display a profile’s followers.

      This method will need to use the Django ORM (i.e., Follower.objects) and its methods to filter/retrieve matching Follower records.

      • This method must return a list of the followers’ Profiles (not a QuerySet or list of Follows). Pay attention to the data types.
    • A get_num_followers method, which will return the count of followers.

    • A get_following method on the Profile class, which will return a list of those Profiles followed by this profile (i.e., publishers to whose Posts this Profile is subscribed).

      Providing this method will make it possible to call the method (among other places) in the template, i.e., to display the profiles a user is following (subscribed to).

      This method will need to use the Django ORM (i.e., Follower.objects) and its methods to filter/retrieve matching Follower records.

      • This method must return a list of the Profiles being followed (not a QuerySet or list of Follows). Pay attention to the data types.
    • A get_num_following method, which will return the count of how many profiles are being followed.

  3. Write the following views, templates, and URLs:

    • Create the ShowFollowersDetailView and ShowFollowingDetailView view classes, each of which will inherit from the generic DetailView. These classes are DetailViews for a Profile, and will provide the context variable profile to their respective templates.

    • Create the templates show_followers.html and show_following.html, which will use the context object profile to call the accessor methods on the Profile model, to retrieve the required lists of Profiles to display.

    • Create the URL patterns 'profile/<int:pk>/followers' and 'profile/<int:pk>/following' to bring up the ShowFollowersDetailView and ShowFollowingDetailView, respectively.

    Modify the show_profile.html template to include displaying the count of Followers and Following, with links that bring up the views for each.

    For example:

  4. Define a new data model called Comment, which encapsulates the idea of one Profile providing a response or commentary on a Post.

    A Comment will associate the following data attributes:

    • post (a foreign key) indicating the Post to which this Comment is related.

    • profile (a foreign key) indicating which profile is doing the commenting.

    • timestamp (a date time field) indicating the time at which this Comment was created.

    • text (a text field) which is the substance of the Comment

    Write a __str__ method so that you can view this Comment as a string representation.

    Use the admin tool to add several Comments on at least 2 different Posts. You don’t need a lot, just enough for testing purposes.

    Create an accessor method on the Post class called get_all_comments to retrive all comments on a Post. This method will need to use the Django ORM (i.e., Comment.objects) and its methods to filter/retrieve matching Comments for a Post.

    Update the show_post.html page to add display of Comments below the Post caption.

  5. Define a new data model called Like, which encapsulates the idea of one Profile providing approval of a Post.

    A Like will associate the following data attributes:

    • post (a foreign key) indicating the Post to which this Like is related.

    • profile (a foreign key) indicating which profileis doing the liking.

    • timestamp (a date time field) indicating the time at which this Like was created.

    Write a __str__ method so that you can view this Like as a string representation.

    Use the admin tool to add several Likess on at least 2 different Posts. You don’t need a lot, just enough for testing purposes.

    Create an accessor method on the Post class called get_likes to retrive all likes on a Post. This method will need to use the Django ORM (i.e., Like.objects) and its methods to filter/retrieve matching Likes for a Post.

    Update the show_post.html page to add display of Like count above the Post caption. For example:

  6. Test everything! Start at this URL pattern: 'http://127.0.0.1:8000/mini_insta/.

Important: Add files to git!

  • You’ve just modified your database structure, and added some data records.

  • 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: Creating a Post Feed

  1. The Instagram “post feed” is a scrollable view that includes Posts, Photos, Comments, and Likes (and lots of ads!), customized to each user (Profile).

    Briefly, the post feed shows posts for each of the profiles being followed by a given user, with the most recent at the top.

    Write an accessor method get_post_feed on the Profile object, which will return a list (or QuerySet) of Posts, specifically for the profiles being followed by the profiles on which the method was called.

    Hint: it will be easiest to develop this by using the ORM to filter Posts.

    You might experiment with using the object managers (e.g., Follow.objects, Post.objects) at the Django python console to discover which methods to use to generate the list/QuerySet that you want.

    You may also use python tools (e.g., list comprehension, for loop, method calls) to build/refine results.

    Hint: begin with a simple if not perfect version, and then you can refine it later.

    Test this method at the console to prove that it returns some data, of the correct type, before you try to build the view/template for it.

  2. Create a new template called show_feed.html to display the post feed for a single Profile. The post feed should show each Post, along with the profile image and name of the person who wrote it.

    Create a new view class PostFeedListView which inherits from ListView, and associate it with the show_feed.html template. The show_feed.html template should display all of the Posts in the feed, and each Post should include the first Photo of the Post, the caption, Likes, and Comments.

    Create a new URL pattern: 'profile/<int:pk>/feed' and associate it with the PostFeedListView.

  3. Navigation

    • Change the “home” navigation link (e.g., the leftmost navigation icon in the example) from the bottom of the page so that it links to the post feed.

    • If you do not already have one, add a navigation link to the profile page (e.g., the rightmost navigation icon in the example).

    • Add a link from the post feed back to the profile page.

    For example:

  4. Test everything! Start at this URL pattern: 'http://127.0.0.1:8000/mini_insta/.

Important: Add files to git!

  • You’ve just reached a good stopping point, and added some data records.

  • 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: Search and Results

  1. Add a search feature to search user Profiles and Posts based on a text input. Implement a view class called SearchView which inherits from the generic ListView. Use 2 templates called search.html and search_results.html, and a URL pattern 'profile/<int:pk>/search' (i.e., the search is being done on behalf of the user with the profile specified by pk).

    In configuring the ListView, set the template_name to be 'search_results.html'. This will be the default way to display results of this search.

    Here are some implementation notes:

    • The search.html page should present an HTML form with a text area search box as well as a button to submit the search. Use an HTML form (not a model form, since this is not creating or updating model data). This form should collect a query to search against the data models.

      For example:

    • The search_results.html page should present two different listings of results: one for Profiles that match the query, and one for Posts that match the query. Consider how you would like this to appear, and use a separate loop for each.

      For example:

  2. In the SearchView class, you will need to implement (override the super-class version) several methods:

    • dispatch(self, request, *args, **kwargs): this method is called first to dispatch (handle) any request. Override this method to add an if statement, testing for the name query in self.request.GET.

      If the query is absent, return the search.html template, i.e., to provide the form to collect the query from the user. Be sure to include the profile context variable, since the template will need this variable to create the URLs.

      Otherwise, return the superclass version of dispatch, i.e., super().dispatch(request, *args, **kwargs), which will continue the work of the generic ListView.

    • get_queryset(self): the generic ListView uses this method to obtain the QuerySet of instance data (that matches the model attribute of a ListView. We did not set that attribute, because we do not want all objects to be returned, but rather we want to control which objects to return.

      In this method, write a query against the object manager (i.e., Post.objects) to obtain Posts that contain the query. Return the QuerySet of matching Posts.

    • get_context_data(self, **kwargs): this method returns the dictionary of context data that can be accessed from the template. Add the following to the context data:

      • the profile object (for whom we are doing this search)

      • the query (if present)

      • the posts that match the query, obtained from get_query_set. A post matches if the query is contained in its caption text.

      • the profiles that match the query, obtained from using the object manager (Profile.objects). A profile matches if they query text is found in its username, display name, or bio text.

  3. Edit the base.html template, and add a link to the bottom-of-screen navigation, to bring up the search page (in its own page view).

  4. Test everything! Start at this URL pattern: 'http://127.0.0.1:8000/mini_insta/.

Important: Add files to git!

  • You’ve just modified your database structure, and added some data records.

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


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: