Я думаю, что создание подклассов усложняет ситуацию, поскольку подкласс содержит только одну или две строки. Вы можете сделать следующее:
def class_id(s):
"""Convert input string from PascalCase to kebab-case"""
import re
return re.sub(r'(?<!^)(?=[A-Z])', '-', s).lower() + '-'
class MyClass(object):
form_name = class_id(__qualname__)
print(f"{form_name}attribute")
class OtherClass(object):
form_name = class_id(__qualname__)
print(f"{form_name}attribute")
>>> MyClass()
>>> OtherClass()
my-class-attribute
other-class-attribute
edit: извините, полностью пропустил часть об автоматическом id
c, тогда потребуется подклассификация, простой подход будет:
def AdjStringField(form_name, **kwargs):
name = kwargs.get('name', 'Bar')
return wtf.StringField(name, render_kw={
'id': f'{}{}'.format(form_name, name.lower(),
**kwargs.get('render_kw', {})})
class FooForm(FlaskForm):
form_name = class_id(__qualname__)
bar = AdjStringField(form_name)
pipe = AdjStringField(form_name, name='Pipe', render_kw={'foo': 'bar'})
Вы можете перегрузить это для любого типа поля ввода, если вы указали его как в объекте аргумента:
def AdjField(Field, form_name, **kwargs):
name = kwargs.get('name', 'Bar')
return Field(name, render_kw={
'id': f'{}{}'.format(form_name, name.lower(),
**kwargs.get('render_kw', {})})
>>> AdjField(wtf.StringField, 'form-name')
>>> AdjField(wtf.InputBox, 'other-name', name='Pipe', render_kw={'foo': 'bar'})