简体   繁体   English

在SQLAlchemy多对多关联表中存储对其他行的引用

[英]Storing reference to other rows in SQLAlchemy Many-to-Many association table

I'm working on a project in SQLAlchemy. 我正在SQLAlchemy中的一个项目。 Let's say (to simplify the problem) there are three tables at play-- Blog_posts, Users, and Users_daily_posts. 我们说(为简化问题),有三个表在起作用-Blog_posts,Users和Users_daily_posts。 The first two look like this: 前两个看起来像这样:

class Blog_posts(db.Model):
    __tablename__ = 'Blog_posts'
    post_id = db.Column(db.Integer(), primary_key = True)
    date = db.Column(db.Integer())
    creator_id = db.Column(db.Integer())

class Users(db.Model):
    __tablename__ = 'Users'
    user_id = db.Column(db.Integer(), primary_key = True)
    likes = db.Column(db.Integer())
    users_daily_posts = db.relationship('Users_daily_posts', lazy='dynamic', backref=db.backref('user', lazy='dynamic'))

For the third table, the expectation is that it has as primary keys a user_id and a date (say date is an integer), a column for likes, and a column that should keep track of which blog posts are on that particular date. 对于第三张表,期望它具有一个user_id和一个日期(例如date是一个整数),一个表示喜欢的列以及一个应该跟踪该特定日期的博客帖子作为主键。 When a post is liked, the like propagates to this table and to the Users table, but Blog_posts does not store it. 当喜欢某个帖子时,类似内容会传播到该表和Users表,但Blog_posts不会存储它。 I originally thought date should be a foreign key, but it turns out there is a uniqueness constraint on this in the original table, and they won't be unique in the Blog_posts table, so I would think the design would be something like: 我最初以为date应该是一个外键,但是事实证明在原始表中对此有一个唯一性约束,并且在Blog_posts表中它们不会是唯一的,因此我认为设计应该是这样的:

class Users_daily_posts(db.Model):
    __tablename__ = 'Users_daily_posts'
    user_id = db.Column(db.Integer(), db.ForeignKey('Users.user_id', ondelete="CASCADE"), primary_key = True)
    date = db.Column(db.Integer(), primary_key = True)
    likes = db.Column(db.Integer())
    blog_posts = ?

For blog_posts, I tried: 对于blog_posts,我尝试过:

db.relationship('Blog_posts', lazy='dynamic', backref=db.backref('posts', lazy='dynamic'))

thinking that this might allow me to add a list of blog posts, but this gives the error: 认为这可能允许我添加博客文章列表,但这会导致错误:

ArgumentError: Could not determine join condition between parent/child tables on relationship Users_daily_posts.blog_posts.  Specify a 'primaryjoin' expression.  If 'secondary' is present, 'secondaryjoin' is needed as well.

I've seen a couple of posts about this error, but I really don't understand what the primaryjoin expression would be, as I'm about the furthest you can get from a databases whiz. 我已经看过几篇有关此错误的文章,但我真的不明白primaryjoin表达式是什么,因为我想从数据库专家那里获得最大的信息。 Could somebody explain what the primary join would be and why? 有人可以解释什么是主要联接,为什么? Or at least what I'm doing wrong? 或至少我做错了什么? If there is a different SQLAlchemy idiom that is better suited to this purpose, I'd love to hear about it. 如果有另一个更适合此目的的SQLAlchemy习惯用法,我很想听听。 Thanks so much for your time! 非常感谢您的宝贵时间!

There are many cases that you need an association table between two classes. 在许多情况下,您需要两个类之间的关联表。 But looking at your case, I believe that you need just a column_property or do a simple query is enough. 但是从您的情况来看,我相信您只需要column_property或做一个简单的查询就足够了。

In your case, you will have: 就您而言,您将拥有:

  • Each post have just a one creator or author, so is Many to one relationship; 每个帖子只有一个创建者或作者,因此多对一关系;

  • The "likes" can't no be on users, but you can have a “赞”不能不被用户接受,但是您可以
    column property that count how many likes; 计算有多少喜欢的专栏属性;

  • Finally, "likes" is more related to the visitors and posts. 最后,“喜欢”与访问者和帖子更多相关。 So you 那么你
    will need another model in order to keep information about the 将需要其他模型以保留有关
    visitors. 访客。 And then make a relationship with users. 然后与用户建立关系。

Try this: 尝试这个:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

import datetime

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)

class Blog_post(db.Model):
    __tablename__ = 'Blog_posts'
    post_id = db.Column(db.Integer, primary_key = True)
    creator_id = db.Column(db.Integer, db.ForeignKey('Users.user_id'), nullable=False)
    headline = db.Column(db.String(255), nullable=False)
    date = db.Column(db.Date, nullable=False)
    likes = db.Column(db.Integer)
    def __init__(self, headline, body,creator_id):
        self.headline = headline
        self.creator_id = creator_id
        self.date = datetime.datetime.today() 

class User(db.Model):
    __tablename__ = 'Users'
    user_id = db.Column(db.Integer(), primary_key = True)
    user_name = db.Column(db.String(80), unique=True)
    users_posts = db.column_property(
        db.select([db.func.count(Blog_post.post_id)]).\
            where(Blog_post.creator_id==user_id).\
            correlate_except(Blog_post)
    )
    def __init__(self, user_name):
        self.user_name = user_name

Testing... 测试中...

>>> db.create_all()
>>> u = User('dedeco')
>>> db.session.add(u)
>>> db.session.commit()
>>> 
>>> p = Blog_post('I am dedeco 1','About dedeco 1',u.user_id)
>>> db.session.add(p)
>>> p = Blog_post('I am dedeco 2','About dedeco 2',u.user_id)
>>> db.session.add(p)
>>> p = Blog_post('I am dedeco 3','About dedeco 3',u.user_id)
>>> db.session.add(p)
>>> db.session.commit()
>>> u.users_posts
3

Query: 查询:

>>> d = db.session.query(db.func.count(Blog_post.post_id),db.func.strftime('%d/%m/%Y', Blog_post.date)).filter(Blog_post.creator_id==u.user_id).group_by(db.func.strftime('%d/%m/%Y', Blog_post.date))
>>> d.all()
[(3, u'04/11/2015')]

You can see some information about Many to Many on Sqlalchemy documentation 您可以在Sqlalchemy文档上看到有关多对多的一些信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM