Flask / SQLAlchemy: несовместимый тип коллекции: None не похож на список

1

Я сбит с толку. Что не так?

У меня две модели и отношение много к одному.

Я создал форму Boss_add для добавления босса в базу данных. Но ничего не работает!

Мои модели:

class User(UserMixin, db.Model):
  __tablename__ = 'users'

  id = db.Column(db.Integer, primary_key=True)
  username = db.Column(db.String(20), unique=True, nullable=False)
  boss_id = db.Column(db.Integer, db.ForeignKey('boss.id'))
  boss = db.relationship('Boss', back_populates='users')

class Boss(db.Model):
  __tablename__ = 'boss'

  id = db.Column(db.Integer, primary_key=True)
  short_name = db.Column(db.String(64))
  users = db.relationship('User', back_populates='boss')

Мои формы:

from flask_wtf import FlaskForm
from wtforms import IntegerField, StringField, PasswordField, BooleanField, SubmitField, DateField
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
from wtforms.ext.sqlalchemy.fields import QuerySelectField, QuerySelectMultipleField
from app.models import User, Boss

class Boss_add(FlaskForm):
  short_name = StringField('Short name', validators=[DataRequired()])
  users = QuerySelectMultipleField('Users', query_factory=lambda: db.session.query(User), get_pk=lambda a: a.id, get_label=lambda a: a.username, allow_blank=True)
  button = SubmitField('Add')

Мой взгляд:

@app.route('/boss_add/', methods=['GET', 'POST'])
@login_required
def boss_add():
  form = Boss_add()
  if request.method == 'POST' and form.validate():
    print("FIRST PRINT: ", type(form.users.data))   # DEBUG PRING 1
    print("SECOND PRINT: ", form.data)              # DEBUG PRING 2
    boss = Boss(short_name=form.short_name.data,
                users=form.users.data)
    db.session.add(boss)
    db.session.commit()
  return render_template('boss_edit.html', form=form)

Мой шаблон:

<html><head><title>Boss add</title></head>
<body>
    <form action="" method="post" novalidate>
        {{ form.hidden_tag() }}
<p>
            {{ form.short_name.label }}<br>
            {{ form.short_name }}
        </p>
        <p>
            {{ form.users.label }}<br>
            {{ form.users }}
        </p>
        <p>{{ form.button() }}</p>
</form>
</body></html>

DEBUG PRINT:

Если я выбираю пользователя в списке

FIRST PRINT: <class 'list'>
SECOND PRINT: {'short_name': '1111', 'users': [<User 1>], 'button': True, 'csrf_token': 'IjYxNDFhYzYyOGNlMGMzYTliNGYxOTA2NDYxYmE1ZDZkZmVjMjVkNDUi.DqPGxg.63Z-bKn8dgRGLNLxgMLUEzKMa15'}

Если я не выбрал пользователя в списке

FIRST PRINT: <class 'list'>
SECOND PRINT: {'short_name': '1111', 'users': [], 'button': True, 'csrf_token': 'IjYxNDFhYzYyOGNlMGMzYTliNGYxOTA2NDYxYmE1ZDZkZmVjMjVkNDUi.DqPGxg.63Z-bKn8dgRGLNLxgMLUEzKMa15'}

ТипError: Несовместимый тип коллекции: None не является списком

Как это возможно? Тип: список, но по ошибке: Нет.

Если это важно, мои библиотеки:

alembic          1.0.0  
Click            7.0    
Flask            1.0.2  
Flask-Login      0.4.1  
Flask-Migrate    2.2.1  
Flask-SQLAlchemy 2.3.2  
Flask-WTF        0.14.2 
itsdangerous     0.24   
jdcal            1.4    
Jinja2           2.10   
Mako             1.0.7  
MarkupSafe       1.0    
pip              18.1   
pkg-resources    0.0.0  
python-dateutil  2.7.3  
python-editor    1.0.3  
setuptools       40.4.3 
six              1.11.0 
SQLAlchemy       1.2.12 
Werkzeug         0.14.1 
wheel            0.32.1 
WTForms          2.2.1  

Проследить:

Traceback (most recent call last):
  File "/lib/python3.7/site-packages/flask/app.py", line 2292, in wsgi_app
    response = self.full_dispatch_request()
  File "/lib/python3.7/site-packages/flask/app.py", line 1815, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/lib/python3.7/site-packages/flask/app.py", line 1718, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/lib/python3.7/site-packages/flask/_compat.py", line 35, in reraise
    raise value
  File "/lib/python3.7/site-packages/flask/app.py", line 1813, in full_dispatch_request
    rv = self.dispatch_request()
  File "/lib/python3.7/site-packages/flask/app.py", line 1799, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/lib/python3.7/site-packages/flask_login/utils.py", line 261, in decorated_view
    return func(*args, **kwargs)
  File "/src/app/routes.py", line 313, in client_add
    users=form.users.data)
  File "<string>", line 4, in __init__
  File "/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 424, in _initialize_instance
    manager.dispatch.init_failure(self, args, kwargs)
  File "/lib/python3.7/site-packages/sqlalchemy/util/langhelpers.py", line 66, in __exit__
    compat.reraise(exc_type, exc_value, exc_tb)
  File "/lib/python3.7/site-packages/sqlalchemy/util/compat.py", line 249, in reraise
    raise value
  File "/lib/python3.7/site-packages/sqlalchemy/orm/state.py", line 421, in _initialize_instance
    return manager.original_init(*mixed[1:], **kwargs)
  File "/lib/python3.7/site-packages/sqlalchemy/ext/declarative/base.py", line 747, in _declarative_constructor
    setattr(self, k, kwargs[k])
  File "/lib/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 229, in __set__
    instance_dict(instance), value, None)
  File "/lib/python3.7/site-packages/sqlalchemy/orm/attributes.py", line 1042, in set
    given, wanted))
TypeError: Incompatible collection type: None is not list-like
  • 0
    Пожалуйста, form.users.data полную трассировку, хотя проблема, скорее всего, в users=form.users.data , где form.users.data - None .
Показать ещё 7 комментариев
Теги:
sqlalchemy
flask-sqlalchemy

1 ответ

0
Лучший ответ

Ну, проблема в том, что вы пытаетесь заполнить users на модели Boss с помощью None value

Попробуйте это на ваш view:

boss = Boss(short_name=form.short_name.data)
if form.users.data:
    for each in form.users.data: boss.users.append(each)
db.session.add(boss)
db.session.commit()

Он должен работать очень хорошо

Есть шанс, что этот тоже работает

boss = Boss(short_name=form.short_name.data, users=form.users.data if form.users.data else [])
  • 0
    @ IljaEverilä Как? Почему?
  • 0
    Не! Более того, как видно из модели и формы, значение может быть пустым, и все проверяется. Ошибка не меняется, оставьте меня пустым или выберите пользователя с именем пользователя. У меня много-много в проекте, проблем не было, и ... вот ситуация.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню