I have a model that wont create the table in the database as shown below
class Person(db.Model):
__tablename__ = 'persons'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20))
pets = db.relationship('Pet', backref='person')
class Pet(db.Model):
__tablename__ = 'pets'
id = db.Column(db.Integer, primary_key=True)
name=db.Column(db.String(20))
owner_id = db.Column(db.Integer, db.ForeignKey('person.id'),nullable=False)
Might the issue be because the class name and the table name do not match since using the command
db.create_all()
throws an error??
Change this
owner_id = db.Column(db.Integer, db.ForeignKey('person.id'),nullable=False)
to
owner_id = db.Column(db.Integer, db.ForeignKey('persons.id'),nullable=False)
since your table is persons
And give this relationship a different name since you already have a table called pets
pets = db.relationship('Pet', backref='person')
you could for example do this
persons_pets = db.relationship('Pet', backref='person')
Related
I am new to Flask and SQLalchmey. I am trying to crate two tables and establish a manytoone relationship between them.
Here is what I did.
table_hub
class Hub(db.Model):
__tablename__ = 'hub'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(),nullable=False,unique=True)
tbl_vehicle
class vehileMaster(db.Model):
__tablename__ = 'res.vehicle'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
hub_id = db.Column(db.Integer,db.ForeignKey('hub.id'))
hub = db.relationship('Hub')
Here is what I need to achieve,
while creating a new vehicle in table res.vehicle I need to choose a hub from the list of hubs.
I don't know whether what i already did is correct or not.
The standard way of implementing a foreign key relationship would be:
class Hub(db.Model):
__tablename__ = 'hub'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False,unique=True)
vehicles = db.relationship('res.vehicle', backref='hub', lazy=True)
class vehicleMaster(db.Model):
__tablename__ = 'res.vehicle'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False)
hub_id = db.Column(db.Integer, db.ForeignKey('hub.id'))
I have created the following models:
tag_post = db.Table('tag_post',
db.Column('tag_id', db.Integer, db.ForeignKey('tag.id'), primary_key=True),
db.Column('post_id', db.Integer, db.ForeignKey('post.id'), primary_key=True))
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(180))
body = db.Column(db.Text, nullable=False)
tags = db.relationship('Tag', secondary=tag_post, backref=db.backref('posts_associated', lazy="dynamic"))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class Tag(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20))
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
username = db.Column(db.String(64), index=True, unique=True)
email = db.Column(db.String(120), index=True, unique=True)
password_hash = db.Column(db.String(128))
posts = db.relationship('Post', backref='author', lazy='dynamic')
How can I query all the posts tagged with a tag, by using the tag.id?
Thanks in advance
The solution is to use a join.
You want all posts that meet a condition. The query should therefore start with the table Post.
Post.query
Then you bind the table posts with your join table using the two columns that should fit. In this case the column post_id in the tag_post table and id in the Post table. Since you use your association table directly, the columns used are referenced using the name via the attribute c.
Post.query\
.join(tag_post, tag_post.c.post_id == Post.id)
Then you filter the second column of your join table based on your condition.
tag_id = 1
Post.query\
.join(tag_post, tag_post.c.post_id == Post.id)\
.filter(tag_post.c.tag_id == tag_id)
Since you want all posts and not just one, close the request with all().
tag_id = 1
tagged_posts = Post.query\
.join(tag_post, tag_post.c.post_id == Post.id)\
.filter(tag_post.c.tag_id == tag_id)\
.all()
The following is a detailed query with the same result, which also includes the third table.
tag_id = 1
tagged_posts = Post.query\
.join(tag_post, tag_post.c.post_id == Post.id)\
.join(Tag, tag_post.c.tag_id == Tag.id)\
.filter(Tag.id == tag_id)\
.all()
The id is associated with the postID. How can I get the contact information and comment information of that id when I enter the id(/postComments/id)?
I'm getting an internal error...
class posts(db.Model):
__tablename__ = "posts"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100))
postName = db.Column(db.String(100))
postDescription = db.Column(db.String(500))
postLike = db.Column(db.Integer)
class postComment(db.Model):
__tablename__ = "postComment"
id = db.Column(db.Integer, primary_key=True)
postID = db.Column(db.Integer)
senderName = db.Column(db.String(20))
commentPost = db.Column(db.String(300))
#app.route('/postComments/<id>',methods=['GET'])
def get_comment_post(id):
userList = posts.query\
.join(postComment, posts.id == postComment.postID)\
.add_columns(posts.id, posts.name, posts.postDescription, postComment.commentPost, postComment.senderName)\
.filter(posts.id == id)
Modify your models (and perform migrations) to allow reference for foreign keys:
class postComment(db.Model):
__tablename__ = "postComment"
id = db.Column(db.Integer, primary_key=True)
postID = db.Column(db.Integer, db.ForeignKey("posts.id")) # <--- Set to Foreign Key
senderName = db.Column(db.String(20))
commentPost = db.Column(db.String(300))
# Establish relationship
post = db.Relationship("posts", backref="postComment") # <--- backref makes this relationship available in the other class
# This should get simpler...
#app.route('/postComments/<id>',methods=['GET'])
def get_comment_post(id):
# Get the comment based on id
my_comment = postComment.query.get(id)
# Get the post associated with that comment
my_post = my_comment.post
# It looks like you're doing an intricate data transformation.
# Do that here...
# Also, for debugging, consider using the following print statements
print(my_comment.__dict__)
print(my_post.__dict__)
Consider reading this slightly more detailed explanation for establishing relationships.
How to reduce the amount of data in the related table when editing and inserting item form in Flask-admin.
In my related tables more than 500,000 records ...
And the flask-admin uploads all the data in the associated drop-down input (example film).... and can not do it.
I created my model mysql innodb through SQLAlchemy.
I can load the data in the parts table? or disable the loading of related data
class LfMailerQueue(db.Model):
__tablename__ = 'lf_mailer_queue'
mail_id = db.Column(db.Integer, primary_key=True)
template_id = db.Column(db.ForeignKey(u'lf_mailer.id'))
user_id = db.Column(db.ForeignKey(u'modx_user_attributes.internalKey'), index=True)
film_id = db.Column(db.ForeignKey(u'modx_lfvideo_items.id'), index=True)
email = db.Column(db.String(255))
fullname = db.Column(db.String(255))
status = db.Column(db.Integer, nullable=False, server_default=db.FetchedValue())
film = db.relationship(u'ModxLfvideoItem', primaryjoin='LfMailerQueue.film_id == ModxLfvideoItem.id', backref=u'lf_mailer_queues')
template = db.relationship(u'LfMailer', primaryjoin='LfMailerQueue.template_id == LfMailer.id', backref=u'lf_mailer_queues')
user = db.relationship(u'ModxUserAttribute', primaryjoin='LfMailerQueue.user_id == ModxUserAttribute.internalKey', backref=u'lf_mailer_queues')
class ModxLfvideoItem(db.Model):
__tablename__ = 'modx_lfvideo_items'
id = db.Column(db.Integer, primary_key=True)
group = db.Column(db.String(255), nullable=False, unique=True)
def __str__(self):
return self.group
....
class ModxUserAttribute(db.Model):
....
I'm working on building a recipe database. In this, there are ingredients (like onions, carrots, etc) and modifiers (like diced, peeled, etc) which are in part of ModifiedIngredients which is part of a recipe. My models.py is as follows:
from app import db
modifiers = db.Table('modifiers',
db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id')),
db.Column('modifier', db.Integer, db.ForeignKey('modifier.id'))
)
modified_ingredients = db.Table('modified_ingredients',
db.Column('recipe', db.Integer, db.ForeignKey('recipe.id')),
db.Column('modified_ingredient', db.Integer, db.ForeignKey('modified_ingredient.id'))
)
class Recipe(db.Model):
__tablename__ = 'recipe'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(256))
description = db.Column(db.Text)
directions = db.Column(db.Text)
prep_time = db.Column(db.Integer)
cook_time = db.Column(db.Integer)
image = db.Column(db.LargeBinary())
ingredients = db.relationship('modified_ingredient', secondary=modified_ingredients)
class Ingredient(db.Model):
__tablename__ = 'ingredient'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), index=True, unique=True)
class Modifier(db.Model):
__tablename__ = 'modifier'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(30), index=True, unique=True)
class ModifiedIngredient(db.Model):
__tablename__ = 'modified_ingredient'
id = db.Column(db.Integer, primary_key=True)
amount = db.Column(db.Integer)
unit = db.Column(db.String(20))
ingredients = db.relationship('ingredient', backref='ingredient', lazy='dynamic')
modifiers = db.relationship('Modifier', secondary=modifiers,
backref=db.backref('modifiers', lazy='dynamic'), lazy='dynamic')
recipe = db.Column(db.Integer, db.ForeignKey('recipe.id'))
However, if I open up a shell and enter in something like "onion = models.Ingredient(name='Onion')" I get the error:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Original exception was: relationship 'ingredients' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)
I'm not exactly sure where my setup is going wrong.
Thanks.
if i'm reading the error message correctly then
ingredients = db.relationship('modified_ingredient', secondary=modified_ingredients)
should become
ingredients = db.relationship('ModifiedIngredient', secondary=modified_ingredients)
Note in the error message:
Original exception was: relationship 'ingredients' expects a class or a mapper argument (received: <class 'sqlalchemy.sql.schema.Table'>)
If it expects a class, give it a class :)