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:
-
Implement web application CRUD (create, read, update and delete) operations.
-
Use the Django object relational manager (ORM) to execute queries against model data.
-
Add additional URL routing and page views to an existing application, understanding that there are multiple ways to navigate/display the model data.
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:
- Viewing, creating, and updating user profiles
- Viewing and creating status messages
- Uploading images
- Viewing and adding friends
- Developing a news feed to show status messages from multiple friends
- Incorporating user accounts, authentication, and registration
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 Friend
s on the profile page.
-
Create a new data model called
Friend
, which encapsulates the idea of an edge connecting two nodes within the social network (e.g., twoProfile
s that are friends with each other).A
Friend
relation will associate 2Profile
s, and also store a timestamp of the friendship creation (i.e., “anniversary”) date. Use the attribute namesprofile1
,profile2
, andtimestamp
.Note: Two
ForeignKey
s to the same model-
Django will complain about a
reverse_accessor
, because you have 2ForeignKey
s with the same model.To fix this, add the parameter
related_name="profile1"
andrelated_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 bothProfile
s 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
. -
-
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). -
Write a
get_friends
accessor method on theProfile
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 matchingFriend
records.-
Note that within the
Friend
instance, theProfile
referred to byself
could be either theprofile1
orprofile2
of theFriend
instance. Your method will need to account for both possibilities when creating the result. -
This method must return a
list
of the friends’Profile
s (not aQuerySet
orlist
ofFriend
s). Pay attention to the data types.
-
-
Modify the
show_profile.html
template to include displaying the friends for thatProfile
, with links to the friend’s own profile pages.For example:
-
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 Friend
s
-
Create a method on the
Profile
class calledadd_friend(self, other)
. This method takes a parameterother
, which refers to anotherProfile
instance, and the effect of the method should be add aFriend
relation for the twoProfile
s:self
andother
.It is important to not add extra/duplicate
Friend
s, so before before creating a newFriend
instance, check to see whether one exists for this pair ofProfile
s. Note, it could be eitherFriend(profile1=self, profile2=other)
orFriend(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 byself
is not the same as theProfiel
referred to byother
.If no existing
Friend
relationship exists, create a newFriend
instance and save it to the database. -
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
addsp2
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 thatp1
isp2
s friend and vice-versa. -
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 theProfile
doing theadd_friend
) andother_pk
corresponding to theProfile
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 superclassdjango.views.generic.View
. This class is closer to the “function-based views” that we used in assignments 3 and 4. Implement/override thedispatch
method, in which we can read the URL parameters (fromself.kwargs
), use the object manager to find the requisiteProfile
objects, and then call theProfile
‘sadd_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.
-
Write a method
get_friend_suggestions(self)
on theProfile
object, which will return alist
(orQuerySet
) of possible friends for aProfile
. There are many possible implementations, and you may pick any that you please so long as it follows these constraints:-
The friend suggestions includes
Profile
s in the list are not currently friends with theProfile
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.
-
-
Create a new template called
friend_suggestions.html
to display the friend suggestions for a singleProfile
, along with links to add friends.Create a new view class
ShowFriendSuggestionsView
which inherits fromDetailView
, and associate it with thefriend_suggestions.html
template.Create a new URL pattern:
'profile/<int:pk>/friend_suggestions'
and associate it with theShowFriendSuggestionsView
.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:
-
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
-
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 theProfile
object, which will return alist
(orQuerySet
) of allStatusMessage
s 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
StatusMessage
s.You might experiment with using the object managers (
StatusMessage.objects
) at the Django python console to discover which methods to use to generate thelist
/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.
-
Create a new template called
news_feed.html
to display the news feed for a singleProfile
. The news feed should show eachStatusMessage
, along with the profile image and name of the person who wrote it.Create a new view class
ShowNewsFeedView
which inherits fromDetailView
, and associate it with thenews_feed.html
template.Create a new URL pattern:
'profile/<int:pk>/news_feed'
and associate it with theShowNewsFeedView
.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:
-
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
- Deploy your web application to the
cs-webapps.bu.edu
.
Follow the [deployment instructions here][deployment].
-
Test your web application on
cs-webapps.bu.edu
to 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
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.
-
Add teaching staff as collaborators to your GitHub repository (
wderocco8
,Aanuszkiewicz
, andazs-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`
-
Log in to GradeScope to submit your work.
In the Gradescope upload page, upload these two files:
-
a8_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.