En mi aplicación, tengo usuarios y publicaciones como modelos. Cada publicación tiene una clave externa para un nombre de usuario. Cuando creo un ModelView encima de mi modelo de Publicaciones, puedo crear publicaciones como usuarios específicos en la interfaz de administración, como se ve en la siguiente captura de pantalla.
Después de agregar una publicación y hacer clic en "Guardar y agregar otra", el "Usuario" vuelve a ser "usuario1". ¿Cómo puedo hacer que el formulario recuerde el valor anterior "usuario2"?
Mi investigación me ha llevado a creer que se puede hacer modificando on_model_change y on_form_prefill, y guardando el valor anterior en la sesión del matraz, pero parece ser una tarea tan simple como un exceso de ingeniería. Debe haber una forma más sencilla.
Mi código se puede ver a continuación
from flask import Flask from flask_sqlalchemy import SQLAlchemy import flask_admin from flask_admin.contrib import sqla app = Flask(__name__) db = SQLAlchemy() admin = flask_admin.Admin(name='Test') class Users(db.Model): """ Contains users of the database """ user_id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(64), index=True, unique=True, nullable=False) def __str__(self): return self.username class Posts(db.Model): """ Contains users of the database """ post_id = db.Column(db.Integer, primary_key=True) username = db.Column(db.String(11), db.ForeignKey(Users.username), nullable=False) post = db.Column(db.String(256)) user = db.relation(Users, backref='user') def build_sample_db(): db.drop_all() db.create_all() data = {'user1': 'post1', 'user1': 'post2', 'user2': 'post1'} for user, post in data.items(): u = Users(username=user) p = Posts(username=user, post=post) db.session.add(u) db.session.add(p) db.session.commit() class MyModelView(sqla.ModelView): pass if __name__ == '__main__': app.config['SECRET_KEY'] = '123456790' app.config['DATABASE_FILE'] = 'sample_db.sqlite' app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database' app.config['SQLALCHEMY_ECHO'] = True db.init_app(app) admin.init_app(app) admin.add_view(MyModelView(Posts, db.session)) with app.app_context(): build_sample_db() # Start app app.run(debug=True)Me he encontrado con esta situación antes y la he resuelto usando 2 funciones. es bastante fácil y pequeño.
@expose('/edit/', methods=('GET', 'POST')) def edit_view(self): #write your logic to populate the value into html self._template_args["arg_name"] = stored_value # in your html find this value to populate it as you needla función anterior le permitirá completar los valores en html cuando el usuario intente editar cualquier valor. Esto se puede completar con el valor almacenado. Y debajo hay una función que lo ayuda a guardar el valor de la edición anterior.
dentro de esta class MyModelView(sqla.ModelView): debe agregar las siguientes 2 funciones.
def on_model_change(self, form, model, is_created): stored_value = model.user # this is your user name stored # get the value of the column from your model and save itEsta es una operación de 2 pasos que es bastante pequeña y no necesita mucho tiempo. He agregado solo un esqueleto/pseudocódigo por ahora.
on_form_prefill no lo ayudará con este problema, ya que solo funciona para el formulario de edición.
Como dice el código lib -> on_form_prefill => Realizar acciones adicionales para completar previamente el formulario de edición
Cuando llega una solicitud, ocurre el siguiente flujo de código:
(Clase base) Ver (create_view) ->create_form->_create_form_class->get_create_form->get_form-> scaffold_form
Por lo tanto, si queremos cambiar el valor predeterminado del formulario de creación que se está cargando, podemos actualizarlo en los métodos que manejan el formulario como se explica en el flujo anterior.
Por lo tanto, podemos anular create_form.
def create_form(self): form = super().create_form() # set the user id we want in the form as default. form.user_id.default = 'USER_2_ID' return formEsto fue para obtener el valor predeterminado para el formulario.
Para establecer el valor, anulamos on_model_change
def on_model_change(self, form, model, is_created): # set the USER_ID from this model.user_id passAhora, la forma de compartir estos datos (USER_ID) de los métodos setter y getter es la siguiente:
Estos datos deben compartirse entre dos solicitudes diferentes, por lo tanto, al almacenarlos en el contexto de la aplicación, g no funcionará. El contexto de la aplicación "no se compartirá entre solicitudes"
def create_form(self): form = super().create_form() user_id = request.args.get('user_id') form.user_id.default = user_id # or if you want only one option to be available user_query = self.session.query(User).filter(User.id = user_id).one() form.user.query = [user_query] return formComo la respuesta anterior menciona usar edit_view, create_view, que también se puede usar para agregar
Una opción fácil pero no buena será consultar sobre la creación que le dará la última entrada ( pero este enfoque no es óptimo )
@expose('/new/', methods=('GET', 'POST')) def create_view(self): model = self.get_model() # query the model here to get the latest value of the user_id self._template_args['user_id'] = user_id return super(YourAdmin, self).details_view()