web-dev-qa-db-fra.com

Préremplissez un WTforms dans le flacon, avec les données d'un objet SQLAlchemy

Je suis relativement nouveau dans le framework flask et je créais une page de modification de profil pour un portail Web. Je suis bloqué à un moment et je ne peux pas remplir automatiquement un formulaire.

Voici ma classe de formulaire:

class EditProfile(Form):

    username = TextField('Username', [Required()])
    email = TextField('Email', [Required()])
    about = TextAreaField('About', [Required()])
    website = TextField('Website', [Required()])

C'est ma fonction qui évalue le formulaire.

def editprofile(nickname = None):
    if g.fas_user['username'] == nickname  or request.method == 'POST':
        form = EditProfile()
        form_action = url_for('profile.editprofile')
        if request.method == 'POST' and form.validate():
            if form.username.data == nickname : 
              query = EditProfile(form.username.data,
                                 form.email.data,
                                 form.about.data,
                                 form.website.data,
                                 )
              print query #debug
              db.session.add(query)
              db.session.commit()
              flash('User Updated')
              print "added"
            return(url_for('profile.editprofile'))
        return render_template('profile/add.html', form=form,
                               form_action=form_action, title="Update Profile")
    else:
        return "Unauthorised"

Et mon modèle html pour le formulaire est le formulaire est:

{% extends "base.html" %}
    {% block title %}
        {{ title }}
    {% endblock %}
    {% block content %}
    {% from "_formhelpers.html" import render_field %}
    <div id="Edit Profile">
        <h2>{{  title  }}</h2>
        <form method="post" action="{{ form_action }}">
            <fieldset>
                <legend></legend>
                {{ render_field(form.username) }}
                {{ render_field(form.email)}}
                {{ render_field(form.about )}}
                {{ render_field(form.website) }}
            </fieldset>
        <input type="submit" class="button" value="Save"/>
    </form>
    </div>
    {% endblock %}


J'ai un objet, de classe utilisateur. Et à partir de cet objet, je veux préremplir ce formulaire. Comment puis-je préremplir les valeurs du formulaire. J'essaie d'implémenter la fonctionnalité de modification du profil ici.

18
Hammad Haleem

Vous devez transmettre votre objet au formulaire lorsque vous le créez.

form = EditProfile(obj=user)  # or whatever your object is called

Vous allez avoir des ennuis avec

          query = EditProfile(form.username.data,
                             form.email.data,
                             form.about.data,
                             form.website.data,
                             )
          db.session.add(query)

Il crée une nouvelle instance de votre formulaire EditProfile. Vous essayez ensuite de l'ajouter à la session. La session veut des modèles, pas des formes.

Au lieu de cela, après avoir validé le formulaire, vous pouvez associer ses valeurs à l'objet.

form.populate_obj(user)  # or whatever your object is called

Parce que votre objet était déjà chargé, vous n'aurez pas besoin de l'ajouter à la session. Vous pouvez supprimer db.session.add(query) et simplement appeler db.session.commit().

21
dirn

La façon la plus simple que j'ai trouvée de le faire est de remplir les champs du formulaire sur une demande d'obtention.

@decorator_authorized_user  # This decorator should make sure the user is authorized, like @login_required from flask-login
def editprofile(nickname = None):
    # Prepare the form and user
    form = EditProfile()
    form_action = url_for('profile.editprofile')
    my_user = Users.get(...)  # get your user object or whatever you need
    if request.method == 'GET':
        form.username.data = my_user.username
        form.email.data = my_user.email
        # and on
    if form.validate_on_submit():
        # This section needs to be reworked.
        # You'll want to take the user object and set the appropriate attributes
        # to the appropriate values from the form.
        if form.username.data == nickname: 
            query = EditProfile(form.username.data,
                                form.email.data,
                                form.about.data,
                                form.website.data,
                                )
            print query #debug
            db.session.add(query)
            db.session.commit()
            flash('User Updated')
            print "added"
            return(url_for('profile.editprofile'))
    return render_template('profile/add.html', form=form,
                           form_action=form_action, title="Update Profile")

Cela configure la fonction pour renvoyer un formulaire prérempli sur une demande get. Vous devrez retravailler la section sous form.validate_on_submit. La réponse de Dirn suggère quelques-unes des bonnes choses à faire.

8
Eric Workman

Pour remplir le formulaire avec votre objet SQLAlchemy, utilisez:

form = EditProfile(obj=<SQLAlchemy_object>)

Si vos champs de formulaire ne correspondent pas aux colonnes de la base de données dans votre modèle pour une raison quelconque (ils le devraient), la classe de formulaire prend des kwargs:

** kwargs - Si ni formdata ni obj ne contiennent de valeur pour un champ, le formulaire attribuera la valeur d'un argument de mot clé correspondant au champ, le cas échéant.

J'ai trouvé qu'un cas d'utilisation pour cela est si vous avez un formulaire qui contient des champs qui référencent plus d'un modèle (par exemple via une relation); passer celui obj ne suffit pas.

Prenons donc votre exemple et disons que dans votre modèle de base de données (pour user) vous utilisez site au lieu de website (le nom du champ du formulaire). Vous feriez cela pour remplir votre formulaire à partir de l'objet SQLAlchemy:

form = EditProfile(obj=user, website=user.site)

Ensuite, dans le POST, vous devez le faire pour remplir votre objet SQLAchemy à partir de votre formulaire:

form.populate_obj(user)
user.site = form.website.data
db.session.commit()
7
brenj