Assignment 4: Using Multiple Models; Creating Model Data
due by 9:00 p.m. EDT on Friday 10/3/2025
Learning Objectives
After completing this assignment, students will be able to:
-
Use generic
ListView
andDetailView
to display records from the database. -
Implement a 1-to-many relationship among data models.
-
Create custom templates to display model data, including 1-to-many relationship data.
-
Handle HTTP GET and POST requests for HTML form display and submission.
-
Use HTML forms to create model data records.
-
Write HTML templates to display HTML forms.
-
Create appropriate URL patterns to perform CRUD actions on specific object instances, and to provide object information to views.
-
Inherit from the Django generic
CreateView
, to process form data submissions. -
Customize the generic
CreateView
class to set foreign-keys when creating 1-to-many relationships.
Pre-requisites: Assignments 3
Assignment 4 builds upon the case study you began in Assignment 3.
You must have completed Assignment 3 before you begin Assignment 4.
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 second part of the case study.
Here is a sample implementation: MiniInsta part 2.
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 comforms 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 3.
Task 1: Modeling and Displaying Posts and Photos
-
Create a new model called
Post
, which will model the data attributes of an Instagram post. ThisPost
model will need to include the following data attributes:profile
(the foreign key to indicate the relationship to theProfile
of the creator of this post)timestamp
(the time at which this post was created/saved)caption
(the optional text associated with this post)
Here is a diagram of the models and their relationships:
The foreign key is how we model a relationship between different kinds of objects. In this case, we are defining the relationship such that every
Post
object is related to a singleProfile
object.Be sure to create a
__str__
method on this class to return a string representation of this object. -
Create a new model called
Photo
, which will model the data attributes of an image associated with aPost
. ThisPhoto
model will need to include the following data attributes:post
(the foreign key to indicate the relationship to thePost
to which thisPhoto
is associated.image_url
(a valid URL to an image stored on the public world-wide web)timestamp
(the time at which thisPhoto
was created/saved)
Here is a diagram of the models and their relationships:
The foreign key is how we model a relationship between different kinds of objects. In this case, we are defining the relationship such that every
Photo
object is related to a singlePost
object.Be sure to create a
__str__
method on this class to return a string representation of this object. -
Use the Django admin to create some sample data:
-
Create 3 sample
Post
s, for at least 2 differentProfiles
, with any content/captions of your choosing. -
Create at least 3 sample
Photo
s, associated with 2 differentPosts
. That is: at least onePost
should have more than onePhoto
.
-
-
Create accessor methods to retrieve related model data.
-
In the
Profile
class, define an accessor methodget_all_posts
to find and return allPost
s for a givenProfile
. The return type will be aQuerySet
containingPost
s. -
In the
Post
class, define an accessor methodget_all_photos
to find and return allPhoto
s for a givenPost
.
The return type will be aQuerySet
containingPhoto
s.
Hint: Use the object manager to filter
Post
objects by theirprofile
(foreign key), and order them by timestamp. -
-
Edit your
show_profile.html
template to add the display ofPost
s.For each
Post
, you should display the firstPhoto
associated with thatPost
. If there is noPhoto
associated with thePost
, display an alternate image indicating that there is “no image.” -
Create a view, template, and URL pattern to display a single
Post
.The view should be called
PostDetailView
, and the template should be calledshow_post.html
. The URL pattern should be in the form:'http://127.0.0.1:8000/mini_insta/post/<int:pk>'
, where<int:pk>
will be replaced by the primary key for thePost
being shown.On the page to show the post, display the post caption and timestamp, as well as all
Photo
s associated with thisPost
. You may choose how to arrange these on the page, for example using atable
ordiv
elements within a grid layout.Finally, on the
show_profile_page.html
template, add a link from eachPost
to retrieve it’s detail page. -
Test your page! Try this URL pattern:
'http://127.0.0.1:8000/mini_insta/
. Follow the link to any profile that has posts, and view that 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: Creating a new Post
In this Task, you will create a form to collect inputs to create a new Post
.
For example:
-
Within the
mini_insta
application folder, create the new fileforms.py
. In this file, add the following import statements at the top:from django import forms from .models import *
Create a class
CreatePostForm
which inherits fromforms.ModelForm
. Be sure to specify the inner-classMeta
, which relates this form to thePost
model.Also, specify the list of
fields
that this form should set (i.e., the data attributes of thePost
class).
Note: How Django displays HTML Form Fields
-
By default, Django will choose which type of HTML form fields to use, based on the data types of the fields in your model.
For example, when your form has a
model.TextField
, Django will use a<textarea>
(multi-line text input box). Often, this is OK. For this assignment it is fine, and you can get full functionality and points using the defaults. -
If you want to customize how the HTML form displays, you can explicitly tell Django which type of form field to use.
-
See the details in the Django Forms Documentation page.
-
Create the template file
mini_insta/create_post_form.html
, to render the HTML form. Your form must:- define the
<form>
tags, and set the form’s method toPOST
- include the django-created
csrf_token
as a form field (as you did in the example video) - provide a submit button and a cancel button
- do not include the
Profile
as one of the fields in this form. It looks awkward on the screen, and anyway theprofile
will be specified by the URL which will process the creation of thePost
.
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
CreateView
class, which will create a new record for this model and store it in the database.Important design notes:
Recall that
Photo
s are stored separately fromPost
s, which is required to enable the “one post can have many photos” relationship. As a consequence, we will need a way to include the important information for aPhoto
(i.e., itsimage_url
attribute), which is not part of thePost
object. To do this, add an explicit HTML form field for theimage_url
to the form. We will return to this in a future assignment to enable (a) uploading images instead of specifying the URL and (b) handling multiple images instead of just one. For now, we will use animage_url
and assume creating one singlePhoto
perPost
. - define the
-
Edit the file
views.py
to add a view calledCreatePostView
to handle the form submission. We will again use the genericCreateView
as a base class, but it will require some additional work that was not required in the pre-class example.Specifically, the
Post
requires a foreign key to relate it to aProfile
object, and aPhoto
requires a foreign key to relate it to aPost
object. We will return to these below. For now, set up thetemplate_name
andform_class
.Create a URL mapping to route requests from the URL pattern
'profile/<int:pk>/create_post'
, associate it with theCreatePostView
, and name this URLcreate_post
.Note: there are several ways to go about solving the issue of attaching the foreign key to the Post object. These instructions walk you through one approach using the generic CreateView.
First Complication: Implementing
get_context_data
methodTry this URL:
http://127.0.0.1:8000/mini_insta/profile/1/create_post
. (Use another primary key if you have no object numbered 1).You should be able to display the
create_post_form.html
template. When you try submitting it, it gets complicated.When you try to create the submission URL (the form
action
), you will need to provide the parameterprofile.pk
(i.e., identifying theProfile
to which thisPost
corresponds) as part of that URL.To have access to this as a context variable, you will need to implement the special method
get_context_data
on theCreatePostView
class.There is a special attribute called
self.kwargs
, which is accessible within the methods on theCreateView
and its subclasses.self.kwargs
is a dictionary containing any URL parameters, and the valueself.kwargs['pk']
is the primary key of theProfile
corresponding to the URL pattern.In the
get_context_data
method: begin with the context dictionary from the superclass. Find theProfile
object (corresponding toself.pk
), add theProfile
object (call the context variableprofile
, for consistency with how things worked on other pages). Now you will have access to the context variableprofile
within thecreate_post_form.html
template. Use theprofile.pk
to help generate the URL to which the form should be submitted, e.g., the form action'http://127.0.0.1:8000/mini_insta/profile/1/create_post'
.Second complication: Implementing the
form_valid
methodTest out this URL again. You should now be able to display/submit the
create_post_form.html
.create_post_form.html
template. When you try to submit the form, you should see an error thatNOT NULL constraint failed: mini_insta_post.profile_id
. Basically, you cannot create/save aPost
without setting theprofile
attribute.To solve this problem, you will need to write some custom code within the
CreatePostView
class, to attach theProfile
to thePost
before submission. Implement the methodform_valid
on theCreatePostView
class to: (a) look up theProfile
object by itspk
. You can find thispk
inself.kwargs['pk']
. (b) attach this object to theprofile
attribute of the post. Now you will be able to save thePost
successfully.Also in the
form_valid
method: use the data from therequest.POST
object to create a newPhoto
for thispost
, and set thepost
attribute as a foreign key (on thePhoto
).After successfully creating a
Post
, Django should automagically redirect you to the page to show that post (i.e., theDetailView
associated with classPost
. )Finally: be sure to include a “cancel” or “back” button to be able to navigate from the “create post” page back to the “profile” page.
-
Edit the
base.html
template, and add a link to the bottom-of-screen navigation, to bring up thecreate_post
page (in its own page view).Note: to be able to create a
Post
, we need to know theprofile
for whom thePost
should be created. This is only possible if theprofile
is part of the context data for the page. Use decision-logic to show/not show this navigation button as appropriate (i.e., only when you have aprofile
in the context data.) -
Testing!! Start at your main
/mini_insta
URL, and pick any existing profile. You should see the profile page, with a form to post a post. Write something witty in the form, and use the submit button to submit it to the server.
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.
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.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
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.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`
-
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.