Django的 TextChoices在添加额外字段时出现 __new__() 的位置参数错误

后端开发 2026-07-09

我在将参数传递给Django的 models.textChoices 类类型时遇到了问题;在尝试添加额外字段时,我在 ___next__() 的覆盖实现中遇到了错误:

TypeError: MyPets.FleaPlans.__new__() missing 1 required positional argument: 'label'

参数应与传递的元组数据相匹配。默认是两个参数 value, label,但我想再要一个第三个参数,另一个 value, desc, label。无论我按何种顺序,都会得到位置参数错误。

如果在 __new__(cls, value, label) 函数中只传递两个参数,它不会报错,但如果传递三个参数 __new__(cls, value, desc, label),就会报错。似乎总是最后一个参数导致问题,如果我改变顺序就会改变。

我可以把它设为一个字符串,因此错误似乎出在传递参数、读取我的元组列表。

我的调试数据只有两条用于测试,我把不同的 __new____init__ 测试代码注释掉了。

用于搜索示例:为Django的 TextChoices添加额外字段

Suggested method:

from django.db import models

class ColorChoices(models.TextChoices):
    def __new__(cls, value, label, hex_code):
        obj = str.__new__(cls, value)
        obj._value_ = value
        obj.label = label
        obj.hex_code = hex_code
        return obj

    RED = 'R', 'Red', '#FF0000'
    GREEN = 'G', 'Green', '#00FF00'
    BLUE = 'B', 'Blue', '#0000FF'

# Usage
print(ColorChoices.RED.hex_code)  # Output: #FF0000

Code:

from django.db import models
# from accounts import CustomUser
from django.apps import apps
from django.conf import settings
from django.core.validators import MinValueValidator, MaxValueValidator
from datetime import datetime, timedelta , date
from dateutil.relativedelta import relativedelta
from django.utils import timezone

class MyPets(models.Model):

    class SexChoices(models.TextChoices):
        FEMALE = 'F', 'Female'
        MALE = 'M', 'Male'
        UNSPECIFIED = 'U', 'Unspecified'
        # You can add more comprehensive options as needed

     class FleaPlans(models.TextChoices):
        REVOLUTION = ('REV','Revolution - Monthly treatment/ every 31 days','Revolution')
        NONE = ('NON','No Treatment plan selected','None')

    def __new__(cls,value,desc,label):
                obj = str.__new__(cls,value)
                obj._value_ = value
                obj._label_ = label

                obj.desc = "description"
                # obj.cycle = "cycle"
                return obj


# it's used in this field
#
    flea_treatment_plan = models.CharField( max_length=3, default=FleaPlans.NONE,
choices=FleaPlans.choices, verbose_name='flea treatment plan')

Easiest way to see the error is via Python/Django Shell:

class FleaPlans(models.TextChoices):
    ...<44 lines>...
            return obj
  File "/home/edwardjs55/.virtualenvs/pet_venv/lib/python3.13/site-packages/django/db/models/enums.py", line 49, in __new__
    cls = super().__new__(metacls, classname, bases, classdict, **kwds)
  File "/usr/local/lib/python3.13/enum.py", line 568, in __new__
    enum_class = super().__new__(metacls, cls, bases, classdict, **kwds)
  File "/usr/local/lib/python3.13/enum.py", line 268, in __set_name__
    enum_member = enum_class._new_member_(enum_class, *args)
TypeError: MyPets.FleaPlans.__new__() missing 1 required positional argument: 'label'

解决方案

class FleaPlans(models.TextChoices):
    #  __new__ must come BEFORE the member declarations
    def __new__(cls, value, desc, label):
        obj = str.__new__(cls, value)   # value is what gets stored in the DB
        obj._value_ = value
        obj._label_ = label             # label is what Django shows in forms/admin
        obj.desc = desc                 # your custom extra field
        return obj

    # tuple order must match (value, desc, label)
    REVOLUTION = ('REV', 'Revolution - Monthly treatment/ every 31 days', 'Revolution')
    NONE       = ('NON', 'No treatment plan selected', 'None')


# Then you can access your field anywhere 
FleaPlans.REVOLUTION.value 
FleaPlans.REVOLUTION.label   
FleaPlans.REVOLUTION.desc
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章