2014-02-26 41 views
0

我試圖動態生成模型mixin。django:ModelForm中未顯示動態創建的模型mixin的字段

我在使用ModelForm時看到字段存在問題,但在最終模型中存在 字段。

def create_address_fields_mixin(prefix='', fields_kwargs={}): 

    class AddressFieldsModelMixin(models.Model): 
     class Meta: 
      abstract = True 

    fields = { 
     'address_line_1': (AddressLineModelField, {'editable': True}), 
     'address_line_2': (AddressLineModelField, {'blank':True, 'null':True}), 
     'city': (CityModelField, {}), 
     'state': (USStateModelField, {}), 
     'zipcode': (USZipCodeModelField, {}) 
    } 

    for field_name, (field_klass, kwargs) in fields.iteritems(): 

     name = '{}{}'.format(prefix, field_name) 
     kwargs.update(fields_kwargs.get(field_name, {})) 

     setattr(
      AddressFieldsModelMixin, 
      name, 
      field_klass(**kwargs) 
     ) 

    return AddressFieldsModelMixin 


AddressModelMixin = create_address_fields_mixin(prefix='main_') 

class User(AddressModelMixin, TimeStampedModel): 
    pass 

創建模型和訪問領域的工作:

u = User() 
u.main_address_line_1 # works 

但使用的ModelForm時,該領域似乎並不存在:

class UserForm(ModelForm):  
    class Meta: 
     model = User 

f = UserForm() 
f.fields # the fields from the model mixin do not exist 

的ModelForm如何認定的領域該模型?

回答

0

我想你應該總是明確列出你的ModelForm中的字段,因爲它在DjangoDocs中完成。

所以這可能幫助:

class UserForm(ModelForm):  
    class Meta: 
     model = User 
     fields = '__all__' 
+0

請添加一些說明,同時回答。 – InnocentKiller

+0

感謝您的回覆。這是行不通的。我也嘗試明確列出這些字段,但它不適用。 我想我明白問題在哪裏。即使「u.main_address_line_1」有效,這些字段似乎並不真正「成爲模型的一部分」。在''django.db.models.base.Model''的init方法中,它看起來像是使用self._meta.fields或self._meta_concrete_fields這些字段。我不明白django如何處理字段,但我的Mixin的字段不在這兩個字段中......我不知道爲什麼我的字段沒有正常添加。 – Michael

0

好,我找到了解決辦法。 問題是我動態創建模型的方式。這些字段並未真正添加到模型中。

這裏是解決方案,以便它可以幫助別人誰遇到同樣的問題:

def create_model_mixin(model_name, model_base, model_definition, fields_prefix='', fields_kwargs={}): 
    # Build the class attributes 
    attrs = {} 
    attrs['__module__'] = __name__ 

    # Create the relevant meta information 
    class Meta: 
     abstract = True 

    attrs['Meta'] = Meta 

    # Build the model by adding django database Field subclasses to the attrs dict 
    for field_name, field_klass, kwargs in model_definition['fields']: 
     name = '{}{}'.format(fields_prefix, field_name) 
     kwargs.update(fields_kwargs.get(field_name, {})) 
     attrs[name] = field_klass(**kwargs) 

    # Create the new model class 
    model_class = type(model_name, (model_base,), attrs) 

    return model_class 

你也可以使用這種方式:

model_name = 'AddressModelMixin' 
model_base = models.Model 
model_definition = { 
    'fields': [ 
     ('address_line_1', AddressLineModelField, {}), 
     ('address_line_2', AddressLineModelField, {'blank':True, 'null':True}), 
     ('city', CityModelField, {}), 
     ('state', USStateModelField, {}), 
     ('zipcode', USZipCodeModelField, {}) 
    ] 
} 

model_class = create_model_mixin(model_name, model_base, model_definition, fields_prefix='my_prefix')