You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flask+Marshmallow+SQLAlchemy中实现枚举值的请求解析与数据库整数存储?

Fix: Store Gender as Integer Instead of Enum String in Flask/Marshmallow/SQLAlchemy

Got it, let's resolve this issue where you want to map male/female from incoming requests to integers 0/1 in your database. Here's a straightforward, maintainable solution tailored to your tech stack:


1. Update Your Model Definition (models.py)

First, we'll adjust the enum to use integer values and switch the gender column from SQLAlchemy's Enum type to Integer—this ensures the database stores raw integers instead of enum strings. We'll also add a helper method to safely convert incoming strings to the correct enum value:

import enum
from sqlalchemy import Column, Integer, String
from .extensions import db

class Genders(enum.Enum):
    MALE = 0
    FEMALE = 1

    # Helper to convert incoming string (case-insensitive) to enum
    @classmethod
    def from_string(cls, gender_input):
        cleaned_input = gender_input.strip().lower()
        if cleaned_input == "male":
            return cls.MALE
        elif cleaned_input == "female":
            return cls.FEMALE
        raise ValueError(f"Invalid gender: {gender_input}. Must be 'male' or 'female'.")

class Users(db.Model):
    id = Column(Integer, primary_key=True)
    first_name = Column(String(100))
    last_name = Column(String(100))
    # Replace Enum(Genders) with Integer to store 0/1
    gender = Column(Integer, nullable=False)

2. Customize the Marshmallow Schema (schema.py)

Next, we'll create a custom Marshmallow field to handle the conversion between incoming strings and database integers. This field will handle both deserialization (converting request data to database values) and serialization (converting database values back to human-readable strings for responses):

from marshmallow import fields, ValidationError
from .models import Users, Genders
from .extensions import ma

class GenderField(fields.Field):
    def _deserialize(self, value, attr, data, **kwargs):
        # Convert incoming string to integer for the database
        try:
            return Genders.from_string(value).value
        except ValueError as e:
            raise ValidationError(str(e))

    def _serialize(self, value, attr, obj, **kwargs):
        # Convert stored integer back to string for responses (optional but useful)
        return Genders(value).name.lower()

class SignUpSchema(ma.SQLAlchemySchema):
    class Meta:
        model = Users
    first_name = ma.auto_field(data_key='firstName', required=True)
    last_name = ma.auto_field(data_key='lastName', required=True)
    # Use our custom field instead of EnumField
    gender = GenderField(required=True)

3. Verify the View Logic (views.py)

Your existing view code doesn't need major changes—since the schema now handles all conversion logic, it will pass the correct integer value to the Users model. We can tweak the return to use the schema's dump method if you want to send the human-readable gender back in the response:

from flask import request
from flask.views import MethodView
from .schemas import SignUpSchema
from .models import Users
from .extensions import db

class SignUp(MethodView):
    methods = ['POST']
    def post(self):
        json_data = request.get_json()
        schema = SignUpSchema()
        # Load will auto-convert "male"/"female" to 0/1
        data = schema.load(json_data)
        user = Users(**data)
        db.session.add(user)
        db.session.commit()
        # Optional: Return the serialized user data (includes gender as string)
        return schema.dump(user)

How This Works

  • Model Layer: The gender column is now an Integer, so your database will store 0 for male and 1 for female exactly as you want.
  • Schema Layer: The GenderField takes care of translating between the request's string values and the database's integer values. It also handles case insensitivity (so Male, MALE, or male all work).
  • Validation: The helper method and ValidationError ensure invalid gender values are caught early and return a clear error message to the client.

Test It

Send this request:

{
  "firstName": "John",
  "lastName": "Doe",
  "gender": "male"
}

Your database will now show:

idfirst_namelast_namegender
42JohnDoe0

If you use schema.dump(user) in the response, you'll get:

{
  "id": 42,
  "firstName": "John",
  "lastName": "Doe",
  "gender": "male"
}

内容的提问来源于stack exchange,提问作者sebsmgzz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 13:42:41