1

I'm trying to get the id from an object that is trapped in a self-referential relationship. I believe my definition of the relationship may be limiting its function, or perhaps I'm projecting. I've tried every related SO solution I could find to no avail. Mainly, the form.parent_id.data.parent_id pattern I've seen on several solutions throws AttributeError: 'NoneType' object has no attribute 'parent_id'. I'm aware that sqlalchemy.exc.InterfaceError: <unprintable InterfaceError object> results from form.parent_id.data because QuerySelectField returns an object, not an id. I get the same error when setting get_pk=lambda x: x.parent_id in the form object.

routes.py

def edit_user(id):
    form = UserForm()
    user = User.query.get_or_404(id)
    selected_date_ids = []
    upcoming_dates = TestDate.query.order_by(TestDate.date).filter(TestDate.status != 'past')
    tests = sorted(set(TestDate.test for TestDate in TestDate.query.all()), reverse=True)
    if form.validate_on_submit():
        if request.method == "POST":
            ...
            user.tutor_id=form.tutor_id.data
            user.parent_id=form.parent_id.data

models.py

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True)
    ...
    tutor_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    students = db.relationship('User', backref=db.backref('tutor'), 
        foreign_keys=[tutor_id], remote_side=[id])
    parent_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    children = db.relationship('User', backref=db.backref('parent'), 
        foreign_keys=[parent_id], remote_side=[id])

forms.py

def get_tutors():
    return User.query.filter_by(role='tutor')

def get_parents():
    return User.query.filter_by(role='parent')

def full_name(User):
    return User.first_name + " " + User.last_name


class UserForm(FlaskForm):
    ...
    tutor_id = QuerySelectField('Tutor', default=1, query_factory=get_tutors, get_label=full_name, allow_blank=True)
    parent_id = QuerySelectField('Parent', query_factory=get_parents, get_label=full_name, allow_blank=True)
    is_admin = BooleanField('Admin')
    submit = SubmitField('Save')
dannypernik
  • 172
  • 2
  • 11

1 Answers1

0

I ended up switching from QuerySelectField to SelectField using this answer to populate dynamic values, and everything became much simpler. Still not sure about my db.relationships, but they seem to be getting the job done.

dannypernik
  • 172
  • 2
  • 11