Here is my HTML dropdown menu. The value is the primary key of the child table.
<select id="category" name="category">
<option selected value="__None"></option>
<option value="1">Category Number One</option>
<option value="2">Category Number Two</option>
</select>
I need to update Post.category_id with the value integer 1 instead of "Category Number One". Here is my code.
# create new post
@app.route('/admin/post', methods=['GET', 'POST'])
@login_required # Required for Flask-Security
def create_post():
form = PostForm()
if form.validate_on_submit():
post = Post(title=form.title.data,
body=form.body.data,
pub_date=form.pub_date.data,
cateogry_id=form.category.data)
db.session.add(post)
db.session.commit()
flash('Your post has been published.')
return redirect(url_for('admin'))
posts = Post.query.all()
return render_template('create_post.html', form=form, posts=posts)
I've tried making...
cateogry_id=form.category.data
cateogry_id=form.category.value
Now wouldn't that be nice!
The comments class attribute defines a One-to-Many relationship between the Post model and the Comment model. You use the db. relationship() method, passing it the name of the comments model ( Comment in this case). You use the backref parameter to add a back reference that behaves like a column to the Comment model.
Step 1 - Install the Flask-SQLAlchemy extension. Step 2 - You need to import the SQLAlchemy class from this module. Step 3 - Now create a Flask application object and set the URI for the database to use. Step 4 - then use the application object as a parameter to create an object of class SQLAlchemy.
create_all() function to create the tables that are associated with your models. In this case you only have one model, which means that the function call will only create one table in your database: from app import db, Student. db.
What is Flask-SQLAlchemy? Flask-SQLAlchemy is an extension for Flask that aims to simplify using SQLAlchemy with Flask by providing defaults and helpers to accomplish common tasks. One of the most sought after helpers being the handling of a database connection across the app.
Flask-SQLAlchemy is a Flask extension that makes using SQLAlchemy with Flask easier, providing you tools and methods to interact with your database in your Flask applications through SQLAlchemy.
Definition of Flask wtforms Flask WTForms is defined as a plugin that enables and eases out the process of designing forms in Flask web applications. This library intends to provide an interactive interface for the users for developing such forms.
The ORM API provides a way to perform CRUD operations without writing raw SQL statements. In this section, we will study the ORM technology of Flask-SQLAlchemy and build a small web application.
This library is present within a Flask plugin which can be installed using the pip command. WTForms has been an undisputed winner in terms of handling forms for years and is still the most widely used, the reason being the ease of rendering and validation along with being flexible.
I figured it out! Here is my solution. Hopefully this writeup will help out the next guy.
The solution is to let extension do the work for you! Here is a working example the WT Forms sqlalchemy extension using Flask, WTForm, SQLAlchemy, and Jinja2. In short, you don't need to worry about the child id because the extension takes care of it automagically. that means when your dealing with SQLAlchemy Parent and Child models in a one to many relationship you ONLY have to deal with the PARENT.
MODEL
First, make sure your model and relationships are correct. Notice in my example how the relationships are defined and that the model's init only has CATEGORY... NOT CATEGORY_ID. My mistake was thinking I would have the populate my model's CATEGORY_ID field. Nope. The extension does it for you. In fact, if you try to do it manually like I did it won't work at all....
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80))
url = db.Column(db.String(120))
body = db.Column(db.Text)
create_date = db.Column(db.DateTime)
pub_date = db.Column(db.DateTime)
pub_status = db.Column(db.Text(80))
author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
author = db.relationship('User',
backref=db.backref('posts', lazy='dynamic'))
category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
category = db.relationship('Category',
backref=db.backref('posts', lazy='dynamic'))
def __init__(self, title, body, category, pub_date=None):
self.title = title
self.body = body
if pub_date is None:
pub_date = datetime.utcnow()
self.category = category
self.pub_date = pub_date
def __repr__(self):
return '<Post %r>' % self.title
class Category(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
description = db.Column(db.String(250))
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
Second, check out the form.... NOTICE I'm using the wtfrom sqlalchmey QuerySelectedField and the Category_ID field is absent...
FORM
from sprucepress.models import Tag, Category
from flask_wtf import Form
from wtforms.fields import StringField, DateTimeField
from wtforms.widgets import TextArea
from wtforms.validators import DataRequired
from wtforms.ext.sqlalchemy.orm import model_form
from wtforms.ext.sqlalchemy.fields import QuerySelectField
def enabled_categories():
return Category.query.all()
class PostForm(Form):
title = StringField(u'title', validators=[DataRequired()])
body = StringField(u'Text', widget=TextArea())
pub_date = DateTimeField(u'date create')
category = QuerySelectField(query_factory=enabled_categories,
allow_blank=True)
Now the FLASK routing and view logic... Notice in post NO category_id again! Only Category only!!!
ROUTING/VIEW
# create new post
@app.route('/admin/post', methods=['GET', 'POST'])
@login_required # required for Flask-Security
def create_post():
form = PostForm()
if form.validate_on_submit():
post = Post(title=form.title.data, pub_date=form.pub_date.data,
body=form.body.data, category=form.category.data)
db.session.add(post)
db.session.commit()
flash('Your post has been published.')
return redirect(url_for('admin'))
posts = Post.query.all()
return render_template('create_post.html', form=form, posts=posts)
Finally, the template. Guess what, we only generate the form.category field!!!
TEMPLATE
<form action="" method=post>
{{form.hidden_tag()}}
<dl>
<dt>Title:
<dd>{{ form.title }}
<dt>Post:
<dd>{{ form.body(cols="35", rows="20") }}
<dt>Category:
<dd>{{ form.category }}
</dl>
<p>
<input type=submit value="Publish">
</form>
The result... this solution correctly uses the Category model as a lookup table and associates the Post rows correctly by writing the Category PK integers to the Posts Category_Id field. Yeeeehaww!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With