Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Flask: Making my first web site
#11
I believe it is validate_on_submit
Reply
#12
correct!
Reply
#13
Again, trouble. It's time to make a database but...
from datetime import datetime 
from flask import Flask, render_template, url_for, flash, redirect
from flask_sqlalchemy import SQLAlchemy
from forms import RegistrationForm, LoginForm 

app = Flask(__name__)
app.config['SECRET_KEY'] = '24b6f628700853713c55abab2a9d8309'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://site.db'
db = SQLALCHEMY(app)

class User(db.Model):
	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.Columb(db.String(60), nullable=False, default=datetime.utcnow)
	content = db.Column(db.Text, 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_keys=True)
	title = db.Column(db.String(100), nullable=False)
	date_posted = db.Column(db.DateTime, nullable=False)
	content = db.Column(db.Text, nullable=False)
	user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
	
	def __repr__(self):
		return f"Post('{self.title}', '{self.date_posted}')"

posts = [
    {
	    'author': 'Corey Schafer',
		'title': 'Blog Post 1',
		'content': 'First post content',
		'data_posted': 'April 20, 2018'
	},
	{
	    'author': 'Jane Doe',
		'title': 'Blog Post 2',
		'content': 'Second post content',
		'date_posted': 'April 21, 2018'
	}
]

@app.route("/")
@app.route("/home")
def home():
    return render_template('home.html', posts=posts)
	
@app.route("/about")
def about():
	return render_template('about.html', title='About')

@app.route("/register", methods=['GET', 'POST'])
def register():
	form = RegistrationForm()
	if form.validate_on_submit():
		flash(f'Account created for {form.username.data}!', 'success')
		return redirect(url_for('home'))
	return render_template('register.html', title='Register', form=form)
	
@app.route("/login", methods=['GET', 'POST'])
def login():
	form = LoginForm()
	if form.validate_on_submit():
		if form.email.data == '[email protected]' and form.password.data == 'password':
			flash('You have been logged in!', 'success')
			return redirect(url_for('home'))
		else:
			flash('Login Unsuccessful. Please check your username and password', 'danger')
	return render_template('login.html', title='Login', form=form)

if __name__ == '__main__':
	app.run(debug=True)
from flaskblog import db

db.create_all()
Error:
Traceback (most recent call last): File "C:\Python37\kodovi\Environments\Flask_Blog\create_db.py", line 1, in <module> from flaskblog import db File "C:\Python37\kodovi\Environments\Flask_Blog\flaskblog.py", line 9, in <module> db = SQLALCHEMY(app) NameError: name 'SQLALCHEMY' is not defined
Reply
#14
Hi,

Hint: Python is case-sensetive, so SQLAlchemy is not the same SQLALCHEMY.

Except this: of course is easier to raise a question in a forum and hope that somebody answers for you - but in this case, it is super-easy to find and eliminate the error yourself. Especially as the traceback is super clear on what the problem is.
In case you do not understand what's wrong in your code, I'd recommend to step back two steps and read through the Python tutorial again to get behind all the basics of Python. Otherwise, you will have a very hard time with your web application project.

Regards, noisefloor
Reply
#15
you imported
from flask_sqlalchemy import SQLAlchemy
Recommended Tutorials:
Reply
#16
That's what we have in Corey's code too:
https://github.com/CoreyMSchafer/code_sn...askblog.py

I just did a copy/paste and after running this second code to create a database got this:
Error:
C:\Python37\lib\site-packages\flask_sqlalchemy\__init__.py:835: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning. 'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
on stackoverflow I found that solution is to add SQLALCHEMY_TRACK_MODIFICATIONS = False to app configuration but I'm not sure how to do that. I got syntax error when tried to add it in some way. Any suggestion?
here it is:
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
Reply
#17
Hi,

@Truman: programming is neither blind copy and paste nor guessing. As I said above, if you proceed like this, you won't learn anything. Try as hard as you can to understand what you are doing.

Quote:when tried to add it in some way.
And how should we know what you tried? Show your code, even if it is not running. Your existing code has lines in it where you add keys to the configuration. So it shouldn't be too difficult to add more keys.

Regards, noisefloor
Reply
#18
I added it in the meantime in flaskblog.py file, ran the program to make a database but site.db file is still not created in my project folder.
site.db created! Now let's try with the next step.

ok, I added some data to the database with this code:
from flaskblog import User, Post
from flaskblog import db

