Колба "get_or_404", как функция, но с другим кодом состояния - PullRequest
0 голосов
/ 29 октября 2018

Что я знаю:

Мы все знаем, что у колбы есть полезное query.get_or_404, мы можем вызвать его для любого объекта класса и вернуть объект или вызвать ошибку 404, если объект не найден.

Проблема:

У меня очень большое приложение, и я использую эту функцию для своих запросов, но теперь это немного сбивает с толку, когда я отправляю данные во внешний интерфейс и другое приложение, использующее мои API. Когда объект, который они запрашивают, не найден, он возвращает 404, и то же самое происходит и в случае, когда страница не найдена.

Чего я хочу достичь:

Я хотел бы получить осмысленный ответ, отличающийся для каждого не найденного объекта и отличающийся для обычного сообщения об ошибке 404.

Пример:

если у меня есть этот запрос:

user = User.query.get_or_404(id)

если пользователь не найден, я хочу вызвать ошибку HTTP и вернуть сообщение типа user not found

Что я уже пробовал:

    user = User.query.get(id)
    if user:
        #do something
    else 
        return {'status':'01', 'description': 'user not found'} 
        # or raise a http error 

Проблема с этим подходом. Я не могу поддерживать приложение, над которым я работаю, оно потребует от меня изменения везде, где я использовал get_or_404 с этим кодом.

О чем я думаю:

Создание функции типа query.get_or_404, но с другим сообщением о состоянии например, query.get_or_415 и добавить обработчик ошибок для кода HTTP 415, чтобы, если объект не был найден, он мог вернуть {'status':'0message:ge : 'object of the class is not found'}

Как мне этого добиться?

Я проверил эту функцию во Flask, но не смог ее найти

Кто-нибудь с предложениями?

Ответы [ 2 ]

0 голосов
/ 29 октября 2018

На основании этого ответа

Вы можете написать так:

from sqlalchemy.orm import Query

class MyQuery(Query):

  def get_or_415(self, pk):
    instance = self.get(pk)
    if not instance:
      raise HttpException(code=415)
    return instance

Затем вы можете использовать обработку ошибок в колбе , чтобы обработать ваше исключение и ответить так, как вы хотите

0 голосов
/ 29 октября 2018

Как отмечает bereal, вы действительно должны использовать BaseQuery flask-SQLAlchemy и добавлять свои собственные функции оттуда. Я проверю, смогу ли я добавить к этому подходу систему обмена сообщениями.

import json
from flask import Flask, abort, Response
from flask_sqlalchemy import SQLAlchemy, BaseQuery

class CustomBaseQuery(BaseQuery):
    def get_or_415(self, ident):
        model_class_name = ''
        try:
            model_class_name = self._mapper_zero().class_.__name__
        except Exception as e:
            print(e)

        rv = self.get(ident)
        if not rv:
            error_message = json.dumps({'message': model_class_name + ' ' + str(ident) + ' not found'})
            abort(Response(error_message, 415))
        return rv

app = Flask(__name__)
db = SQLAlchemy(app, query_class=CustomBaseQuery)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)

db.create_all()
user = User(username='foo')
db.session.add(user)
db.session.commit()

@app.route('/')
def index():
    User.query.get_or_415(1)
    User.query.get_or_415(2)
    return ''

При переходе к индексу возвращает:

{"message": "User 2 not found"}
...