yangmillstheory
yangmillstheory

Reputation: 1065

Flask view methods and SRP

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?

Upvotes: 1

Views: 307

Answers (1)

Doobeh
Doobeh

Reputation: 9450

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.

Upvotes: 4

Related Questions