I want to add images on my flaskblog posts, however, I am facing with the following error:
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: post.post_image
[SQL: SELECT post.id AS post_id, post.title AS post_title, post.date_posted AS post_date_posted, post.content AS post_content, post.user_id AS post_user_id, post.post_image AS post_post_image
FROM post]
(Background on this error at: http://sqlalche.me/e/e3q8)
These are my imports in routes.py file
import os
import secrets
from PIL import Image
from flask import render_template, url_for, flash, redirect, request, abort
from flaskblog import app, db, bcrypt
from flaskblog.forms import RegistrationForm, LoginForm, UpdateAccountForm, PostForm
from flaskblog.models import User, Post
from flask_login import login_user, current_user, logout_user, login_required
This is my new_post function and new post route in routes.py file
#app.route("/post/new", methods=['GET', 'POST'])
#login_required
def new_post():
form = PostForm()
if form.validate_on_submit():
if form.post_picture.data:
image_post = save_picture(form.picture.data)
form.post_picture = image_post
post = Post(title=form.title.data, content=form.content.data, author=current_user, post_image= form.post_picture.data)
db.session.add(post)
db.session.commit()
flash('Your post has been created!', 'success')
return redirect(url_for('home'))
image_file = url_for('static', filename='profile_pics/')
return render_template('create_post.html', title='New Post', image_file=image_file,
form=form, legend='New Post')
This is my imports in form.py file
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from flask_login import current_user
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from flaskblog.models import User
this is my PostForm class in forms.py file
from datetime import datetime
from flaskblog import db, login_manager
from flask_login import UserMixin
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
def __repr__(self):
return f"User('{self.username}', '{self.email}', '{self.image_file}')"
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
post_image = db.Column(db.String(20), nullable=False)
def __repr__(self):
return f"Post('{self.title}', '{self.date_posted}')"
regarding these codes, what do you think I should do in order to fix this error? Thank you.
edit1:
This is my init.py file
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from flask_login import LoginManager
app = Flask(__name__)
app.config['SECRET_KEY'] = '5791628bb0b13ce0c676dfde280ba245'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
login_manager = LoginManager(app)
login_manager.login_view = 'login'
login_manager.login_message_category = 'info'
from flaskblog import routes
edit2: I am having the following error after dropping tables from the db.
This is the blog post view
Have you newly added the post_image field to the Post model?
If so, you'd need to either
use a database migration tool like Alembic to generate and apply the SQL statements to alter the table, or
add the suitable column into the table by hand (tedious), or
drop the table and recreate it (destroying all data; dangerous)
Related
I wanted to start programming and thus looked at some tutorials on YouTube.
I have followed this tutorial 1:1 but it still doesn't work and I am stuck, can someone maybe help me fix this?
from flask import Blueprint, render_template, request, flash
from flask_login import login_required, current_user
from .models import Vocab
from . import db
views = Blueprint('views', __name__)
#views.route('/', methods=['GET', 'POST'])
#login_required
def home():
if request.method == 'POST':
vocab = request.form['vocab']
if len(vocab) < 1:
flash('Vocabulary is too short!', category='error')
else:
# somehow can't find the problem, the vocab can't be saved in the database, data is apparently an invalid keyword
new_vocab = Vocab(data=vocab, user_id=current_user.id)
db.session.add(new_vocab)
db.session.commit()
flash('Vocabulary added successfully', category='success')
return render_template("home.html", user=current_user)
models.py :
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class Vocab(db.Model):
id = db.Column(db.Integer, primary_key=True)
data = db.Column(db.String(10000))
date = db.Column(db.DateTime(timezone=True), default=func.now())
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
username = db.Column(db.String(150))
password = db.Column(db.String(100))
notes = db.relationship('Vocab')
i have an isssue with flask-login the user loader is not working
Exception: Missing user_loader or request_loader. Refer to http://flask-login.readthedocs.io/#how-it-works for more info.
and
when i try to import the user model in shell:
AttributeError: 'LoginManager' object has no attribute 'load_user'
This is my code:
-------------------app/__init__.py----------------
from app.config import Config
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
#create app
app = Flask(__name__)
app.config.from_object(Config)
#init pckages
db = SQLAlchemy(app)
login_manager = LoginManager(app)
#import Blueprints
from app.blueprints.user.routes import user
from app.blueprints.dashboard.routes import dashboard
#register Blueprints
app.register_blueprint(user)
app.register_blueprint(dashboard)
------------------------------app.py-------------------------------
from app import app
if __name__ == "__main__":
app.run(debug=True)
------------------------------user model------------------------------------
from app import db, login_manager
from flask_login import UserMixin
#login_manager.load_user
def load_user(user):
return User.get(user)
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(20), unique=True, nullable=False)
avatar = db.Column(db.String(50), default="default.jpg")
password = db.Column(db.String(60), nullable=False)
def __repr__(self):
return self.username
The decorator should be
#login_manager.user_loader not load_user
Instead of :
#login_manager.load_user
def load_user(user):
return User.get(user)
try :
#login_manager.user_loader
def load_user(user):
return User.query.get(int(user))
You can make a slight modification to your current user model. As it is currently, you have:
#login_manager.load_user
def load_user(user):
return User.get(user)
Consider this:
Import LoginManager from flask_login
from flask_login import LoginManager
login = LoginManager(app)
Update your user model as follows:
from flask_login import UserMixin
from app import login # the variable from Flask-login
#login.user_loader
def load_user(id):
return User.query.get(int(id)) # slightly modified such that the user is loaded based on the id in the db
The user loader is registered with Flask-Login with the #login.user_loader decorator. The id that Flask-Login passes to the function as an argument is going to be a string, so databases that use numeric IDs need to convert the string to integer as you see above.
I started learning flask a few weeks ago and I followed flask mega tutorial. Now I want to do some programming myself and I tried to return data from database in json format using flask-marshmallow and I got stuck. I got an error saying ImportError: cannot import name fields.
This is full error message
This is models.py module:
followers = db.Table('followers',
db.Column('follower_id', db.Integer, db.ForeignKey('user.id')),
db.Column('followed_id', db.Integer, db.ForeignKey('user.id')))
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
country = db.Column(db.String(140))
nationality = db.Column(db.String(140))
password_hash = db.Column(db.String(128))
# Definisanje veze sa Post tabelom
posts = db.relationship('Post', backref='author', lazy='dynamic')
about_me = db.Column(db.String(140))
last_seen = db.Column(db.DateTime, default=datetime.utcnow())
# Definisanje veze sa followers tabelom
followed = db.relationship(
'User', secondary=followers,
primaryjoin=(followers.c.follower_id == id),
secondaryjoin=(followers.c.followed_id == id),
backref=db.backref('followers', lazy='dynamic'), lazy='dynamic')
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(140))
timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
def __repr__(self):
return '<Post {}>'.format(self.body)
#Declaring marshmallow ModelSchema
class UserSchema(ma.ModelSchema):
class Meta:
model = User
This is routes.py module:
#app.route('/all_users', methods=['GET'])
def get_all_users():
users = User.query.all()
user_schema = UserSchema(many=True)
out = user_schema.dump(users).data
return jsonify(out)
I didn't include all code but I will provide it if it's necessary.
Since error message point me to microblog.py and init.py, also modules in my app, so I will include these two modules.
microblog.py
from app import app, db
from app.models import User, Post
#app.shell_context_processor
def make_shell_context():
return {'db': db, 'User': User, 'Post': Post}
__init__.py
from flask import Flask
from logging.handlers import RotatingFileHandler
import logging
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_login import LoginManager
from flask_mail import Mail
from flask_bootstrap import Bootstrap
from flask_moment import Moment
import os
'''Inicijalizacija ekstenzija'''
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
login = LoginManager(app)
login.login_view = 'login'
mail = Mail(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
ma = Marshmallow(app)
from app import routes, models, errors
if not app.debug:
if not os.path.exists('logs'):
os.mkdir('logs')
file_handler = RotatingFileHandler('logs/microblog.log', maxBytes=10240,
backupCount=10)
file_handler.setFormatter(logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s [in %(pathname)s:%(lineno)d]'))
file_handler.setLevel(logging.INFO)
app.logger.addHandler(file_handler)
app.logger.setLevel(logging.INFO)
app.logger.info('Microblog startup')
i have been getting this error sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: user but i dont know why since i created my database at the good directory by the command sqlite3 database.db and .tables .I tried db.create_all() but if it is before the declaration of db it of course not work but if i put it after it does not change anything
I have an other problem which is that db."" is always marked as an error. I tried to install pylint-flask and loading it in the settings. It worked for around 5 mins then the errors are back again (Instance of 'SQLAlchemy' has no 'Column' memberpylint(no-member))
from flask import Flask, render_template, redirect, url_for
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField
from wtforms.validators import InputRequired, Email, Length
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
app = Flask(__name__)
app.config['SECRET_KEY'] = 'Thisissupposedtobesecret!'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///sqlite-tools-win32-x86-3290000/database.db'
bootstrap = Bootstrap(app)
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
#login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
class LoginForm(FlaskForm):
username = StringField('username', validators=[InputRequired(), Length(min=4, max=15)])
password = PasswordField('password', validators=[InputRequired(), Length(min=8, max=80)])
remember = BooleanField('remember me')
class RegisterForm(FlaskForm):
email = StringField('email', validators=[InputRequired(), Email(message='Invalid email'), Length(max=50)])
username = StringField('username', validators=[InputRequired(), Length(min=4, max=15)])
password = PasswordField('password', validators=[InputRequired(), Length(min=8, max=80)])
after defining your Model you need to call create_all() to update the changes to the database.
for example..
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(15), unique=True)
email = db.Column(db.String(50), unique=True)
password = db.Column(db.String(80))
db.create_all()
Short story. I took this example:https://github.com/MrJoes/Flask-Admin/tree/master/examples/sqla i played with it and everything was fine until i decided what i want to split app.py(main file) to two parts. In main file app.py i will keep views and in another models.py i will keep all classes. Both files are in same folder.
Issue. I get error Error when running my app.py file:
"NameError: name 'UserAdmin' is not defined"
This is part from app.py file where i try to call Class UserAdmin from models.py file:
import os
import os.path as op
from flask import Flask, render_template, request, redirect, url_for, abort, session, flash
from flask_sqlalchemy import SQLAlchemy, Model
from flask_login import UserMixin, session, LoginManager, login_user, login_required, logout_user
from flask_bcrypt import Bcrypt,check_password_hash,generate_password_hash
from models import *
from flask_admin import Admin, BaseView, expose
app = Flask(__name__)
app.config['SECRET_KEY'] = '123456790'
app.config['DATABASE_FILE'] = 'db.sqlite'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + app.config['DATABASE_FILE']
app.config['SQLALCHEMY_ECHO'] = True
db = SQLAlchemy(app)
bcrypt = Bcrypt(app)
admin = Admin(app, name='Admin Site', template_mode='bootstrap3')
# Add views. This is where it fails
admin.add_view(UserAdmin(User, db.session))
models.py file where is described UserAdmin part:
from wtforms import validators
from app import db, app, url_for, admin
from flask_admin.contrib import sqla
from flask_admin.contrib.sqla import filters, ModelView
from flask_login import UserMixin
...
# Create models
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100))
username = db.Column(db.String(80), unique=True)
email = db.Column(db.String(120), unique=True)
# Required for administrative interface. For python 3 please use __str__ instead.
def __str__(self):
return self.username
class UserInfo(db.Model):
id = db.Column(db.Integer, primary_key=True)
key = db.Column(db.String(64), nullable=False)
value = db.Column(db.String(64))
user_id = db.Column(db.Integer(), db.ForeignKey(User.id))
user = db.relationship(User, backref='info')
def __str__(self):
return '%s - %s' % (self.key, self.value)
class UserAdmin(sqla.ModelView):
inline_models = (UserInfo,)
...
If someone could point me what i am doing wrong there it would be very nice.
Thanks