modulenotfounderror form example bootstrap python flask sqlalchemy flask-wtforms

python - example - ¿Actualizar las relaciones de muchos a muchos usando Flask, SQLAlchemy y WTForms?



python web form (1)

Quiero crear un formulario para relaciones de muchos a muchos usando Flask, SQLAlchemy y WTForms que representa estos modelos:

personaddress = db.Table(''personaddress'', db.Column(''person'', db.Integer, db.ForeignKey(''person.id'')), db.Column(''address'', db.Integer, db.ForeignKey(''address.id'')) ) class Person(db.Model): __tablename__ = "person" id = db.Column(Integer, primary_key=True) name = db.Column(String, nullable=False) addresses = db.relationship(''Address'', secondary=personaddress, backref=db.backref(''person'', lazy=''dynamic'')) class Address(db.Model): __tablename__ = "address" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String, nullable=False)

Requerimientos

Ahora quiero crear una sola página que contenga formularios para lograr lo siguiente:

  • agregar / editar / borrar una persona
  • agregar / editar / borrar una dirección
  • agregar / editar / eliminar una relación entre una persona y una dirección

Requisito importante: al usar QuerySelectField, puedo elegir direcciones existentes para una persona. Pero quiero agregar nuevas direcciones en la misma forma.

He jugado un poco con model_form para los principales modelos y subformularios utilizando FormField para la tabla de unión, pero simplemente no puedo averiguar cómo actualizar todo, incluidas las relaciones de clave externa. La página debe tener un solo botón de envío para todos los formularios y subformularios mostrados.

Preguntas

  1. ¿Cómo se implementan normalmente los requisitos anteriores en Flask?
  2. ¿Es este escenario de muchos a muchos algo que Django puede manejar más fácilmente a través de su interfaz de administración?

También he encontrado algo similar antes. Traté de resolverlo usando model_form, pero no soluciona el problema de agregar nuevas entradas dinámicamente, y me estaba costando mucho usarlo al tratar con las relaciones.

El uso de QuerySelectField en WTForms solo lo ayudará a completar, por ejemplo, un <select> con id, pares de valores correspondientes a las direcciones existentes. Pero todavía se procesa en un formulario html regular en la plantilla.

Al utilizar algún tipo de selección múltiple con la posibilidad de agregar dinámicamente nuevas opciones en la interfaz, puede enviar direcciones adicionales de la misma forma. El punto final se encargará de crear nuevas direcciones si no existen en la base de datos.

El formulario WTForm sería:

from app import db class PersonAddressForm(Form): id = HiddenField(''id'') name = StringField(''Name'') addresses = QuerySelectField(''Addresses'', query_factory=lambda: db.session.query(Address), get_pk=lambda a: a.id, get_label=lambda a: a.name) # Custom validate def validate(self): # ... custom validation return True

Y la ruta algo como:

# ... this will be used to create and update a user @route(''create/<userid>'', methods=["GET"]) def get_user_form(userid): # ... Get the Person user = Person() if userid: # ... if userid supplied, use existing Person object user = Person.query.get(userid) # ... Populate the form person_form = PersonAddressForm(obj=user) # ... return form return render_template(''somepage.html'', form=person_form) @route(''create/<userid>'', methods=["POST"]) def post_person_form(userid): person_form = PersonAddressForm(request.form) if person_form.validate(): # ... Get db object person = db.session.query(Person).get(form.id) # ... Add changes to the object from the form person_form.populate_obj(obj=person_address) # ... Get addresses addresses = form.addresses.raw_data # ... loop over and add to person for address in addresses: # Add or create an address actual_address = db.session.query(Address).get(address.id) # ... check if address is existing if not actual_address: # ... if address not existing, create new one actual_address = Address(address.name) db.session.add(actual_address) # ... Append new or created address to person person.addresses.append(actual_address) # ... save changes to the db db.session.commit() # ... Update/Create complete return redirect(url_for(''get_users'')) else: # ... form not valid, notify user # ...

Esto manejará editar / crear usuario y crear dirección. Además de crear la relación entre. Para que sea también compatible con eliminar dirección, cambiar

person.addresses.append(actual_address)

a

person.addresses = list_of_actual_addresses

y cambia esto en el modelo de persona (cascade = ''delete-huérfano'')

addresses = db.relationship(''Address'', secondary=personaddress, cascade=''delete-orphan'' backref=db.backref(''person'', lazy=''dynamic''))

Esto hará que el formulario actualice la relación de direcciones completa cada vez y la cascada eliminará las direcciones huérfanas. Por lo tanto, la lista completa de direcciones de una persona se actualizaría cada vez que se envíe el formulario.

Al tratar con WTForms en plantillas, recomiendo usar macros si aún no lo ha hecho. Tendrías que reescribirlo hasta cierto punto, pero mira this .

Espero que esto ayude