2013-07-07 78 views
1

全部,django南遷移與自定義字段不工作

我在我的模型上有幾個自定義字段。我曾嘗試在其上添加「south_field_triple」方法以獲得數據庫遷移工作。初始化我的應用程序與南(「python manage.py convert_so_south myApp」)的作品。但產生第一遷移(「蟒manage.py schemamigration對myApp --auto」)失敗,錯誤如下:

TypeError: type() takes 1 or 3 arguments 

問題是與以下字段存在的(我不顯示自定義代碼FormField或工具;我認爲這些都沒有涉及到問題的原因):

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 
+0

你可以發佈stacktrace嗎? – Thomas

回答

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)