Получение peewee IntegrityError для уникального ограничения только через API

Получение IntegrityError при попытке обновить записи в моей базе данных PostgreSQL с помощью peewee. Однако это происходит только тогда, когда я пробую метод HTTP PUT.

Использование Flask и Flask-Restful для создания ресурсов API. ПОЛУЧИТЬ, УДАЛИТЬ в один пост в блоге работает отлично. Сообщение в корзину работает отлично

Я могу запустить точно такой же код через REPL, и он отлично работает. Что еще более странно, так это то, что API внезапно сломался, я вчера тестировал эту функцию, и все было в порядке. Теперь не могу определить, что изменилось.

Вот моя модель крошки в models.py


class BlogPost(Model):
    title = CharField(default='', unique=True)
    content = TextField(default='')
    created = DateTimeField(default=datetime.datetime.now)

    class Meta:
        database = DATABASE

Вот ресурс для одного сообщения блога в resources.blogposts.py.


class BlogPost(Resource):
    def __init__(self):
        self.reqparse = reqparse.RequestParser()
        self.reqparse.add_argument(
            'title',
            required=False,
            help='No title provided',
            location=['form', 'json']
        )
        self.reqparse.add_argument(
            'content',
            required=False,
            nullable=True,
            location=['form', 'json'],
            default=''
        )
        super().__init__()

    @marshal_with(blogpost_fields)
    def get(self, id):
        return (blogpost_or_404(id))

    @marshal_with(blogpost_fields)
    @auth.login_required
    def put(self, id):
        args = self.reqparse.parse_args()
        try:
            blogpost = models.BlogPost.get(models.BlogPost.id==id)
        except models.BlogPost.DoesNotExist:
            return make_response(json.dumps(
                    {'error': 'That blogpost does not exist or is not editable'}
                ), 403)
        else:
            query = blogpost.update(**args)
            query.execute()
            blogpost = (blogpost_or_404(id))
            return (blogpost, 200, {
                'Location': url_for('resources.blogposts.blogpost', id=id)
               })

    @auth.login_required
    def delete(self, id):
        try:
            blogpost = models.BlogPost.select().where(
                models.BlogPost.id==id
            ).get()
        except models.BlogPost.DoesNotExist:
            return make_response(json.dumps(
                    {'error': 'That blogpost does not exist or is not editable'}
                ), 403)
        else:
            query = blogpost.delete().where(models.BlogPost.id==id)
            query.execute()
            return '', 204, {'Location': url_for('resources.blogposts.blogposts')}

blogposts_api = Blueprint('resources.blogposts', __name__)
api = Api(blogposts_api)
api.add_resource(
    BlogPost,
    'api/v1/blogposts/<int:id>',
    endpoint='blogpost'
)

Если я выполню GET для http://localhost:8000/api/v1/blogposts/8 Я получаю в таблице свой единственный пост в блоге (для проверки я удалил все, кроме этого)


{
    "id": 8,
    "title": "Test3",
    "content": "This is to test changes to BlogPost 1",
    "created": "Wed, 19 Jun 2019 12:44:31 -0000"
}

Однако, если я PUT на тот же URL-адрес, я получаю уникальное ограничение. У меня определенно нет записи в базе данных с таким заголовком.


{
    "title": "9sdnfsudngfisdngondasgjns",
    "content": "lkbksigsndignsoidugnlis",
}

Я могу сделать это в REPL, и он отлично работает, это должно быть то же самое, что и то, что я делаю выше:


blogpost = models.BlogPost.get(models.BlogPost.id==8)
blogpost.update(
    title="9sdnfsudngfisdngondasgjns",
    content="lkbksigsndignsoidugnlis"
)
blogpost.execute()

Фактическая ошибка:

peewee.IntegrityError: повторяющееся значение ключа нарушает уникальное ограничение «blogpost_title» ПОДРОБНОСТЬ: Ключ (название) = (9sdnfsudngfisdngondasgjns) уже существует.

РЕДАКТИРОВАТЬ: перед ошибкой peewee psycopg2 также выдает эту ошибку:

UniqueViolation: повторяющееся значение ключа нарушает уникальное ограничение «user_username_key» ПОДРОБНОСТЬ: Ключ (имя пользователя) = (9sdnfsudngfisdngondasgjns) уже существует.


person HellowThar    schedule 19.06.2019    source источник


Ответы (1)


Это действительно странно, но я понял это. Мне пришлось обновить мой метод put, чтобы он имел тот же синтаксис, что и мой метод удаления. По сути, мне пришлось перейти в контексте к фактическому методу обновления:


@marshal_with(blogpost_fields)
    @auth.login_required
    def put(self, id):
        args = self.reqparse.parse_args()
        try:
            blogpost = models.BlogPost.select().where(
                models.BlogPost.id==id).get()
        except models.BlogPost.DoesNotExist:
            return make_response(json.dumps(
                    {'error': 'That blogpost does not exist or is not editable'}
                ), 403)
        else:
            query = blogpost.update(**args).where(models.BlogPost.id==id)
            query.execute()
            blogpost = (blogpost_or_404(id))
            return (blogpost, 200, {
                'Location': url_for('resources.blogposts.blogpost', id=id)
               })

    @auth.login_required
    def delete(self, id):
        try:
            blogpost = models.BlogPost.select().where(
                models.BlogPost.id==id).get()
        except models.BlogPost.DoesNotExist:
            return make_response(json.dumps(
                    {'error': 'That blogpost does not exist or is not editable'}
                ), 403)
        else:
            query = blogpost.delete().where(models.BlogPost.id==id)
            query.execute()
            return '', 204, {'Location': url_for('resources.blogposts.blogposts')}

person HellowThar    schedule 20.06.2019