user_1 = User(username='Corey', email='[email protected]', password='password')
db.session.add(user_1)
user_2 = User(username='JohnDoe', email='[email protected]', password='password')
db.session.add(user_2)
db.session.commit()
...and it works.
it can be checked with User.querry.all() if anybody wants to know.
Reply
#19
I'm trying to upload a picture to the account page.
routes.py
from flask import render_template, url_for, flash, redirect, request
from flaskblog import app, db, bcrypt
from flaskblog.forms import RegistrationForm, LoginForm
from flaskblog.models import User, Post
from flask_login import login_user, current_user, logout_user, login_required


posts = [
    {
        'author': 'Corey Schafer',
        'title': 'Blog Post 1',
        'content': 'First post content',
        'date_posted': 'April 20, 2018'
    },
    {
        'author': 'Jane Doe',
        'title': 'Blog Post 2',
        'content': 'Second post content',
        'date_posted': 'April 21, 2018'
    }
]


@app.route("/")
@app.route("/home")
def home():
    return render_template('home.html', posts=posts)


@app.route("/about")
def about():
    return render_template('about.html', title='About')


@app.route("/register", methods=['GET', 'POST'])
def register():
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    form = RegistrationForm()
    if form.validate_on_submit():
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
        user = User(username=form.username.data, email=form.email.data, password=hashed_password)
        db.session.add(user)
        db.session.commit()
        flash('Your account has been created! You are now able to log in', 'success')
        return redirect(url_for('login'))
    return render_template('register.html', title='Register', form=form)


@app.route("/login", methods=['GET', 'POST'])
def login():
    if current_user.is_authenticated:
        return redirect(url_for('home'))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get('next')
            return redirect(next_page) if next_page else redirect(url_for('home'))
        else:
            flash('Login Unsuccessful. Please check email and password', 'danger')
    return render_template('login.html', title='Login', form=form)


@app.route("/logout")
def logout():
    logout_user()
    return redirect(url_for('home'))


@app.route("/account")
@login_required
def account():
	image_file = url_for('static', filename='profile_pics/' + current_user.image_file)
	return render_template('account.html', title='Account', image_file=image_file)
account.html
{% extends "layout.html" %}
{% block content %}
    <div class="content-section">
	    <div class="media">
		    <img class="rounded-circle account-img" src="{{ image_file }}">
			<div class="media-body">
			    <h2 class="account-heading">{{ current_user.username }}</h2>
				<p class="text-secondary">{{ current_user.email }}</p>
			</div>
		</div>
		<!-- FORM HERE -->
    </div>
{% endblock content %}
So basically I opened a folder profile_pics, put one image in it and then placed that folder into a folder called static. When I go to the Account page there is a frame where the image should stand. Any idea why?
p.s to give a clearer picture there is also a models.py file with image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
Reply
#20
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


@app.route("/")
@app.route("/home")
def home():
    page = request.args.get('page', 1, type=int)
    posts = Post.query.order_by(Post.date_posted.desc()).paginate(page=page, per_page=5)
    return render_template("home.html", posts=posts)


@app.route("/about")
def about():
    return render_template("about.html", title="About")


@app.route("/register", methods=["GET", "POST"])
def register():
    if current_user.is_authenticated:
        return redirect(url_for("home"))
    form = RegistrationForm()
    if form.validate_on_submit():
        hashed_password = bcrypt.generate_password_hash(form.password.data).decode(
            "utf-8"
        )
        user = User(
            username=form.username.data, email=form.email.data, password=hashed_password
        )
        db.session.add(user)
        db.session.commit()
        flash("Your account has been created! You are now able to log in", "success")
        return redirect(url_for("login"))
    return render_template("register.html", title="Register", form=form)


@app.route("/login", methods=["GET", "POST"])
def login():
    if current_user.is_authenticated:
        return redirect(url_for("home"))
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(email=form.email.data).first()
        if user and bcrypt.check_password_hash(user.password, form.password.data):
            login_user(user, remember=form.remember.data)
            next_page = request.args.get("next")
            return redirect(next_page) if next_page else redirect(url_for("home"))
        else:
            flash("Login Unsuccessful. Please check email and password", "danger")
    return render_template("login.html", title="Login", form=form)


@app.route("/logout")
def logout():
    logout_user()
    return redirect(url_for("home"))


def save_picture(form_picture):
    random_hex = secrets.token_hex(8)
    _, f_ext = os.path.splitext(form_picture.filename)
    picture_fn = random_hex + f_ext
    picture_path = os.path.join(app.root_path, "static/profile_pics", picture_fn)

    output_size = (125, 125)
    i = Image.open(form_picture)
    i.thumbnail(output_size)
    i.save(picture_path)

    return picture_fn


