Невозможно протестировать простой класс данных модели sqlalchemy: «Сопоставленный класс Mapper не смог собрать столбцы первичного ключа для сопоставленной таблицы»

#python #sqlalchemy #flask-sqlalchemy

Вопрос:

У меня есть простой скрипт на Python ( models.py ) для создания приложения Flask-SQLAlchemy и простого класса данных sqlalchemy (ссылка здесь), который выглядит следующим образом:

 from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///test.db"
db = SQLAlchemy(app)

class User(db.Model):

    __tablename__ = 'user'

    user_id: db.Column(db.Integer, primary_key=True)
    user_url: db.Column(db.String(2083), unique=True, nullable=False)
    username: db.Column(db.String(80), unique=True, nullable=False)
    avatar_url: db.Column(db.String(2083), unique=True, nullable=False)
 

Затем я написал чрезвычайно простой скрипт pytest, который выглядит следующим образом, следуя примеру создания приложения Flask-SQLAlchemy отсюда:

 import pytest

from models import User
from models import db

def test_basic():

    db.create_all()

    u1 = User(1, "http://testuserurl", "charliebrown", "http://avatarurl")

    assert u1.user_id == 1
    assert u1.user_url == "http://testuserurl"
    assert u1.username == "charliebrown"
    assert u1.avatar_url == "http://avatarurl"
 

Этот тест сразу же завершается неудачей в строке «от пользователя импорта моделей» с сообщением:

sqlalchemy.exc.ArgumentError: Пользователь сопоставленного класса Mapper->пользователь не смог собрать столбцы первичного ключа для сопоставленной таблицы «пользователь»

Я не понимаю этого сообщения (особенно учитывая, что я действительно указываю primary_key в User ). Какая-нибудь помощь, пожалуйста?

Комментарии:

1. В foo: Bar баре есть аннотация. Вместо этого вам нужны атрибуты класса, поэтому назначения.

Ответ №1:

Попробуйте использовать = вместо :

Подобный этому:

 class User(db.Model):

    __tablename__ = 'user'

    user_id = db.Column(db.Integer, primary_key=True)
    user_url = db.Column(db.String(2083), unique=True, nullable=False)
    username = db.Column(db.String(80), unique=True, nullable=False)
    avatar_url = db.Column(db.String(2083), unique=True, nullable=False)
 

Комментарии:

1. Голосовали как есть, но это сделало бы этот ответ лучше, если бы вы упомянули разницу между ними и почему один работает, но не другой.

2. Ах, я запутался с декоратором dataclass, который использует назначение foo: bar! docs.python.org/3/library/dataclasses.html