2014-03-05 7 views
8

Ich habe eine Webanwendung, die es Benutzern ermöglicht, ihre eigenen Felder zu erstellen, die später in einem Formular gerendert werden.Generieren Sie ein dynamisches Formular mit Hilfe von flask-wtf und sqlalchemy

Ich habe ein Modell Formfield wie so:

class Formfield(db.Model): 
    id = db.Column(db.Integer, primary_key = True) 
    form_id = db.Column(db.Integer, db.ForeignKey('formbooking.id')) 
    label = db.Column(db.String(80)) 
    placeholder_text = db.Column(db.String(80)) 
    help_text = db.Column(db.String(500)) 
    box_checked = db.Column(db.Boolean, nullable = True, default = False) 
    options = db.Column(db.String) # JSON goes here? 
    answer = db.Column(db.String) 
    required = db.Column(db.Boolean, nullable = False, default = False) 
    order = db.Column(db.Integer) 
    fieldtype = db.Column(db.Integer) 

, die ich verwende, um ein Feld darzustellen, unabhängig von der Art (Checkbox, Input, mehr in der Zukunft).

Wie Sie sehen können, hat jedes Feld einen FK zu einer form_id.

Ich versuche, ein dynamisches Formular für eine bestimmte Form_id zu generieren. Der Catch ist, dass ich den Typ des Feldes bestimmen muss, um für jedes Formfield zu rendern. Also muss ich auch den Feldtyp irgendwann verarbeiten.

Ich denke, eine Lösung wäre irgendwie die form_id an eine Funktion in meiner Form-Klasse weitergeben.

Ich habe keine Ahnung, wie es geht oder wo Sie nach einer Lösung suchen.

Jede Hilfe wäre sehr willkommen!

Antwort

13

Ich denke, ich von hier aus dynamischen Formen mit der Idee zu schaffen verwaltet https://groups.google.com/forum/#!topic/wtforms/cJl3aqzZieA

Sie haben eine dynamische Form an View-Funktion erstellen, holen Sie das Formularfeld Sie erhalten möchten, und wiederholen Sie alle Felder dieses Formulars zu konstruieren Objekt. Ich habe für Feldtypen einfachen Text anstelle von ganzzahligen Werten verwendet. Da es auf Code-Ebene leicht zu lesen scheint.

class FormView(MethodView): 
def get(self): 
    class DynamicForm(wtforms.Form): pass 

    dform = main.models.Form.objects.get(name="name2") 
    name = dform.name 
    for f in dform.fields: 
     print f.label 
     setattr(DynamicForm , f.label, self.getField(f)) 

    d = DynamicForm() # Dont forget to instantiate your new form before rendering 
    for field in d: 
     print field # you can see html output of fields 

    return render_template("customform.html", form=d) 

def getField(self, field): 
    if field.fieldtype == "text": 
     return TextField(field.label) 
    if field.fieldtype == "password": 
     return PasswordField(field.label) 
    # can extend if clauses at every new fieldtype 

für eine einfache Form jinja template 'Forms.html'

{% macro render(form) -%} 
<fieldset> 
{% for field in form %} 
{% if field.type in ['CSRFTokenField', 'HiddenField'] %} 
    {{ field() }} 
{% else %} 
    <div class="form-group {% if field.errors %}error{% endif %}"> 
    {{ field.label }} 
    <div class="input"> 
     {% if field.name == "body" %} 
     {{ field(rows=10, cols=40) }} 
     {% else %} 
     {{ field() }} 
     {% endif %} 
     {% if field.errors or field.help_text %} 
     <span class="help-inline"> 
     {% if field.errors %} 
      {{ field.errors|join(' ') }} 
     {% else %} 
      {{ field.help_text }} 
     {% endif %} 
     </span> 
     {% endif %} 
    </div> 
    </div> 
{% endif %} 
{% endfor %} 
</fieldset> 
{% endmacro %} 

und customform.html ist wie dieser

{% extends "base.html" %} 
{% import "forms.html" as forms %} 

{% block content %} 
{{ forms.render(form) }} 
{% endblock %} 
+1

dank machen! Als Referenz siehe [dynamische Formularzusammensetzung] (http://wtforms.readthedocs.org/en/1.0/specific_problems.html#dynamic-form-composition) in den wtforms-Dokumenten. – Dailyrox

+0

Schönheit, Instanziieren des Formularklassenobjekts löste mein Problem. – Adrian

+0

@Dailyrox tote Verbindung. – roy