CS412
Spring 2025

Assignment 8: Using the Object Relational Manager

due by 9:00 p.m. EDT on Friday, March 21, 2025

Learning Objectives

After completing this assignment, students will be able to:


Pre-requisites: Assignments 7

Assignment 8 builds upon the case study you began in Assignment 5.

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

Case Study: Mini Facebook

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 Facebook social networking application:

This assignment is the fifth part of the case study, and you will continue the work from the previous assignment to build a database-enabled web application.

Sample Implementation

Here is a sample implementation (tasks 1 and 2): MiniFacebook Application.

Here is a sample implementation (task 3): MiniFacebook Application.

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 display, 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 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_fb Application

Continue to do this work within your existing Django project, within the mini_fb. application that you worked on in Assignment 7.

Task 1: Defining the Friend model and displaying Friends on the profile page.

  1. Create a new data model called Friend, which encapsulates the idea of an edge connecting two nodes within the social network (e.g., two Profiles that are friends with each other).

    A Friend relation will associate 2 Profiles, and also store a timestamp of the friendship creation (i.e., “anniversary”) date. Use the attribute names profile1, profile2, and timestamp.

    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 parameter related_name="profile1" and related_name="profile2", respectively.

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

  2. Use the admin tool to add some friend relationships; even a handful is enough to get started. Also, make sure you leave at least 1 Profile without friends (for testing purposes).

  3. Write a get_friends accessor method on the Profile class, which will return a list of friend’s profiles. Providing this method will make it possible to call the method (among other places) in the template, i.e., to display a profile’s friends.

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

    • Note that within the Friend instance, the Profile referred to by self could be either the profile1 or profile2 of the Friend instance. Your method will need to account for both possibilities when creating the result.

    • This method must return a list of the friends’ Profiles (not a QuerySet or list of Friends). Pay attention to the data types.

  4. Modify the show_profile.html template to include displaying the friends for that Profile, with links to the friend’s own profile pages.

    For example:

  5. Test everything! Start at this URL pattern: 'http://127.0.0.1:8000/mini_fb/.

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: Adding Friends

  1. Create a method on the Profile class called add_friend(self, other). This method takes a parameter other, which refers to another Profile instance, and the effect of the method should be add a Friend relation for the two Profiles: self and other.

    It is important to not add extra/duplicate Friends, so before before creating a new Friend instance, check to see whether one exists for this pair of Profiles. Note, it could be either Friend(profile1=self, profile2=other) or Friend(profile1=other, profile2=self); either way, we do not want to create an extra/duplicate.

    Additionally, we do not want to allow “self-friending”. Make sure that the Profile referred to by self is not the same as the Profiel referred to by other.

    If no existing Friend relationship exists, create a new Friend instance and save it to the database.

  2. Test your Profile.add_friend method at the django python shell. For example:

    >>> # Obtain 2 `Profile` objects, 
    >>> p1 = Profile.objects.get(pk=1)
    >>> p2 = Profile.objects.get(pk=2)
    >>> p1.add_friend(p2)
    >>> # obtain and print out the list of friends; check for success.
    >>> p1.get_friends()
    

    Note: when p1 adds p2 as a friend, the relationship is automatically created, reciprocally. That is, there is no need to “accept” or approve friends, and the relationship is created such that p1 is p2s friend and vice-versa.

  3. There are many ways to trigger the Profile.add_friend operation, and this is a simple approach. (You are welcome to try a more complicated strategy too!)

    The general idea is to have a URL that will cause the “add friend” event to occur, for example: http://127.0.0.1:8000//mini_fb/profile/1/add_friend/3 would mean that we want to add a friend (identified by the primary key of 3) to the profile identified by the primary key of 1.

    Create a new URL pattern: 'profile/<int:pk>/add_friend/<int:other_pk>'. Notice that there are 2 URL parameters here, pk (corresponding to the Profile doing the add_friend) and other_pk corresponding to the Profile to add as the friend.

    In the previous assignment, we inherited from the generic CreateView class to create model data via a form. In this case, we do not need to handle a form submission, but in this case, we can obtain all of the information we need from URL parameters.

    Create a view class called AddFriendView, which inherits from the generic superclass django.views.generic.View. This class is closer to the “function-based views” that we used in assignments 3 and 4. Implement/override the dispatch method, in which we can read the URL parameters (from self.kwargs), use the object manager to find the requisite Profile objects, and then call the Profile‘s add_friend method (from step 2, above). Finally, we can redirect the user back to the profile page.

    C’est tout! Test it out by typing in a URL to add a friend, and see that it works.

  4. Write a method get_friend_suggestions(self) on the Profile object, which will return a list (or QuerySet) of possible friends for a Profile. There are many possible implementations, and you may pick any that you please so long as it follows these constraints:

    • The friend suggestions includes Profiles in the list are not currently friends with the Profile instance on which the method is called.

    • The friend suggestions must not contain the Profile instance on which the method is called.

    You might experiment with using the object managers (Profile.objects, Friend.objects) at the Django python console to discover which methods to use to generate the list.

    You may also use python tools (e.g., list comprehension, for loop, metGo hod calls) to build/refine the list of friend suggestions.

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

  5. Create a new template called friend_suggestions.html to display the friend suggestions for a single Profile, along with links to add friends.

    Create a new view class ShowFriendSuggestionsView which inherits from DetailView, and associate it with the friend_suggestions.html template.

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

    Add a link or button from the profile page to bring up the friend suggestions, and a link from the friend suggestions back to the profile page.

    For example:

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

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: Creating a Newsfeed

  1. The Facebook “news feed” is a page view (scrollable) that includes status messages and images (and lots of ads!), customized to each user (profile).

    Briefly, the news feed shows status message(s) for each of the friends of a given user, with the most recent at the top.

    Write a method get_news_feed(self) on the Profile object, which will return a list (or QuerySet) of all StatusMessages for the profile on which the method was called, as well as all of the friends of that profile.

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

    You might experiment with using the object managers (StatusMessage.objects) at the Django python console to discover which methods to use to generate the list/QuerySet.

    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.

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

    Create a new view class ShowNewsFeedView which inherits from DetailView, and associate it with the news_feed.html template.

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

    Add a link or button from the profile page to bring up the news feed, and a link from the news feed back to the profile page.

    For example:

  3. Test everything! Start at this URL pattern: 'http://127.0.0.1:8000/mini_fb/.

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.


Deployment to cs-webapps

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

Follow the [deployment instructions here][deployment].

  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 a8_url.txt, containing the URL to your web page, and nothing else.

    For example: https://cs-webapps.bu.edu/azs/cs412/mini_fb/.

    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 teaching staff as collaborators to your GitHub repository (wderocco8, Aanuszkiewicz, and azs-bu). 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 a8_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:

    • a8_url.txt

    • github_url.txt

Notes: