This question already has answers here:
AttributeError: can't set attribute when connecting to sqlite database with flask-sqlalchemy
(6 answers)
Closed 1 year ago.
I try to create a database and put an article table in routes.py's /articles/<article_name> route but it gives me AttributeError: can't set attribute. I looked up other sources for a solution but they seemed irrelevant. Error occurs when create_all(), add(), commit() are used.
models.py
from files import db
from datetime import datetime
class Article(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False,unique=True)
article_content = db.Column(db.Text)
date = db.Column(db.DateTime,default=datetime.utcnow)
abstract = db.Column(db.String(150))
comments = db.relationship("Comment", backref="article", lazy = True)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_name = db.Column(db.String(30), unique=True, nullable=False)
password = db.Column(db.String(30), nullable=False)
comments = db.relationship("Comment", backref="user", lazy = True)
class Comment(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_comment = db.Column(db.String(200), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey("user.id"))
article_id = db.Column(db.Integer, db.ForeignKey("article.id"))
init.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = ''
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
from files import routes
routes.py
from files import app, db
from flask import render_template
from files.models import Article
from files.forms import RegisterForm, LoginForm
#app.route('/')
#app.route('/main')
#app.route('/home')
def home():
return render_template("home.html")
#app.route('/articles/<article_name>') # dynamic route
def article(article_name):
db.create_all()
article_ = Article(title = article_name, article_content = "article", abstract = "ndng")
db.session.add(article_)
db.session.commit()
return render_template("article.html", article_name=article_name)
#app.route('/articles')
def articles():
return render_template("articles.html")
#app.route('/register')
def register():
form = RegisterForm()
return render_template("register.html", form = form)
#app.route('/login')
def login():
form = LoginForm()
return render_template("login.html", form = form)
I recently delt with that same error message. It is actually due to an upgrade in SQLAlchemy, which gets installed as a dependency of flask-sqlalchemy.
You can find the question I posted on stackoverflow for the issue here:
The problem gets solved by uninstalling SQLAlchemy==1.4.0 and installing the previous version SQLAlchemy==1.3.23.
Try doing that and see if it helps.
Just Downgrade the SQLAlchemy .
For some reason the latest version is not working
pip install 'SQLAlchemy<1.4.0'
Downgrading SQLAlchemy to anything lower than 1.4.0 (1.3.8 in my case) solves the problem.
Related
When I try to use flask-migrate with my model and a Postgres database, it does not work. Even if the database is created at startup. Every time migrate only detects the following:
INFO [alembic.autogenerate.compare] Detected added unique constraint 'None' on '['Auth_ID']'
INFO [alembic.autogenerate.compare] Detected added unique constraint 'None' on '['ClosedCourse_ID']'
My Model (much larger but is poorly designed like this)
class SKAuthentication(db.Model):
__tablename__ = 'sk-authentication'
Auth_ID = db.Column(UUID(as_uuid=True), primary_key=True, unique=True)
Basic_Auth = db.Column(Text, nullable=False)
Basic_User = db.Column(Text, nullable=False)
Teacher_ID = db.Column(UUID(as_uuid=True), db.ForeignKey('sk-teacher.Teacher_ID'), nullable=False)
Model = db.Column(Text, nullable=True)
Phone_ID = db.Column(Text, nullable=True)
Brand = db.Column(Text, nullable=True)
VersionInstalled = db.Column(Text, nullable=False, default='0.0.0')
def __init__(self, teacher_id):
chars = string.digits + string.ascii_letters + string.punctuation
self.Basic_Password = ''.join(secrets.choice(chars) for _ in range(256))
self.Auth_ID = create_ID(teacher_id, token_1, auth_crypt)
self.Basic_Auth = sha512_crypt.encrypt(self.Basic_Password)
self.Basic_User = create_ID(self.Basic_Auth, self.Auth_Secret)
self.Teacher_ID = teacher_id
class SKDayilyClosedCourse(db.Model):
__tablename__ = 'sk-daily-closed-course'
ClosedCourse_ID = db.Column(UUID(as_uuid=True), primary_key=True, unique=True)
Teachers_Group_ID = db.Column(UUID(as_uuid=True), db.ForeignKey('sk-teachers-groups.Row_ID'), nullable=False)
Course_Date = db.Column(Date, nullable=False)
Closed = db.Column(BOOLEAN, nullable=False, default=False)
Reminded = db.Column(BOOLEAN, nullable=False, default=False)
def __init__(self, teachers_group_id, course_date, reminded):
self.ClosedCourse_ID = create_ID(teachers_group_id, False, False, course_date)
self.Teachers_Group_ID = teachers_group_id
self.Course_Date = course_date
self.Reminded = reminded
My run.py looks like this:
from flask import Flask, session
from flask_sqlalchemy import SQLAlchemy
from modules.extensions import csrf, migr, cors
from config import DevelopmentConfig
from flask_migrate import upgrade, migrate
db = SQLAlchemy()
migr = Migrate()
def create_app():
app = Flask(__name__)
csrf.init_app(app)
app.config.from_object(DevelopmentConfig)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db.init_app(app)
cors.init_app(app, resources={r"/mobile/v1/*": {"origins": "GET, POST, OPTIONS"}})
migr.init_app(app, db, render_as_batch=False)
with app.app_context():
import modules.database.model
db.create_all()
db.session.commit()
migrate()
upgrade()
from application import application
from application import application_ticket
from application import application_mobile
from application import application_bookings
app.register_blueprint(application.application)
app.register_blueprint(application_ticket.ticket, url_prefix="/ticket")
app.register_blueprint(application_mobile.mobile, url_prefix="/mobile/v1")
app.register_blueprint(application_bookings.bookings, url_prefix="/bookings/v1")
#app.before_request
def before_request():
session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=1)
return app
This is the important part form my extensions.py
from flask_wtf import CSRFProtect
from flask_migrate import Migrate
from flask_cors import CORS
csrf = CSRFProtect()
migr = Migrate()
cors = CORS()
...
And that's my wsgi.py:
from run import create_app
app = create_app()
Once it worked, but I don't know how. I didn't change anything, so I tried to reproduce it and I encountered the same problem I mentioned before. I am not sure how to proceed with this problem.
I tried to create the tables inside the models.py and try to migrate everything from there, but still just the unique constraints.
Another way, I figured out was to import the models, which I also needed to create the tables with Flask-SQLAlchemy, but that changed nothing.
Next solution I've found was, to run everything from console. Nothing changed.
Other solution: Drop Table "alembic_version" -> didn't changed anything.
Hopefully someone can help me soon!
I am expecting to get following output:
INFO [alembic.autogenerate.compare] Detected added table '[<Tablename>]'
...
Thank you all!
I'm currently trying my hand at Flask-SQLAlchemy and I'm running into the following problem when it comes to running the commit() method:
First, here is my User class:
from flask_login import LoginManager, UserMixin
from flask_sqlalchemy import Model, SQLAlchemy
from app import db
class User(db.Model, UserMixin):
def __init__(self, id, name, password, active):
self.id = id
self.name = name
self.password = password
self.active = active
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False, unique=True)
password = db.Column(db.String, nullable=False)
active = db.Column(db.Boolean, nullable=False, default=True)
#property
def is_active(self):
return self.active
Now my main app:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.sqlite'
app.secret_key = b'test'
db = SQLAlchemy(app)
from user import User
db.create_all()
db.session.commit() # This commit works fine!
admin = User(1, 'admin', 'admin', True)
db.session.add(admin)
db.session.commit() # <------ Value Error at this position
print(User.query.all())
And I get the following Error message when I try to run my code:
in flask_sqlalchemy\__init__.py
before_models_committed.send(session.main, changes=list(d.values()))
AttributeError: 'SignallingSession' object has no attribute 'main'
I am using Pycharm and the version of flask_sqlalchemy is 2.5.1
Am I using the module wrong?
Thank you for every helpfull comment!
Kind regards,
Bagheera
Now I don't know if this really counts as a solution, but I tried lowering the version of the flask_sqlalchemy module.
After this didn't work either, because now other error messages appeared, I set the version back to the highest.
After that it worked in a mysterious way. But maybe someone has an explanation for this or experienced something similar.
I am trying to implement a restful API with Flask using flask-restful, flask-sqlalchemy and flask-marshmallow. I am aware there are many questions about this issue but I still can't figure it out.
Solutions like using strict=True in marshmallow schemas or adding .data to user_schema.dump(result) don't let me see my result in the response body.
Here is my code :
# User.py file
from flask import jsonify, request
from flask_restful import Resource
from src import db
from src.models.user import User
from src.validation import UserSchema
class Users(Resource):
def get(self):
try:
data = request.get_json()
user = User.query.filter_by(email=data['email']).first()
user_schema = UserSchema()
result = user_schema.dump(user)
return jsonify(result)
except:
return jsonify({'error_message': 'User not found'})
def post(self):
try:
data = request.get_json()
user = User(data["firstName"], data["lastName"],
data["email"], data["password"])
db.session.add(user)
db.session.commit()
user_schema = UserSchema()
result = user_schema.dump(user)
return result
except:
return jsonify({'error_message': 'User already exists in database'})
The init.py file :
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_restful import Api
from flask_marshmallow import Marshmallow
app = Flask(__name__)
app.config["DEBUG"] = True
app.config["SQLALCHEMY_ECHO"] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql:///gauss"
ma = Marshmallow(app)
api = Api(app)
db = SQLAlchemy(app)
from src import routes
The validation.py file :
from src import ma
from src.models.user import User
class UserSchema(ma.SQLAlchemySchema):
class Meta:
model = User
And the User.py schema for the database :
from src import db
from datetime import datetime
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
firstName = db.Column(db.String(20))
lastName = db.Column(db.String(20))
email = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(), nullable=False)
createdAt = db.Column(db.DateTime, default=datetime.utcnow)
def __init__(self, firstName, lastName, email, password):
self.firstName = firstName
self.lastName = lastName
self.email = email
self.password = password
I've been looking for solutions for a few days now and it seems that marshmallow returning empty json occures mostly when querying with the .all() method for instance, because marshmallow .dump() method misses the Many=True configuration.
I'm probably missing something but I can't wrap my head around it. Any help appreciated !
i had the same problem, the solution to my problem was to change UserSchema(ma.SQLAlchemySchema): to UserSchema(ma.SQLAlchemyAutoSchema):
I am trying to build a simple blogging platform to learn Python and Flask. I am using SQLAlchemy to connect to a Postgres db hosted on Heroku and flask_s3 to serve static files from an AWS bucket. Im mostly following along from this:
https://gist.github.com/mayukh18/2223bc8fc152631205abd7cbf1efdd41/
All was going well, it is correctly hosted on Heroku and connceted to AWS S3 bucket, ready to go. I am stuck however on how to add blog posts to the database through some kind of form or route that will allow me to fill in the attributes of a blog post (found in Post in models.py below)
I have html templates that get rendered and the following three files, app.py, manage.py and models.py.
app.py:
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_s3 import FlaskS3
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = '*URI for DB hosted on heroku'
app.config['FLASKS3_BUCKET_NAME'] = 'my S3 bucket on AWS'
db = SQLAlchemy(app)
s3 = FlaskS3(app)
from models import Post
#routes to templates to be rendered
if __name__ == '__main__'
app.run(debug=True)
manage.py:
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
and models.py:
from manage import db,app
class Post(db.Model):
__tablename__ = 'blogposts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), index=True, unique=True)
content = db.Column(db.Text, index=True, unique=True)
date = db.Column(db.DateTime, index=True, unique=True)
tag = db.Column(db.String(120), index=True, unique=True)
cover = db.Column(db.String(120), index=True, unique=True)
def __repr__(self):
return '<Post: %r>' % (self.title)
my file strucure is:
-blog
--__pycache__
--migrations
--static
--templates
app.py
manage.py
models.py
Pipfile
Pipfile.lock
Procfile
I want to work on this locally (before I publish anything to Heroku) but have no idea what to do from here. Anyone have advice on how to go about creating a route to add blog posts and saving them to a local Postgres instance before I go about pushing finalized blog posts to Heroku?
the gist I have been following has something like this as a route:
#app.route('/add/')
def webhook():
#post attributes defined
p = Post(id = id, title = title, date = datetime.datetime.utcnow, content = content, tag = tag, cover = cover)
print("post created", p)
db.session.add(p)
db.session.commit()
return "post created"
when I try and run it locally I get the following error so I'm not sure I have the files connecting properly.
File "/Users/Mb/Desktop/datadude/app.py", line 15, in <module>
from models import Post
ImportError: cannot import name 'Post'
Sorry if this is the wrong place for this. If there is a better place to ask for advice let me know.
The problem exists in circular dependencies.
You could move initializing of SQLAlchemy to models.py. Then only run method init_app on db object in app.py.
models.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Post(db.Model):
__tablename__ = 'blogposts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), index=True, unique=True)
content = db.Column(db.Text, index=True, unique=True)
date = db.Column(db.DateTime, index=True, unique=True)
tag = db.Column(db.String(120), index=True, unique=True)
cover = db.Column(db.String(120), index=True, unique=True)
def __repr__(self):
return '<Post: %r>' % (self.title)
app.py
import datetime
from flask import Flask, render_template
from flask_s3 import FlaskS3
from models import db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = '*URI for DB hosted on heroku'
app.config['FLASKS3_BUCKET_NAME'] = 'my S3 bucket on AWS'
db.init_app(app)
s3 = FlaskS3(app)
from models import Post
#app.route('/add/')
def webhook():
#post attributes defined
p = Post(id = id, title = title, date = datetime.datetime.utcnow, content = content, tag = tag, cover = cover)
print("post created", p)
db.session.add(p)
db.session.commit()
return "post created"
#routes to templates to be rendered
if __name__ == '__main__':
app.run(debug=True)
You can read more about it https://github.com/slezica/bleg/blob/master/data/posts/2014-03-08-avoiding-circular-dependencies-in-flask.md
I am following this tutorial https://www.youtube.com/watch?v=kuyrL6krkwA. I have modified the db, table, and columns names for my app. Everything else is identical to tutorial. The error occurs (10 mins into tutorial) where he enters python shell and runs the following commands:
from models import User # my app uses 'User' not 'BlogPost'
users = User.query.all()
The Python Shell Script returns error message below:
sqlalchemy.exc.OperationalError: (OperationalError) no such
column:users.id u'SELECT users.id AS users_id, users.name AS
users_name, users.zipcode AS users_zipcode, users.inter1 AS
users_inter1, users.inter2 AS users_inter2, users.inter3 AS
users_inter3 \nFROM users' ()
The three files I am using are (App.py, models.py, db_create.py)
App.py
from flask import Flask, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///mfiyzc.db'
db = SQLAlchemy(app)
if __name__ == "__main__":
app.run(debug = True)
models.py
from app import db
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
zipcode = db.Column(db.Integer, nullable=False)
inter1 = db.Column(db.String, nullable=False)
inter2 = db.Column(db.String, nullable=False)
inter3 = db.Column(db.String, nullable=False)
def __init__(self, name, zipcode, inter1, inter2, inter3):
self.name = name
self.zipcode = zipcode
self.inter1 = inter1
self.inter2 = inter2
self.inter3 = inter3
def __repr__(self):
return '<title {}'.format(self.title)
db_create.py
from app import db
from models import User
db.create_all()
db.session.add(User("Jane Parker", 11104, "ice skating", "dancing", "reading"))
db.session.add(User("Bob Smith", 11104, "boxing", "cars", "beers"))
db.session.commit()
You need to run db_create.py ie :
python db_create.py
or
from models import User
db.create_all()
You are trying to query the table before it has been created.
I had the wrong field name (since I copied from the tutorial)
incorrect:
def __repr__(self):
return '<title {}'.format(self.title)
correct:
def __repr__(self):
return '<name {}'.format(self.name)