为什么没有为StringField/flask调用\uuu set\u name\uuuuu_

2024-10-03 00:22:53 发布

您现在位置:Python中文网/ 问答频道 /正文

任何人都知道为什么在StringField/flask\uwtf类中没有调用hookset\u name(由装饰函数添加)。当它被称为“简单构造”类时?如以下代码所示:

from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField, SelectField, IntegerField
from wtforms.validators import DataRequired, Email, ValidationError, StopValidation
from flask import Flask, render_template, flash, redirect, url_for, request, jsonify, session

def AddSetName(Cl) :
    class ClsWithSetName(Cl):
        def __set_name__(self, owner, name):
            print("Set Name ", self, owner, name,super(Cl,self))
#            super(Cl,self).__set_name__(self,owner,name)
            self.key = name
            try:
                owner.KeyFields.append(name)
            except :
                owner.KeyFields = [name]

    return ClsWithSetName

class Trait(object):
    def __init__(self, minimum, maximum):
        self.minimum = minimum
        self.maximum = maximum

    def __get__(self, instance, owner):
        print("get called ", self, instance, owner)
        return instance.__dict__[self.key]

    def __set__(self, instance, value):
        print("Set called ", self, instance, value)
        if self.minimum < value < self.maximum:
            instance.__dict__[self.key] = value
        else:
            raise ValueError("value not in range")

Trait = AddSetName(Trait)
StringField = AddSetName(StringField)

class T1:
    Val1=Trait(0,10)
    Val2=Trait(0,5)

class FrmLogin(FlaskForm):
    username=StringField('username', validators=[DataRequired])
    password=StringField('password', validators=[DataRequired])

if __name__ == '__main__':
    pass
    print(dir(StringField))
#    x = T1()
#    x.Val1 = 8
#    x.Val2 = 4
#    print(x)
#    print(T1.KeyFields)

>>> Set Name  <__main__.AddSetName.<locals>.ClsWithSetName object at 0x0000018E2A0FDD88> <class '__main__.T1'> Val1 <super: <class 'Trait'>, <ClsWithSetName object>>
>>>Set Name  <__main__.AddSetName.<locals>.ClsWithSetName object at 0x0000018E2A0FDE08> <class '__main__.T1'> Val2 <super: <class 'Trait'>, <ClsWithSetName object>>
>>>['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__html__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', '__weakref__', '_formfield', '_run_validation_chain', '_translations', '_value', 'do_not_call_in_templates', 'errors', 'gettext', 'ngettext', 'populate_obj', 'post_validate', 'pre_validate', 'process', 'process_data', 'process_errors', 'process_formdata', 'raw_data', 'validate', 'validators', 'widget']

输出不显示任何为StringField设置\u name的调用!你知道吗

有没有建议“重新激活”或模仿这个电话?你知道吗


Tags: instancenameselfobjectvaluemaindefclass
1条回答
网友
1楼 · 发布于 2024-10-03 00:22:53

有一种情况可能会导致类的“不调用设置名称”(non call toset\u name):当类包含new的定义时,该定义不会按预期返回对象的实例(不返回任何实例)。如果没有这个实例,python就不会调用该类的init也不会set\u name。你知道吗

我试着用StringField组件来分析这个案例:

from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired
from flask import Flask


app = Flask(__name__ )

@app.route('/', methods=['GET', 'POST'])
def MainPage():
    Frm = FrmLogin()


def AddSetName(Cl) :
    class ClsWithSetName(Cl):
        def __new__(cls, *args, **Kargs):
            if len(Kargs) == 0 :
                inst = super(ClsWithSetName, cls).__new__(cls)
            else:
                inst = super(ClsWithSetName, cls).__new__(cls, *args, **Kargs)
            print("new ", inst)
            return inst

        def __init__(self, *args, **Kargs):
            super(ClsWithSetName, self).__init__(*args, **Kargs)
            print("init get called")

        def __set_name__(self, owner, name):
            print("Set Name ", self, owner, name,super(Cl,self))
#            super(Cl,self).__set_name__(self,owner,name)
            self.key = name
            try:
                owner.KeyFields.append(name)
            except :
                owner.KeyFields = [name]

    return ClsWithSetName

class Trait(object):
    def __init__(self, minimum, maximum):
        self.minimum = minimum
        self.maximum = maximum

    def __get__(self, instance, owner):
        print("get called ", self, instance, owner)
        return instance.__dict__[self.key]

    def __set__(self, instance, value):
        print("Set called ", self, instance, value)
        if self.minimum < value < self.maximum:
            instance.__dict__[self.key] = value
        else:
            raise ValueError("value not in range")

Trait = AddSetName(Trait)
StringField = AddSetName(StringField)

class T1:
    Val1=Trait(0,10)
#    Val2=Trait(0,5)
    pass

class FrmLogin(FlaskForm):
    username=StringField('username', validators=[DataRequired])
#    password=StringField('password', validators=[DataRequired])
    pass

if __name__ == '__main__':
    pass

>>> new  <__main__.AddSetName.<locals>.ClsWithSetName object at 0x0000017F46386348>
>>> init get called
>>> Set Name  <__main__.AddSetName.<locals>.ClsWithSetName object at 0x0000017F46386348> <class '__main__.T1'> Val1 <super: <class 'Trait'>, <ClsWithSetName object>>

>>> new  <UnboundField(ClsWithSetName, ('username',), {'validators': [<class 'wtforms.validators.DataRequired'>]})>

如果我们在new钩子中刷出'return'指令,则既不会调用init也不会调用set\u name。 同时,打印显示原始new调用为“Trait”字段返回一个对象(在特定地址),而对于StringField,它不返回对象(没有与之关联的地址),而是返回一个名为“UnboundField”的类。 但是,不从new返回对象是一种不寻常的行为,对象实例的丢失使得initset\u name的调用没有意义。你知道吗

这也许可以回答我的问题“为什么set\u name不被调用”,但它并没有提供一个替代方法来模仿它。你知道吗

相关问题 更多 >