我有一个带get_form方法的模型。
# models.py
from model_utils.managers import InheritanceManager
from breathingactivities.forms import ParentRecordForm, ChildRecordForm
class ParentRecord(models.Model):
....
objects = InheritanceManager()
def get_fields(self, exclude=('user')):
fields = self._meta.fields
return [(f.verbose_name, f.value_to_string(self)) for f in fields if not exclude.__contains__(f.name)]
@classmethod
def get_form(self, *args, **kwargs):
return ParentRecordForm
class ChildRecord(ParentRecord):
....
duration = DurationField(
_('Duration'),
help_text=_('placeholder'))
@classmethod
def get_form(self, *args, **kwargs):
return ChildRecordForm
我有一个视图,它使用这个get_form方法来确定纠正给定对象的形式。
# views.py
class ParentRecordUpdateView(UpdateView):
model = ParentRecord
form_class = ParentRecordForm
template_name = 'parentrecords/create.html'
def get_object(self, **kwargs):
return ParentRecord.objects.get_subclass(slug=self.kwargs['slug'])
def get_form_class(self, *args, **kwargs):
form_class = self.model.objects.get_subclass(slug=self.kwargs['slug']).get_form()
return form_class
def get_form_kwargs(self):
kwargs = super(ParentRecordUpdateView, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
我正在使用来自django-model-utils的InheritanceManager,所以当我查询父类时,我得到一个干净的API子类 - 这就是get_subclass()的东西,这就是我的视图与ParentRecord一起工作的原因。
这一切都很好。我通过控制台看到,form_class确实是我期望的表单类,例如ChildRecordForm,当实例是ChildRecord时。
在我的forms.py中,我不能只导入models.ParentRecord和models.ChildRecord,因为我在models.py中导入了这些表单,因此引发了Django无法导入这些模型的错误。我推测是因为循环进口。
所以,我试试这个:
# forms.py
from django.db.models import get_model
class ParentRecordForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super (ParentRecordForm, self).__init__(*args, **kwargs)
class Meta:
model = get_model('model', 'ParentRecord')
exclude = ('user')
class ChildRecordForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super (ChildRecordForm, self).__init__(*args, **kwargs)
class Meta:
model = get_model('model', 'ParentRecord')
exclude = ('user')
但是,这些表单的模型始终返回None。
我去传递ChildRecordForm一些完全不相关的模型,我可以从我项目中的不同应用程序导入,例如:
# forms.py
from another_app import AnotherModel
class ChildRecordForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
super (ChildRecordForm, self).__init__(*args, **kwargs)
class Meta:
model = AnotherModel
exclude = ('user')
然后它起作用,意思是,表单返回AnotherModel的字段。
所以,我无法弄清楚为什么get_model()在shell中适用于我,但在我使用它来为模型声明值时不能在表单类中使用。
答案 0 :(得分:2)
我对get_model()
的猜测是,在类定义级别运行它会产生不正确的结果,因为当Django填充其AppCache中的所有模型时,它会得到评估。我对django.db.models.loading
模块的快速阅读似乎没有显示该问题,但要尝试的一件事是在视图中运行get_model()
并打印出结果以查看如果它是您认为的那样,那么AppCache
应该完全加载。
但是 - 作为解决原始循环导入的一种解决方法(所以你不必使用get_model)就是不要在模块级别进行表单导入 - 你可以将它们粘贴在classmethod中:
class ParentRecord(models.Model):
@classmethod
def get_form(self, *args, **kwargs):
from yourapp.forms import BreathingActivityRecordForm
return BreathingActivityRecordForm
这样,只有在实际调用.get_form()
时才会导致导入,并且模块加载时不应存在任何循环依赖关系。