Intro to Backend Development
  • Introduction
  • SP25 Syllabus
  • Apply to Take the Course
  • Getting Started
  • Weekly Feedback Form
  • Ed Discussion
  • Intro to Backend SP25 Google Calendar
  • Cheat Sheets
    • Assignment Requirements
    • Assignment FAQs
    • Error FAQs 😢
    • Concept FAQs
    • Postman
    • Command Line
    • Virtual Environment
  • Chapters
    • 1. Routes
      • Pre-Class TODO's
      • Lecture
      • Assignment Handout
      • API Specification
    • 2. Databases
      • Pre-Class TODO's
      • Lecture
      • Demo
      • Assignment Handout
      • API Specification
    • 3. Relational Databases
      • Pre-Class TODO's
      • Lecture
      • Demo
      • Assignment Handout
      • API Specification
    • 4. Abstractions
      • Pre-Class TODO's
      • Lecture
      • Demo
      • Assignment Handout
      • API Specification
    • 5. Containerization
      • Pre-Class TODO's
      • Docker Installation
      • Lecture
      • Demo
      • Assignment Handout
    • 6. Deployment
      • Lecture
      • Demo
      • Assignment Handout
    • 7. Images
      • Demo
      • Assignment Handout
    • 8. Authentication
      • Lecture
      • Demo
      • Assignment Handout
    • (Work in Progress) OAuth
      • Pre-Class TODO's
      • Lecture
      • Demo
      • OAuth 2.0 vs OpenID
      • Flask / OpenID example
  • Additional Topics
    • Git and Github
    • HackOurCampus
  • Other AppDev Courses
    • Intro to iOS Development
    • Intro to Android Development
    • Intro to Digital Product Design
  • Deprecated
    • Previous Semester Syllabi
      • FA22 Syllabus
      • SP22 Syllabus
      • FA21 Syllabus
      • SP21 Syllabus
      • FA20 Syllabus
      • SP20 Syllabus
    • Deployment Pre-Class TODO's
    • PA6 Assignment Handout
    • Deployment Demo
    • Final Project (Spring 2019)
      • Final Project Award Winners
Powered by GitBook
On this page
  • backref vs. back_populates vs. none of these
  • using neither backref nor back_populates
  • using back_populates
  • using backref

Was this helpful?

  1. Cheat Sheets

Concept FAQs

Contributors: Alanna Zhou

backref vs. back_populates vs. none of these

This is introduced when we start using SQLAlchemy, and can be a bit confusing to understand why we need backref or back_populates at all and what the difference between these two are. To help you understand, I am going to break this up into three scenarios:

  1. using neither backref nor back_populates

  2. using back_populates

  3. using backref

Just as a note, we have been using back_populates in our demo and assignment solutions, but that does not mean you can't use backref!

using neither backref nor back_populates

Let's give an example of two classes that have a relationship with each other, Parent and Child. Let's assume that one parent can have multiple children, and each child can only have one parent.

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent")

The consequence of this is that if you create child object A and assign it a parent object B, it does not mean that this parent object B will recognize child object A as its child:

>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print parent.children
[]

As expected, this is wacky! parent.children should return me the newly created child = Child()!

Let's fix this by using back_populates.

using back_populates

This is a SQLAlchemy keyword that you pass into the relationship() method that allows SQLAlchemy to recognize that there is a connection between the two entities that are related. To modify the previous example, we would do:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", back_populates="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))
    parent = relationship("Parent", back_populates="children")

The way that back_populates works is that you are directing each relationship from one end to the other: Child to parent (lowercase p in parent), and likewise Parent to children).

Now, if you assign some children to a parent, the children will be able to recognize the parent. And if you assign a parent to a child, the parent will be able to recognize the child. By recognize, I am referring to having SQLAlchemy understand that the object is from an existing class you defined.

The fruits of your labor can now be seen:

>>> parent = Parent()
>>> child = Child()
>>> child.parent = parent
>>> print parent.children
[Child(...)]

Solid! But what about backref?

using backref

This is simply another way of doing what back_populates does. There does not seem to be any execution advantage over the other (at least that Alanna knows of, please message her if you discover that that is not the case...). However, we recommend back_populates for a reason that is explained once you've read what exactly back_ref does.

When using backref, you don't need to declare the relationship on the second table defined:

class Parent(Base):
    __tablename__ = 'parent'
    id = Column(Integer, primary_key=True)
    children = relationship("Child", backref="parent")

class Child(Base):
    __tablename__ = 'child'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('parent.id'))

Notice how Child did not have to use relationship nor backref; all it had to do was keep track of the parent.id.

From seeing this, the difference between backref and back_populates is clear. Since you have to define the relationships in every class, we recommend using back_populates because it is nice and easy to see all the fields just be glancing at the model class, instead of having to look at other classes that define fields via backref.

PreviousError FAQs 😢NextPostman

Last updated 1 year ago

Was this helpful?

This example will still "work", but is not using nor taking advantage of SQLAlchemy's recommended relationship pattern. You can read more about its one-to-many relationship pattern .

here