@app.route("/account", methods=["GET", "POST"])
@login_required
def account():
    form = UpdateAccountForm()
    if form.validate_on_submit():
        if form.picture.data:
            picture_file = save_picture(form.picture.data)
            current_user.image_file = picture_file
        current_user.username = form.username.data
        current_user.email = form.email.data
        db.session.commit()
        flash("Your account has been updated!", "success")
        return redirect(url_for("account"))
    elif request.method == "GET":
        form.username.data = current_user.username
        form.email.data = current_user.email
    image_file = url_for("static", filename="profile_pics/" + current_user.image_file)
    return render_template(
        "account.html", title="Account", image_file=image_file, form=form
    )


@app.route("/post/new", methods=["GET", "POST"])
@login_required
def new_post():
    form = PostForm()
    if form.validate_on_submit():
        post = Post(
            title=form.title.data, content=form.content.data, author=current_user
        )
        db.session.add(post)
        db.session.commit()
        flash("Your post has been created!", "success")
        return redirect(url_for("home"))
    return render_template('create_post.html', title='New Post', 
	                        form=form, legend='New Post')
	

@app.route("/post/<int:post_id>")
def post(post_id):
	post = Post.query.get_or_404(post_id)
	return render_template('post.html', title=post.title, post=post)
	

@app.route("/post/<int:post_id>/update", methods=['GET', 'POST'])
@login_required
def update_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author != current_user:
        abort(403)
    form = PostForm()
    if form.validate_on_submit():
        post.title = form.title.data
        post.content = form.content.data 
        db.session.commit()
        flash('Your post has been updated!', 'success')
        return redirect(url_for('post', post_id=post.id))
    elif request.method == 'GET':
        form.title.data = post.title 
        form.content.data = post.content 
    return render_template('create_post.html', title='Update Post', 
	                       form=form, legend='Update Post')
	
	
@app.route("/post/<int:post_id>/delete", methods=['POST'])
@login_required
def delete_post(post_id):
    post = Post.query.get_or_404(post_id)
    if post.author !=current_user:
        abort(403)
    db.session.delete(post)
    db.session.commit()
    flash('Your post has been deleted!', 'success')
    return redirect(url_for('home'))


@app.route("/user/<str:username>")
def user_posts(username):
	page = requests.args.get('page', 1, type=int)
	user = User.query.filter_by(username=username).first_or_404()
	posts = Post.query.filter_by(author=user)\
	    .order_by(Post.date_posted.desc())\
        .paginate(page=page, per_page=5)
	return render_template('user_posts.html.', posts=posts, user=user)
	
error
Error:
Traceback (most recent call last): File "C:\Python37\kodovi\Environments\Flask_Blog\run.py", line 1, in <module> from flaskblog import app File "C:\Python37\kodovi\Environments\Flask_Blog\flaskblog\__init__.py", line 16, in <module> from flaskblog import routes File "C:\Python37\kodovi\Environments\Flask_Blog\flaskblog\routes.py", line 155, in <module> @app.route("/user/<str:username>") File "C:\Python37\lib\site-packages\flask\app.py", line 1251, in decorator self.add_url_rule(rule, endpoint, f, **options) File "C:\Python37\lib\site-packages\flask\app.py", line 67, in wrapper_func return f(self, *args, **kwargs) File "C:\Python37\lib\site-packages\flask\app.py", line 1217, in add_url_rule self.url_map.add(rule) File "C:\Python37\lib\site-packages\werkzeug\routing.py", line 1388, in add rule.bind(self) File "C:\Python37\lib\site-packages\werkzeug\routing.py", line 730, in bind self.compile() File "C:\Python37\lib\site-packages\werkzeug\routing.py", line 790, in compile _build_regex(self.rule if self.is_leaf else self.rule.rstrip("/")) File "C:\Python37\lib\site-packages\werkzeug\routing.py", line 779, in _build_regex convobj = self.get_converter(variable, converter, c_args, c_kwargs) File "C:\Python37\lib\site-packages\werkzeug\routing.py", line 738, in get_converter raise LookupError("the converter %r does not exist" % converter_name) LookupError: the converter 'str' does not exist
Any idea how is it possible that 'str' doesn't exist?
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Flask - Opening second page via href is failing - This site can’t be reached rafiPython1 2 5,491 Apr-11-2018, 08:41 AM
Last Post: rafiPython1

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020