Питонье продолжение: хаки для flask-admin

· На чтение уйдёт 2 минуты · (338 слов)

Завершался второй день знакомства с flask и flask-admin. Сегодня всё обстоит получше. Немножко повозившись, вынес конфиг, app и db в __init__.py, за счёт этого появилась возможность разбить приложение на несколько модулей. На работе сделать этого не успел, пришлось немножко повозиться в выходные. Потенциально такая разбивка может позволить создавать приложения довольно-таки большого размера. Главное, не сойти б с ума от __init__'ов: после Java есть желание создавать десятки package'й, а значит - и десятки __init__.py файлов.

В генерацию формы получилось вклиниться лишь следующим образом, чтобы отобразить только модули типа GK, подходящие данному объекту.

def edit_form(self, obj=None):
    form = super().edit_form(obj)
    form.gk.query_factory = lambda: self.session.query(Module).filter(Module.usage == 'GK', Module.parent == obj)
    return form

Поскольку приложение по размеру совсем небольшое, я разнёс его, собственно на модели (все в одном файле), вьюшки (тоже засунул всё в один файл), ну а поскольку контроллеров как таковых, тут нет - логика приложения оставлена в основном файле приложения.

Для того, чтобы добавить в приложение возможность задать количество строк на страницу, пришлось воспользоваться ещё одним хаком.

class PageView(sqla.ModelView):
    def _get_list_extra_args(self):
        args = super()._get_list_extra_args()
        new_page_size = request.args.get('max', 0, type=int)
        if new_page_size > 0:
            args.extra_args['max'] = new_page_size
            self.page_size = new_page_size
        return args

Смутно подозреваю, что можно сохранить где-то вьюху, написать "декоратор", который будет следить за этой переменной. Но так мне показалось проще, тем более что я уже немножко поотлаживал фляжку и нашёл этот замечательный _get_list_extra_args, который уже вызывается каждый раз ).

Для того, чтобы реализовать сериализацию в JSON, тоже пришлось воспользоваться хаком. На самом деле, на взгляд джависта, всю работу с JSON стоило бы переписать (слава Jackson и Gson!): jsonify ужасен (хотя бы тем, что из интерактивного питона его не вызвать: working outside of application context), собственный маршалинг написать не очень-то и просто. В итоге пришлось написать собственный метод as_json(), который сначала делает из объекта dict, а потом уже его сериализует (причём при помощи обычного json.dumps — не использовал jsonify из Flask). В целом, DjangoJSONEncoder вроде бы выглядит поинтереснее… Наверное, в следующий рзз возьму Django для опытов, тем более что какие-то начальные навыки питона я уже обрёл, и даже уроки почитал )).

Полезное