2016-04-25 16 views
2

Ich baue ein einfaches CMS, das eine Profilverwaltungsseite enthält. Auf dieser Profilseite, zusammen mit anderen Bereichen gibt es eine Dropdown-Liste, die ich aus einer Tabelle ‚Parks‘ mit der wtforms Erweiterung des QuerySelectField erzeugen:Flask/WTForms/QuerySelectField - render QuerySelectField mit einer Auswahl basierend auf dem vorhandenen Datenbankwert

from wtforms.ext.sqlalchemy.fields import QuerySelectField 

Der Rest der Felder auf der Profilseite ist bevölkert von die 'Benutzer' Tabelle.

Angenommen, ein Benutzer hat sich angemeldet und sein Datensatz in der Tabelle 'user' ist bereits ausgefüllt. Unter den Feldern in der Tabelle 'user' befindet sich ein Fremdschlüssel für einen Wert aus der Tabelle 'parks': 'park_id'.

Wenn ein angemeldeter Benutzer zu seiner Profilseite navigiert, möchte ich die Auswahl in der Dropdownliste anzeigen, die dem Fremdschlüsselwert des Benutzers park_id entspricht.

Beachten Sie, dass Flask/Python et al sehr neu für mich ist. Außerdem verwende ich Flask-Security und das unten stehende Benutzermodell basiert auf ihren Beispielen. Vielleicht muss ich eine weitere Beziehung mit Benutzern/Parks aufbauen?

Die gespeicherten Profilinformationen eines Benutzers, einschließlich derjenigen, die in einer Dropdown-Liste angezeigt werden könnten, um zur Bearbeitung verfügbar zu sein, erscheinen mir sehr grundlegend. Ich fürchte, ich vermisse etwas Grundlegendes. Bis jetzt scheinen andere ähnliche Fragen/Antworten auf SO und anderswo für mich sehr verwirrend zu sein.

Mein Benutzer Modell:

# Define models 
roles_users = db.Table('roles_users', 
     db.Column('user_id', db.Integer(), db.ForeignKey('user.id')), 
     db.Column('role_id', db.Integer(), db.ForeignKey('role.id'))) 

class Role(db.Model, RoleMixin): 
    id = db.Column(db.Integer(), primary_key=True) 
    name = db.Column(db.String(80), unique=True) 
    description = db.Column(db.String(255)) 

class User(db.Model, UserMixin): 
    id = db.Column(db.Integer, primary_key=True) 
    email = db.Column(db.String(255), unique=True) 
    password = db.Column(db.String(255)) 
    active = db.Column(db.Boolean()) 
    confirmed_at = db.Column(db.DateTime()) 
    roles = db.relationship('Role', secondary=roles_users, 
          backref=db.backref('users', lazy='dynamic')) 
    park_id = db.Column(db.Integer) 
    weather_zip = db.Column(db.String(255)) 
    flickr_api_key = db.Column(db.String(255)) 
    flickr_api_secret = db.Column(db.String(255)) 
    flickr_user_id = db.Column(db.String(255)) 
    flickr_photo_set_id = db.Column(db.String(255)) 

Meine Parks Modell:

class Parks(db.Model): 
    id = db.Column(db.Integer, primary_key=True) 
    park = db.Column(db.String(255)) 

Profil-Form (mit query_factory Sache)

def get_parks(): 
    return Parks.query 

class ProfileForm(Form): 
    id = HiddenField() 
    email = HiddenField() 
    park_id = QuerySelectField('Park',[validators.InputRequired(u'Please select a park')], default=19, query_factory=get_parks, get_label='park', allow_blank=True) 
    weather_zip = StringField('Zip Code',[validators.Length(min=5, max=5, message=u'Zip must contain 5 numbers'), validators.InputRequired(u'please enter a 5-digit zip code')]) 
    flickr_api_key = StringField('Flickr API Key', [validators.InputRequired(u'Please supply a Flickr API key')]) 
    flickr_api_secret = StringField('Flickr API Secret', [validators.InputRequired(u'Please supply a Flickr API secret')]) 
    flickr_user_id = StringField('Flickr User ID', [validators.InputRequired(u'Please supply a Flickr user id')]) 
    flickr_set_id = StringField('Flickr Set ID', [validators.InputRequired(u'Please supply a Flickr set id')]) 

Meine profile_page Ansicht:

@app.route('/profile/<id>', methods=["GET","POST"]) 
@login_required 
def profile_page(id): 

    id = id 
    current_user = User.query.filter_by(id=id).first() 

    form = ProfileForm(obj=current_user) 

    return render_template("profile.html", form=form) 

Form Meine Vorlage ist:

{% from "_formhelpers.html" import render_field %} 
    <form method=post action="/profile"> 
     <dl> 
     {{ form.id(value=current_user.id) }} 
     {{ form.email(value=current_user.email) }} 
     {{ render_field(form.park_id) }} 
     {{ render_field(form.weather_zip) }} 
     {{ render_field(form.flickr_api_key) }} 
     {{ render_field(form.flickr_api_secret) }} 
     {{ render_field(form.flickr_user_id) }} 
     {{ render_field(form.flickr_set_id) }} 
     </dl> 
     <p><input type=submit value=Register> 
    </form> 

Ein Makro, um die Felder zu machen (relevant sein könnte?):

{% macro render_field(field) %} 
    <dt>{{ field.label }} 
    <dd>{{ field(**kwargs) |safe }} 
    {% if field.errors %} 
     <ul class=errors> 
     {% for error in field.errors %} 
      <li>{{ error }}</li> 
     {% endfor %} 
     </ul> 
    {% endif %} 
    </dd> 
{% endmacro %} 

Vielen Dank für jede Hilfe auf all dies.

Antwort

4

Nach ein paar Bier trinken und die Darsteller in diesem Beitrag: SQLAlchemy/WTForms: set default selected value for QuerySelectField bis meine Augen gekreuzt, entdecken ich, dass ich ein Ergebnisobjekt aus einer Abfrage zu meinem Park Tabelle durch den aktuellen Benutzer id gefiltert passieren benötigt.

Ein besonderes Detail ist, dass ich jeden Feldwert (abgesehen von dem QuerySelectField, Parks) manuell vom Abfrageergebnis des gegenwärtigen Benutzers zuweisen musste. Dies liegt daran, dass in meinem Fall die Übergabe des current_user-Ergebnisses an das Argument "obj =" mein Schlüsselwort QuerySelectField (in meinem Fall "park_id") überschreiben würde, weil die Zuweisung "obj = current_user" bereits eine eigene Instanz des Parameters park_id enthält , auch wenn es nicht funktioniert, um eine Standardauswahl in meinem Dropdown anzuzeigen.

So ...Das Problem bestand darin, meine Profilansicht-Funktion wie folgt zu aktualisieren:

@app.route('/profile/<id>', methods=["GET","POST"]) 
@login_required 
def profile_page(id): 

    id = id 
    current_user = User.query.filter_by(id=id).first() 
    park = Parks.query.filter_by(id=current_user.park_id).first() 
    form = ProfileForm(park_id=park, # this is the main thing 
         weather_zip=current_user.weather_zip, 
         flickr_api_key=current_user.flickr_api_key, 
         flickr_api_secret=current_user.flickr_api_secret, 
         flickr_user_id=current_user.flickr_user_id, 
         flickr_photo_set_id=current_user.flickr_photo_set_id) 

    return render_template("profile.html", form=form)