Hacker News new | ask | show | jobs
by mattdawson 4952 days ago
A little off topic, but forms are a big PITA using Flask and extensions, too. Forms are definitely not a solved problem in the python world.
2 comments

What are you using? They are pretty convenient with WTForms.

    # models.py
    class Post(db.Model):
        id = db.Column(db.Integer, primary_key=True)
        name = db.Column(db.String(80))
        title = db.Column(db.String(200))
        content = db.Column(db.Text)
                
        def __init__(self, name, title, content):
            self.name = name
            self.title = title
            self.content = content

    # forms.py
    import flaskext.wtf as wtf
    from flaskext.wtf import Form, validators
    from wtforms.ext.sqlalchemy.orm import model_form
    import models


    PostForm = model_form(models.Post, Form, field_args = {
        'name': {'validators': [validators.required()]},
        'title': {'validators': [validators.required(), validators.length(min=5)]},
        
    })

    # views.py
    def post_new():
        form = forms.PostForm()
        if form.validate_on_submit():
            post = models.Post(form.name.data, form.title.data, form.content.data)
            db.session.add(post)
            db.session.commit()
            return redirect(url_for('post.index'))
        return render_template('post/new.slim', form=form)

    # _post_form.slim
    - from 'helpers.slim' import render_field

    form method="POST" class="well"
      = form.hidden_tag()
      = render_field(form.name, class\="span4")
      = render_field(form.title, class\="span4")
      = render_field(form.content, class\="span4")
      
      .field
        input type="submit" class="btn btn-success"

    # post/new.slim
    - extends 'layout.slim'

    - block content
      .span6
        h2 Creating new post
        - include 'post/_post_form.slim'
        a href="=url_for('.index')" class="btn btn-primary btn-small" Back

    # helpers.slim
    - macro render_field(field)
      div class="{{ 'field-with-errors' if field.errors else 'field' }}"
        - if field.errors
          - for error in field.errors
            p class="error" =  error
        = field.label
        = (field(**kwargs) | safe)

Don't bother about the slim templates. It's a small jinja2 extension which I use to give me slim syntax.

Now this probably looks like a lot. But consider that you write the helper to render the form only once. Also, you can write a helper to generate models and form scaffolding for you. That's what I do.

    python manage.py create_model post -f 'name:String(80) title:String(200) content:Text'
It generates me the model, form and form template(models.py, forms.py, _post_form.py). The form of course will have empty validators which I fill.
I disagree. I found WTForms quite easy to use and straight forward. I believe there's even a Flask-WTForms module. It's very natural. I was just thinking the other day how nice forms are in Flask. Having to write ky own forms stuff in Scala.

Edit: stupid auto-correct.