Sam Archer
Sam Archer

Reputation: 301

Flask-sqlalchemy AttributeError: 'function' object has no attribute 'query'

I've been using flask with flask-sqlalchemy successfully for a number of weeks, but all of a sudden my code is coming up with this error: AttributeError: 'function' object has no attribute 'query', relating to this line of code: project_choices = [(str(c.id) + ': ' + c.project_name) for c in Projects.query.all()]

Seems like the flask-sqalchemy Projects class is not being successfully created but I can't work out why.

Main routes file:

from flask import Flask, request, flash, url_for, redirect, render_template, session
from flask_sqlalchemy import SQLAlchemy
from app import db
from app import app
from app.forms import Basic_data_Form, Which_project#, Areas_form
from flask_bootstrap import Bootstrap
from app.models import Projects

@app.route('/Index', methods = ['GET', 'POST'])
def Index():

   if 'project_name' not in session:
      session['project_name'] = "0: No project selected"

   project_name = session['project_name'].split(':')[1]

   project_choices = [(str(c.id) + ': ' + c.project_name) for c in Projects.query.all()]  
   form2 = Which_project()
   form2.project_choice.choices = project_choices
   
   return render_template('Index.html', form2=form2, projects = Projects.query.filter_by(id=session['project_name'].split(':')[0]).all(), project_name=project_name)

init file:

from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap

app = Flask(__name__)
app.config.from_object(Config)

db = SQLAlchemy(app)

bootstrap = Bootstrap(app)

from app import routes

models file:

from app import db

class Projects(db.Model):
   id = db.Column(db.Integer, primary_key=True, autoincrement=True)
   project_name = db.Column(db.String(100))
   user_id = db.Column(db.String(100))
   address = db.Column(db.String(100))
   region = db.Column(db.String(100)) 
   postcode = db.Column(db.String(20))
   building_year = db.Column(db.Integer)
   climate_file = db.Column(db.String(100))
   building_TFA = db.Column(db.Float)
   thermal_mass = db.Column(db.String(100))
   winter_int_temp = db.Column(db.Float)
   summer_int_temp = db.Column(db.Float)
   height_above_sea = db.Column(db.Float)
   occupany = db.Column(db.Float)

   def __repr__(self):
        return '<Project {}>'.format(self.project_name)

Upvotes: 2

Views: 6500

Answers (2)

Nick
Nick

Reputation: 160

I had a similar issue with that same error. It was because there was a function with the same name. So that is probably why it was saying a function had no attribute query even though the table used with sqlalchemy is a class

Upvotes: 3

Yaakov Bressler
Yaakov Bressler

Reputation: 12018

Consider either implementing a class function which renders the object into the current string representation you desire or implementing a hybrid property.

String method:

class Projects(db.Model):
    ...
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    project_name = db.Column(db.String(100))
    ...

    def __str__(self):
         return f'{self.id}: {self.project_name}'

Use string method as follows:

project_choices = Projects.query.all()  
form2 = Which_project()
# probably str(x) would work, but if it doesn't the code below def works
form2.project_choice.choices = [x.__str__() for x in project_choices]

Hybrid property method:

from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method
class Projects(db.Model):
    ...
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    project_name = db.Column(db.String(100))
    ...

    @hybrid_property
    def project_choice(self):
        return f'{self.id}: {self.project_name}'

Use hybrid property as follows:

# Access only the hybrid property
project_choices = Projects.query(Projects.project_choice).all()  
form2 = Which_project()
form2.project_choice.choices = project_choices

Upvotes: 0

Related Questions