Ошибка при записи данных в БД

Я пытаюсь записать в таблицу данные, внизу код из файлов. Отношения в бд one-to-many. One user, many documents. views.py Функция, которая обрабатывает запрос создания новой записи в БД

@aiohttp_jinja2.template('document_edit.html')
async def add_document(request) -> Dict[str, str]:
    """Записывает данные в бд"""
    if request.method == 'POST':
        async with request.app['db'].acquire() as conn:
            data = await request.post()
            try:
                await db.add_document(conn=conn, new_document=data)
            except db.AddNewFileProblem as e:
                raise web.HTTPNotFound(text=str(e.message))
            location = request.app.router['get_document_list'].url_for()
            raise web.HTTPFound(location=location)
    return {'document': ''}

db.py

import aiopg.sa
from sqlalchemy import (
    MetaData, Table, Column, ForeignKey,
    Integer, String, DateTime
)
from datetime import datetime

meta = MetaData()

user = Table(
    'user', meta,

    Column('id', Integer, primary_key=True),
    Column('username', String(200), nullable=False),
    Column('password_hash', String(100), nullable=False)
)

document = Table(
    'document', meta,

    Column('id', Integer, primary_key=True),
    Column('file_name', String(200), nullable=False),
    Column('publish_date', DateTime, nullable=False),
    Column('url', String(200), nullable=False),

    Column('user_id',
           Integer,
           ForeignKey('user.id', ondelete='CASCADE'))
)


async def init_pg(app):
    conf = app['config']['postgres']
    engine = await aiopg.sa.create_engine(
        database=conf['database'],
        user=conf['user'],
        password=conf['password'],
        host=conf['host'],
        port=conf['port'],
        minsize=conf['minsize'],
        maxsize=conf['maxsize'],
    )
    app['db'] = engine


async def close_pg(app):
    app['db'].close()
    await app['db'].wait_closed()


class AddNewFileProblem(Exception):
    """Возникли проблемы при добавлении записи в БД"""

    def __init__(self, message):
        self.message = message


async def add_document(conn, new_document):
    """Добавляет элемент в БД"""
    await conn.execute(document.insert(), [
        {'file_name': str(new_document.get('filename')),
         'publish_date': datetime.now(),
         'url': str(new_document.get('url')),
         'user_id': int(new_document.get('user_id'))}
    ])

routes.py

from .views import add_document


def setup_routes(app):
    app.router.add_get('/document/new/', add_document, name='add_document')
    app.router.add_post('/document/new/', add_document, name='add_document')

Отрисовка страницы происходит, и передача данных в тело функции тоже. Но дальше выдается ошибка.

Error handling request
Traceback (most recent call last):
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/aiohttp/web_protocol.py", line 418, in start
    resp = await task
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/aiohttp/web_app.py", line 458, in _handle
    resp = await handler(request)
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/aiohttp_jinja2/__init__.py", line 122, in wrapped
    context = await coro(*args)
  File "/home/ian/Passion/testing_aiohttp/test_web_server/views.py", line 46, in add_document
    await db.add_document(conn=conn, new_document=data)
  File "/home/ian/Passion/testing_aiohttp/test_web_server/db.py", line 82, in add_document
    'user_id': int(new_document.get('user_id'))}
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/aiopg/sa/connection.py", line 97, in _execute
    compiled_parameters = [compiled.construct_params(dp)]
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/aiopg/sa/engine.py", line 19, in construct_params
    pd = super().construct_params(params, _group_number, _check)
  File "/home/ian/Passion/testing_aiohttp/venv/lib/python3.7/site-packages/sqlalchemy/sql/compiler.py", line 693, in construct_params
    code="cd3x",
sqlalchemy.exc.InvalidRequestError: A value is required for bind parameter 'id' (Background on this error at: http://sqlalche.me/e/cd3x)

Если перейти по ссылке, то описывается случай, который вообще не помогает. Гуглил sqlalchemy one-to-many - там все примеры описаны в декларативном стиле(через классы), что не рекомендуется в документации aiohttp.

It is possible to configure tables in a declarative style ... But it doesn’t give much benefits later on. SQLAlchemy ORM doesn’t work in asynchronous style and as a result aiopg.sa doesn’t support related ORM expressions such as Question.query.filter_by(question_text='Why').first() or session.query(TableName).all().

Как создать отношения one-to-many не в декларативном стиле или какую ошибку я допускаю, определяя БД таким образом?


Ответы (1 шт):

Автор решения: Ian

Ошибка оказалась простая
Должно быть в файле db.py

async def add_document(conn, new_document):
    await conn.execute(
        document.insert().values(
            {'file_name': str(new_document.get('file_name')),
             'publish_date': datetime.now(),
             'url': str(new_document.get('url')),
             'user_id': int(new_document.get('user_id'))}))

Так написано в официальной документации SQLAlchemy

→ Ссылка