1

全部,

我的模型上有几个自定义字段。我尝试在它们上添加“south_field_triple”方法以使数据库迁移工作。用南(“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的“枚举”参数指定)。与该字段关联的 FormField 和 Widget 分别使用 MultiValueField 和 MultiWidget 来向用户呈现一个组合框和一个单独的文本框,用户可以在其中输入他们自己的自定义值,而不是在原始枚举中。但是,在迁移应用程序中的模型的情况下 - 不提供枚举。

关于出了什么问题的任何想法?谢谢。

编辑:添加了堆栈跟踪

  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
4

1 回答 1

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)
于 2013-07-08T17:30:55.843 回答