所有
我的模型上有几个自定义字段。我尝试在它们上添加“south_field_triple”方法,以便让db迁移工作。使用south(“python manage.py convert_so_south myApp”)初始化我的应用程序。但是生成第一次迁移(“python manage.py schemamigration myApp --auto”)失败,并出现以下错误:
TypeError: type() takes 1 or 3 arguments
问题出现在以下字段中(我没有显示自定义FormField或Widget的代码;我认为这些与问题的原因无关):
class MyCustomField(models.CharField):
_type = "EnumerationField"
enumerationAppName = ""
enumerationModelName = ""
def __init__(self,*args,**kwargs):
enumeration = kwargs.pop('enumeration',None)
super(MyCustomField,self).__init__(*args,**kwargs)
if enumeration:
(self.enumerationAppName, self.enumerationModelName) = enumeration.split(".")
def getEnumeration(self):
try:
app = get_app(self.enumerationAppName)
enumeration = getattr(app,self.enumerationModelName)
return enumeration
except:
msg = "failed to get enumeration '%s.%s'" % (self.enumerationAppName,self.enumerationModelName)
print "error: %s" % msg
return None
def south_field_triple(self):
field_class_path = self.__class__.__module__ + "." + self.__class__.__name__
args,kwargs = introspector(self)
return (field_class_path,args,kwargs)
对于它的价值,该字段向用户提供一组选择。这些选择在另一个类中定义(由 init 的“enumeration”参数指定)。与此字段关联的FormField和Widget分别使用MultiValueField和MultiWidget向用户显示组合框和单独的文本框,用户可以在其中输入自己的自定义值,而不是原始枚举。但是,如果正在迁移应用程序中的模型,则不会提供枚举。
关于出了什么问题的任何想法?感谢。
编辑:添加了stacktrace
File "manage.py", line 11, in <module>
execute_manager(settings)
File "/usr/local/lib/python2.7/site-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 459, in execute_manager
utility.execute()
File "/usr/local/lib/python2.7/site-packages/Django-1.4-py2.7.egg/django/core/management/__init__.py", line 382, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 196, in run_from_argv
self.execute(*args, **options.__dict__)
File "/usr/local/lib/python2.7/site-packages/django/core/management/base.py", line 232, in execute
output = self.handle(*args, **options)
File "/usr/local/lib/python2.7/site-packages/south/management/commands/schemamigration.py", line 97, in handle
old_orm = last_migration.orm(),
File "/usr/local/lib/python2.7/site-packages/south/utils.py", line 62, in method
value = function(self)
File "/usr/local/lib/python2.7/site-packages/south/migration/base.py", line 422, in orm
return FakeORM(self.migration_class(), self.app_label())
File "/usr/local/lib/python2.7/site-packages/south/orm.py", line 46, in FakeORM
_orm_cache[args] = _FakeORM(*args)
File "/usr/local/lib/python2.7/site-packages/south/orm.py", line 126, in __init__
self.models[name] = self.make_model(app_label, model_name, data)
File "/usr/local/lib/python2.7/site-packages/south/orm.py", line 320, in make_model
field = self.eval_in_context(code, app, extra_imports)
File "/usr/local/lib/python2.7/site-packages/south/orm.py", line 238, in eval_in_context
return eval(code, globals(), fake_locals)
File "<string>", line 1, in <module>
TypeError: type() takes 1 or 3 arguments
答案 0 :(得分:0)
啊哈!事实证明,这是导致问题的另一个自定义领域;一个使用工厂方法创建的。
class MyOtherCustomField(models.Field):
def __init__(self,*args,**kwargs):
super(MyOtherCustomField,self).__init__(**kwargs)
@classmethod
def Factory(cls,model_field_class_name,**kwargs):
try:
# there is a global dictionary of potential field_classes and extra kwargs to pass to the constructor
model_field_class_info = MODELFIELD_MAP[model_field_class_name.lower()]
model_field_class = model_field_class_info[0]
model_field_class_kwargs = model_field_class_info[1]
except KeyError:
msg = "unknown field type: '%s'" % model_field_class_name
print "error: %s" % msg
raise MyError(msg)
class _MyOtherCustomField(cls,model_field_class):
def __init__(self,*args,**kwargs):
kwargs.update(model_field_class_kwargs)
super(_MyOtherCustomField,self).__init__(**kwargs)
self._type = model_field_class_name
def south_field_triple(self):
# I was doing this which didn't work...
#field_class_path = self.__class__.__module__ + "." + self.__class__.__name__
# I'm now doing this which does work...
field_class_path = "django.db.models.fields" + "." + model_field_class.__name__
args,kwargs = introspector(self)
return (field_class_path,args,kwargs)
return _MyOtherCustomField(**kwargs)