peewee IntegrityError:唯一约束失败:userpost.user_id,userpost.post_id

时间:2020-05-31 17:35:07

标签: python peewee

我有以下模型:Post,Tag,User,UserPost和PostTag

我希望一个帖子具有多个标签,而用户希望多个帖子

我正在尝试通过点击此端点/edit/<post-slug-here>/来更新帖子,但收到此错误IntegrityError: UNIQUE constraint failed: userpost.user_id, userpost.post_id,我认为peewee会增加主键ID,我不确定为什么会这样或我没有正确理解某些东西,感谢您的帮助

models.py

from datetime import datetime
from app import database, app
from playhouse.sqlite_ext import CharField, DateTimeField, BooleanField, TextField, ForeignKeyField, FTSModel, SearchField
from peewee import Model


class BaseModel(Model):
    class Meta:
        database = database

class Tag(BaseModel):
    name = CharField()

class Post(BaseModel):
    title = CharField()
    slug = CharField(unique=True)
    content = TextField()
    published = BooleanField(index=True)
    timestamp = DateTimeField(default=datetime.now, index=True)

    @property
    def get_tags(self):
        """
        Returns string array of all tags for a post
        """
        tag_list  = []
        query = Tag.select().join(PostTag).where(PostTag.post == self)
        for newtag in query:
            tag_list.append(newtag.name)
        return ','.join(tag_list)


    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = re.sub('[^\w]+', '-', str(self.title).lower()).strip('-')
        ret = super(Post, self).save(*args, **kwargs)
        return ret

class User(BaseModel):
    username = CharField()
    email = CharField(unique=True)
    password = CharField(unique=True)
    timestamp = DateTimeField(default=datetime.now, index=True)


class UserPost(BaseModel):
    user = ForeignKeyField(User, backref='userposts' )
    post = ForeignKeyField(Post, backref='userposts' )
    class Meta:
        indexes = (
            (('user', 'post'), True),
        )


class PostTag(BaseModel):
    post = ForeignKeyField(Post, backref='posttags')
    tag = ForeignKeyField(Tag, backref='posttags')

    class Meta:
        indexes = (
            (('post', 'tag'), True),
        )

routes.py

from flask import render_template, flash, redirect, url_for, session
from sqlalchemy.exc import IntegrityError
from app.models import *
from peewee import *

# get the user from the session
def get_current_user():
    if session.get('logged_in'):
        return User.get(User.id == session['user_id'])


@app.route('/edit/<string:slug>/', methods=['GET', 'POST'])
@login_required
def edit(slug):
    post = get_object_or_404(Post, Post.slug == slug)
    return _create_or_edit(post, 'edit.html')

def _create_or_edit(post, template):
    if request.method == 'POST':
        post.title = request.form.get('title') or ''
        post.content = request.form.get('content') or ''
        post.tags = post.get_tags or ''
        post.published = request.form.get('published') or False
        if not (post.title and post.content):
            flash('Title and Content are required.', 'danger')
        else:
            try:
                with database.atomic()
                    if post.tags != '':
                        tag_names = post.get_tags.split(',')
                        for name in tag_names:
                            tag = Tag.create(name=name)
                            tag.save()
                            post_tag = PostTag.create(
                                post = post,
                                tag = tag
                            )
                            post_tag.save()
                    UserPost.create(
                        user = get_current_user(),
                        post= post
                    )
                    post.save()
            except IntegrityError:
                flash('Error: this title is already in use.', 'danger')
                raise
            else:
                flash('Post saved successfully.', 'success')
                if post.published:
                    return redirect(url_for('detail', slug=post.slug))
                else:
                    return redirect(url_for('edit', slug=post.slug))
    return render_template(template, post=post)

1 个答案:

答案 0 :(得分:2)

您似乎要保存相同的用户+帖子组合。换句话说,您正在插入一个用户<->帖子链接,但是该用户已经链接到该帖子,因此约束失败。

相关问题