Отношение один-ко-многим с wtforms_alchemy.ModelFieldList не обновляет дочерние элементы - PullRequest
0 голосов
/ 25 апреля 2018

Ниже приведена форма, которая заполняет пустой родительский объект и создает его дочерние элементы.Необходимо было вручную вызвать ModelFormField, что было незначительным раздражением.Это прекрасно работает.Однако, когда я использую форму для обновления , обновляется только объект - дочерние объекты создаются свежими.

Как правильно распространить обновление для дочерних элементов вэто рамки?По сути, я хотел бы, чтобы два приведенных ниже оператора печати печатали одно и то же.Я был бы особенно признателен, если бы форма создавала (удаляла) дочерние элементы, если у формданных были дополнительные (отсутствующие) данные для дочерних элементов.

from multidict import MultiDict
from sqlalchemy import Column, ForeignKey, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

from wtforms_alchemy import ModelFieldList, ModelForm, ModelFormField

Base = declarative_base()

class Child(Base):
  __tablename__ = "child"
  id = Column(Integer, primary_key=True)
  name = Column(String)
  parent_id = Column(Integer, ForeignKey("parent.id"))

class Parent(Base):
  __tablename__ = "parent"
  id = Column(Integer, primary_key=True)
  name = Column(String)
  children = relationship(Child)

class ChildForm(ModelForm):
  class Meta:
    model = Child

class ParentForm(ModelForm):
  class Meta:
    model = Parent
  children = ModelFieldList(ModelFormField(ChildForm))  # annoyed!

engine = create_engine("sqlite://")
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()

# Form data
formdata = MultiDict({"name": "Foo", "children-0-name": "hotdog"})

# Create initial object
question = Parent()
form = ParentForm(formdata, obj=question)
form.populate_obj(question)
if not form.validate():
  raise RuntimeError(form.errors)
session.add(question)
session.commit()

# prints: "(1, 1)"
print((question.id, question.children[0].id))


# Retrieve object and update with same data
question_get = session.query(Parent).get(question.id)
form = ParentForm(formdata, obj=question_get)
form.populate_obj(question_get)
if not form.validate():
  raise RuntimeError(form.errors)
session.add(question_get)
session.commit()

# prints: "(1, 2)", want it to print the same as above
print((question_get.id, question_get.children[0].id))

1 Ответ

0 голосов
/ 02 мая 2018

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

--- orig.py 2018-05-01 20:51:09.000000000 -0700
+++ fixed.py    2018-05-01 20:56:16.000000000 -0700
@@ -4,6 +4,7 @@
 from sqlalchemy.orm import relationship
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy import create_engine
+from wtforms import IntegerField

 from wtforms_alchemy import ModelFieldList, ModelForm, ModelFormField

@@ -24,6 +25,7 @@
 class ChildForm(ModelForm):
   class Meta:
     model = Child
+  id = IntegerField()  # Optional field used in update operations.

 class ParentForm(ModelForm):
   class Meta:
@@ -53,7 +55,11 @@

 # Retrieve object and update with same data
 question_get = session.query(Parent).get(question.id)
-form = ParentForm(formdata, obj=question_get)
+child_id = question_get.children[0].id
+formdata_update = MultiDict({"name": "Foo",
+                             "children-0-id": child_id,
+                             "children-0-name": "pizza"})
+form = ParentForm(formdata_update, obj=question_get)
 form.populate_obj(question_get)
 if not form.validate():
   raise RuntimeError(form.errors)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...