为了账号安全,请及时绑定邮箱和手机立即绑定

前后端协作实现用户名验证:利用SQLAlchemy和Formik/Yup进行表单验证

在我开发第5阶段项目的过程中,实现的一个最重要的特性是数据验证。从后端到前端,一致的验证功能有助于保持数据库的完整性并确保数据一致性,并通过屏幕上的错误和成功提示,为用户提供友好的体验。

在这篇博客里,我会通过一个例子来带您了解在注册流程中如何验证主要用户属性之一(例如用户名)。我将使用FlaskSQLAlchemy来处理后端验证,同时使用FormikYup来处理前端验证。

在后端:使用 Flask 和 SQLAlchemy 验证用户名的有效性

我们先从Flask/SQLAlchemy后端和User模型开始。这里实现了验证,以确保用户名是唯一的、格式正确,并符合一些基本的验证规则,在添加到数据库之前。

使用SQLAlchemy的用户模型(User Model)

下面这个用户模型定义了用户名字段,并使用SQLAlchemy的@validates装饰器进行了验证。

db = SQLAlchemy()class User(db.Model):  
    __tablename__ = 'users'    id = db.Column(db.Integer, primary_key=True)  
    username = db.Column(db.String, unique=True, nullable=False)  
    # 其他属性 ... additional attributes

    @validate('username')  
    def validate_username(self, key, username):  
        if not username:  
            raise ValueError("请输入用户名。")  

        if len(username) < 5:  
            raise ValueError("用户名必须至少包含5个字符。")  

        if not re.match(r'^[\w_]+

已实施的验证:

* **唯一性**:在数据库中将属性标记为 `unique=True` 可以确保每个用户名都是独一无二的。
* **必填项**:`if not username` 检查用户名字段是否为空。
* **最小长度**:`len(username) < 5` 检查用户名长度是否小于 5 个字符。
* **格式**:正则表达式 `^[\w_]+# 前后端协作实现用户名验证:利用SQLAlchemy和Formik/Yup进行表单验证

在我开发第5阶段项目的过程中,实现的一个最重要的特性是**数据验证**。从后端到前端,一致的验证功能有助于保持数据库的完整性并确保数据一致性,并通过屏幕上的错误和成功提示,为用户提供友好的体验。

在这篇博客里,我会通过一个例子来带您了解在注册流程中如何验证主要用户属性之一(例如用户名)。我将使用**Flask**和**SQLAlchemy**来处理后端验证,同时使用**Formik**和**Yup**来处理前端验证。

# 在后端:使用 Flask 和 SQLAlchemy 验证用户名的有效性

我们先从**Flask/SQLAlchemy**后端和User模型开始。这里实现了验证,以确保用户名是唯一的、格式正确,并符合一些基本的验证规则,在添加到数据库之前。

## 使用SQLAlchemy的用户模型(User Model)

下面这个用户模型定义了用户名字段,并使用SQLAlchemy的`@validates`装饰器进行了验证。

db = SQLAlchemy()class User(db.Model):
tablename = 'users' id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True, nullable=False)

其他属性 ... additional attributes
@validate('username')  
def validate_username(self, key, username):  
    if not username:  
        raise ValueError("请输入用户名。")  

    if len(username) < 5:  
        raise ValueError("用户名必须至少包含5个字符。")  

    if not re.match(r'^[\w_]+

已实施的验证:

检查用户名是否只包含字母、数字和下划线。

  • 检查重复User.query.filter_by() 方法查询数据库中是否已有相同用户名。
Flask 中的用户注册

以下是处理用户注册的注册资源页面,应用了模型验证逻辑。

    class Signup(Resource):  
        def post(self):  
            data = request.get_json()    
            username = data.get('username')  
            try:  
                new_user = User(  
                    username=username.lower(),  
                    ... 其他相关属性  
                )  
                db.session.add(new_user)  
                db.session.commit()  
                session['username'] = new_user.username  
                return jsonify({'message': '用户注册成功。'}), 201  
            except ValueError as e:  
                return jsonify({'error': str(e)}), 400  
            except IntegrityError as e:  
                return jsonify({'error': str(e)}), 409  
            except Exception as e:  
                return jsonify({'error': str(e)}), 500

class CheckUsername(Resource):  
    def get(self, un):  
        un = un.lower()  
        existing_user = User.query.filter_by(un=un).first()  
        if existing_user:  
            return {'error': '用户名已存在。'}, 400  
        return {'message': '该用户名可用。'}, 200
注册步骤:

如果任何验证(例如唯一性或格式验证)失败,将会抛出一个 ValueErrorexcept 块捕获该异常并返回一个 400 错误。

检查用户名可用性

The User.query.filter_by() 方法查询数据库中,检查用户名是否已存在。

前端:用 Formik 和 Yup 检查用户名

后台验证已经处理好了,现在用户名可以在前端通过FormikYup进行实时验证。

表单注册组件,与 Formik 和 Yup

下面是SignupForm组件,它导入了Formik进行表单处理和Yup进行验证:

    function SignupForm() {  
        const checkUsername = (username) => {  
            formik.setFieldError("username", "");  
            formik.setStatus({ usernameAvailable: "" });  
            fetch(`/check_username/${username}`)  
                .then((r) => r.json())  
                .then((data) => {  
                    if (data.error) {  
                        formik.setFieldError("username", data.error);  
                    } else {  
                        formik.setStatus({ usernameAvailable:   
                        data.message });  
                    }  
                })  
                .catch((error) => {  
                    console.error("用户名检查错误:", error.message);  
                });  
        };  
        useFormik({  
            initialValues: {  
                username: "",  
                ...其他属性  
            },  
            validationSchema: Yup.object({  
                username: Yup.string()  
                    .required("用户名是必填的")  
                    .matches(/^[\w]+$/, "用户名只能包含字母、数字和下划线。")  
                    .min(5, "用户名必须至少包含5个字符。")  
                    .test("check-username", "检查用户名...",  
                     function(value) {  
                        if (value) {  
                            checkUsername(value);  
                        }  
                        return true;  
                    }),  
                ...其他属性  
            }),  
            onSubmit: (values) => {  
                const newUser = {  
                    username: values.username,  
                    ...其他属性  
                };  
                signup(newUser);  
            },  
        });  
        return (  
            <div>  
                <h1>注册</h1>  
                <form onSubmit={formik.handleSubmit}>  
                    <div>  
                        <label>用户名:</label>  
                        <input  
                            type="text"  
                            id="username"  
                            name="username"  
                            onChange={(e) => {  
                                formik.handleChange(e);  
                                checkUsername(e.target.value);  
                            }}  
                            value={formik.values.username}  
                        />  
                        <p>{!formik.errors.username && formik.status  
                            ? formik.status.usernameAvailable  
                            : formik.errors.username}</p>  
                    </div>  
                    <button type="submit">注册</button>  
                </form>  
            </div>  
        );  
    }  
export default SignupForm;
解释:
  • 实时用户名验证:用户输入时,checkUsername 函数会在 Formik 中触发。此函数向后端发送请求以验证用户名是否可用。
  • Yup 验证:在提交之前,Formik 确保用户名符合要求规则(最小长度、格式等)。如果验证失败,会立即显示相应的错误消息。
结论

在这篇博客里,我讲解了如何进行用户名验证,既在后端(使用 Flask 和 SQLAlchemy)上,也在前端(使用 Formik 和 Yup)上。同时在客户端和服务器端验证用户名,这样可以让你的应用程序既安全又好用。

  • 后端验证 确保系统进入数据库的数据是有效的,并符合规定的规则(比如,唯一性,格式)。
  • 前端验证 向用户即时提供反馈,减少不必要的服务器交互。

通过将这些技术结合起来,你可以构建一个坚实且可靠的表单验证系统,使其在整个技术栈中顺畅运行。
, username):
raise ValueError("用户名只能包含字母、数字和下划线。")

    if User.query.filter_by(username=username).first():  
        raise ValueError("该用户名已存在。")  

    return username

Validations implemented:

* **Uniqueness** : Marking the attribute as `unique=True` in the database ensures that no two users can have the same username.

* **Required** : `if not username` checks if the username field is empty.

* **Minimum length** : `len(username) < 5` checks if the username less than 5 characters long.

* **Format** : The regular expression `^[\w_]+$` checks the username from the first character to the last, ensuring the username only contains letters, numbers, and underscores.

* **Check for duplicates** : The `User.query.filter_by()` method queries the database checking to see if the username already exists.

## Signup Resource in Flask

Below is the **signup resource** where user registration is handled and the validation logic from the model is applied:
class Signup(Resource):  
    def post(self):  
        data = request.get_json()    
        username = data.get('username')  
        ... other attributes        try:  
            new_user = User(  
                username=username.lower(),  
                ... other attributes  
            )            db.session.add(new_user)  
            db.session.commit()  
            session['username'] = new_user.username            return jsonify({'message': 'User registered   
            successfully.'}), 201        except ValueError as e:  
            return jsonify({'error': str(e)}), 400        except IntegrityError as e:  
            return jsonify({'error': str(e)}), 409        except Exception as e:  
            return jsonify({'error': str(e)}), 500class CheckUsername(Resource):  
    def get(self, un):  
        un = un.lower()  
        existing_user = User.query.filter_by(un=un).first()            if existing_user:  
                return {'error': 'Username already exists.'}, 400        return {'message': 'Username is available.'}, 200

## Signup Resource:

If any validation fails (either backend validation like uniqueness or format), a `ValueError` is raised which is caught in the `except` block and returned as a `400` error.

## Check Username Resource:

The `User.query.filter_by()` method queries the database checking to see if the username already exists.

# Frontend: Validating Usernames with Formik and Yup

Now that the backend validations have been handled, the username can be validated in real-time on the frontend with **Formik** and **Yup**.

## Signup Form Component with Formik and Yup

Below is the **SignupForm** component which imports **Formik** for form handling and **Yup** for validation:
function SignupForm() {  
    const checkUsername = (username) => {  
        formik.setFieldError("username", "");  
        formik.setStatus({ usernameAvailable: "" });        fetch(`/check_username/${username}`)  
            .then((r) => r.json())  
            .then((data) => {  
                if (data.error) {  
                    formik.setFieldError("username", data.error);  
                } else {  
                    formik.setStatus({ usernameAvailable:   
                    data.message });  
                }  
            })  
            .catch((error) => {  
                console.error("Username check error:",   
                error.message);  
            });  
    };    const formik = useFormik({  
        initialValues: {  
            username: "",  
            ... other attributes  
        },validationSchema: Yup.object({  
            username: Yup.string()  
                .required("Username is required")  
                .matches(/^[\w]+$/, "Username can only contain   
                 letters, numbers, and underscores.")  
                .min(5, "Username must be at least 5 characters.")  
                .test("check-username", "Checking username...",  
                 function(value) {  
                    if (value) {  
                        checkUsername(value);  
                    }  
                    return true;  
                }),  
            ... other attributes  
        }),        onSubmit: (values) => {  
            const newUser = {  
                username: values.username,  
                ... other attributes  
            };  
            signup(newUser);  
        },  
    });    return (  
        <div>  
            <h1>Sign Up</h1>  
            <form onSubmit={formik.handleSubmit}>  
                <div>  
                    <label>Username:</label>  
                    <input  
                        type="text"  
                        id="username"  
                        name="username"  
                        onChange={(e) => {  
                            formik.handleChange(e);  
                            checkUsername(e.target.value);  
                        }}  
                        value={formik.values.username}  
                    />  
                    <p>{!formik.errors.username && formik.status   
                        ? formik.status.usernameAvailable  
                        : formik.errors.username}</p>  
                </div>  
                <button type="submit">Sign Up</button>  
            </form>  
        </div>  
    );  
}export default SignupForm;


## Explanation:

* **Real-time Username Validation** : The `checkUsername` function is triggered in Formik as the user types. This function sends a request to the backend to check if the username is available.

* **Yup Validation** : Before submitting, Formik ensures the username follows the required rules (minimum length, format, etc.). If the validation fails, the error message is displayed immediately.

# Conclusion

In this blog post, I’ve shown how to handle **username validation** both on the **backend** (using Flask and SQLAlchemy) and the **frontend** (using Formik and Yup). By validating the username both client-side and server-side, you ensure that your application is both secure and user-friendly.

* **Backend validation** ensures that the data entering your database is valid and conforms to the required rules (e.g., uniqueness, formatting).

* **Frontend validation** provides immediate feedback to users, reducing unnecessary requests to the server.

By combining these techniques, you can build a solid, reliable form validation system that works seamlessly across the entire stack.
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消