3
\$\begingroup\$

I'm trying to capture all input fields in a form (i.e. sign_up.html) & validating them - if one of them is null or empty then it should show a validation message. I've done it but I'm looking for an elegant way to do it.

sign_up.html

{% extends "layout.html" %}

{% block main %}
<form action="/sign_up.html" method="POST" autocomplete="off" name="sign_up">

    <h2>Sign Up</h2>

    <label for="username">User name:
        <input type="text" placeholder="Username" name="username" required="required" maxlength="20">
    </label>
    <br>

    <sup>* Password must be 8-12 Digit ,Numbers & letters & punctuations @, !, $, ETC..</sup>
    <label for="password">Password:
        <input type="password" placeholder="password" name="password" required="required" minlength="8" maxlength="12">
    </label>

    <label for="check">Check Password:
        <input type="password" placeholder="Check Password" name="check" required="required" minlength="8" maxlength="12">
    </label>
    <br>

    <label for="security_question">Security question :
        <select name="security_question">
            <option value="where were you born?" name="q1" >where were you born?</option>
            <option value="what is your favorite nickname?" name="q2" >what is your favorite nickname?</option>
            <option value="what is the name of your first pet?" name="q3" >what is the name of your first pet?</option>
            <option value="what is the name of your first best friend?" name="q4" >what is the name of your first best friend?</option>
        </select>
    </label>

    <label for="answer">Security answer:
        <input type="text" placeholder="Answer" name="answer" required="required">
    </label>
    <br>

    <input type="submit" value="Sign Up">
</form>
{% endblock %}

this is my spaghetti validation python code:

from flask import Flask, flash, redirect, render_template, Request, request, session
from werkzeug.datastructures import ImmutableOrderedMultiDict
from werkzeug.utils import HTMLBuilder

#Something in between

class OrderedRequest(Request):
    parameter_storage_class = ImmutableOrderedMultiDict

app = Flask(__name__)

app.request_class = OrderedRequest

#Something in between

@app.route("/sign_up.html",  methods=["GET", "POST"])
def sign_up():

if request.method == "POST":

        #assigning returning page
        page = "sign_up.html"

        #Null fields checking
        if not request.form.get("username"):
            return render_template("errors/general_error.html", error = "Username field is Empty", page = page)

        elif not request.form.get("password"):
            return render_template("errors/general_error.html", error = "Password field is Empty", page = page)

        elif not request.form.get("check"):
            return render_template("errors/general_error.html", error = "Check Password field is Empty", page = page)

        elif not request.form.get("answer"):
            return render_template("errors/general_error.html", error = "answer field is Empty", page = page)

#something at the end

this will return a page with the validation error massage.

I need to loop through an element gives me names of all the inputs inside the form & I'll return the error massage due to it..

& code will be like:

for i in needed_element:
    if not i:
        return render_template("errors/general_error.html", error = f"{i} field is Empty", page = page)

or something similar or any more elegant way because I'm repeating this step many times in the project :'D

\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

Readability

Before addressing the main concern, readability should be addressed.

Many python developers adhere to PEP8 for consistent code style.

This code does not adhere to a few aspects:

Limit all lines to a maximum of 79 characters.

For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.

Don't use spaces around the = sign when used to indicate a keyword argument, or when used to indicate a default value for an unannotated function parameter:

Repeated code

As you already identified, the code to check for missing fields in order to display validation prior errors is quite redundant. This goes against the Don't Repeat Yourself principle .

One option is to abstract out the fields to check into a dictionary:

field_mapping = {'username': 'Username', 'password': 'Password',
                 'check': 'Check Password', 'answer': 'Answer'}

Then the items() method can be used to iterate through the keys and values, unpacked to a tuple:

for field, label in field_mapping.items():
    if not request.form.get(field):
        return render_template("errors/general_error.html",
                               error=f"{label} field is Empty", page=page)
\$\endgroup\$
3
  • \$\begingroup\$ many thanks for Readability instruction's. I found that too I can easily do ``` for i in request.form: if not request.form.get(i): return render_template("errors/general_error.html", error = i + " field is Empty", page=page) ``` \$\endgroup\$ Aug 12, 2021 at 15:52
  • \$\begingroup\$ Ah I had considered mentioning that but figured it wouldn't allow customizing the label - e.g. check -> Check Password \$\endgroup\$ Aug 12, 2021 at 16:02
  • 1
    \$\begingroup\$ that's a nice concentration, I find that too so I changed the input names to be check -> check_password then applying "check_password".replace("_"," ").capitalize() when returning values to jinja. \$\endgroup\$ Aug 12, 2021 at 16:11
1
\$\begingroup\$

I found that I can iterate through form inputs by doing this..

for i in request.form:
            if not request.form.get(i):
                return render_template("errors/general_error.html", error = i + " field is Empty", page=page)

as request.form will give you a list contains all names of inputs in form.

Note: it excludes <input type="submit" value="Sign Up"> by default, because this input have no name.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.