django南迁移与自定义领域不起作用

时间:2013-07-07 19:46:10

标签: django django-south custom-fields

所有

我的模型上有几个自定义字段。我尝试在它们上添加“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

1 个答案:

答案 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)