I've seen a pattern in Flask (and Lithium) where a single view method corresponds to multiple HTTP verbs; example:
@app.route('/login', methods=['GET', 'POST'])
def login():
error = None
if request.method == 'POST':
if request.form['username'] != app.config['USERNAME']:
error = 'Invalid username'
elif request.form['password'] != app.config['PASSWORD']:
error = 'Invalid password'
else:
session['logged_in'] = True
flash('You were logged in')
return redirect(url_for('show_entries'))
return render_template('login.html', error=error)
I think this leads to bloated view methods that do more than one thing.
I was going to ask why this was the default pattern in Flask, but now I see that method-based views exist.
Still, why have non-method based views in the framework at all? Because not all client-server protocols talk through REST, and method-based views are inherently REST-flavored?
The simple answer is it's easier, and often cleaner. The majority of views
are GET
methods, and so Flask makes that very simple, with decorated
views such as:
@app.route('/')
def home():
thing = do_fun_stuff()
return render_template('home.html', foo=thing)
If I wanted to represent using a MethodView
that you find less bloated, I'd end up with:
class HomeView(MethodView):
def get(self):
thing = do_fun_stuff()
return render_template('home', foo=thing)
app.add_url_rule('/', view_func=HomeView.as_view('home'))
In reality, your login()
code could be cleared up, and made less bloated by
using better form handling and validation using Flask-WTF and Flask-Login, which
would lead you to a login process such as:
app.route('/login', methods=['GET', 'POST'])
def login():
form = LoginForm()
if form.validate_on_submit():
login_user(form.user)
return redirect(url_for('show_entries'))
return render_template('login.html', form=form)
Which is a long-way around of saying, it's nice to have options. Flask doesn't force a particular narrative on your development, and what is bloated on one project might be concise on another that solves a different goal.