django - 各种动态django表单集抛出missing_management_form错误
问题描述
当我动态构建多个表单集时,我在验证 django 表单集时遇到问题在这种情况下,一个客户可能是各种品牌并联系人们。
模型.py
class Client(ChangesMixin, models.Model):
name = models.CharField(verbose_name="Nombre", max_length=100, unique=True)
code = models.PositiveIntegerField(verbose_name="Código", blank=True)
class Meta:
verbose_name = "Cliente"
verbose_name_plural = "Clientes"
class Brand(ChangesMixin, models.Model):
name = models.CharField(verbose_name="Marca", max_length=100, blank=True, null=True)
client = models.ForeignKey('Client', verbose_name="Cliente", related_name='brand_client', on_delete=models.DO_NOTHING)
class Meta:
verbose_name = "Marca"
verbose_name_plural = "Marcas"
class Contact(ChangesMixin, models.Model):
name = models.CharField(verbose_name="Contacto", max_length=100, blank=True, null=True)
client = models.ForeignKey('Client', verbose_name="Cliente", related_name='contact_client', on_delete=models.DO_NOTHING)
class Meta:
verbose_name = "Contacto"
verbose_name_plural = "Contactos"
我有两种动态创建表单和表单集的方法
表格.py
def get_custom_formset(entry_model=None, entry_fields=None, action=None):
formset = None
if action == 'create':
extra = 1
else:
extra = 0
formset = modelformset_factory(
model = entry_model,
extra = extra,
form = get_custom_form(entry_model, entry_fields, action)
return formset
def get_custom_form(entry_model=None, entry_fields=None, action=None):
class _CustomForm(forms.ModelForm):
class Meta:
model = entry_model
fields = [field.name for field in entry_fields]
def __init__(self, *args, **kwargs):
"""
"""
super(_CustomForm, self).__init__(*args, **kwargs)
instance = getattr(self, 'instance', None)
if instance and instance.pk:
for field in entry_fields:
if action == 'detail':
self.fields[field.name].widget.attrs['readonly'] = True
return _CustomForm
我有一个带有 get 和 post 方法的创建类视图,取决于传递的模型。我得到模型字段来构建表单,如果一个字段是外键,我用这些具体模型构建表单集。
视图.py
class CustomCreateView(LoginRequiredMixin, View, PermissionRequiredMixin):
model = None
template = 'create.html'
def get(self, request, *args, **kwargs):
template_form = str(self.model._meta.verbose_name).lower() + "_form.html"
model_fields = self.model._meta.get_fields()
form = None
formset = None
formsets = {}
for main_field in model_fields:
main_field_name = main_field.__class__.__name__
if main_field_name == 'ManyToOneRel':
model_names = str(main_field.name).split("_")
submodel = apps.get_model('app', model_names[0])
submodel_fields = submodel._meta.get_fields()
formset = app_forms.get_custom_formset(submodel, submodel_fields, 'create')
queryset = submodel.objects.none()
UPDATED with SOLUTION
formset = formset(queryset=queryset, prefix=submodel.__name__.lower())
formsets[submodel._meta.verbose_name.lower()] = formset
elif main_field_name == 'ManyToManyField':
print("NOT PROVIDED YET")
form = app_forms.get_custom_form(self.model, model_fields, 'create')
form = form(prefix=self.model.__name__.lower())
return render(request, self.template, {
'form': form,
'formsets': formsets,
'template_form': template_form,
})
def post(self, request, *args, **kwargs):
template_form = str(self.model._meta.verbose_name).lower() + "_form.html"
model_fields = self.model._meta.get_fields()
for main_field in model_fields:
main_field_name = main_field.__class__.__name__
if main_field_name == 'ManyToOneRel':
model_names = str(main_field.name).split("_")
submodel = apps.get_model('app', model_names[0])
submodel_fields = submodel._meta.get_fields()
formset = app_forms.get_custom_formset(submodel, submodel_fields, 'create')
queryset = submodel.objects.none()
formset = formset(queryset=queryset, prefix=submodel.__name__.lower())
formsets[submodel.__name__.lower()] = formset
elif main_field_name == 'ManyToManyField':
print("NOT PROVIDED YET")
form = app_forms.get_custom_form(self.model, model_fields, 'create')
form = form(request.POST, prefix=self.model.__name__.lower())
for prefix, formset in formsets.items():
formset = formset.__class__(request_post, prefix=prefix)
if formset.is_valid() and form.is_valid(): HERE THROWS THE ERROR
对于模板,我有 3 个级别来动态构建表单和表单集
创建.html
{% get_url urls 'create' as element_create %}
<form class="" action="{% url element_create %}" method="POST">
{% csrf_token %}
{% include template_form %}
{% if formsets|length > 0 %}
{% for subtemplateformname, formset in formsets.items %}
{% include 'formset.html' %}
{% endfor %}
{% endif %}
</form>
表单集.html
{{ formset.management_form }}
{% for form in formset %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% include 'form.html' %}
{% endfor %}
表单.html
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{{ field|add_class:"form-control" }}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
解决方案
首先,当您获得相关模型的表单集时,您会通过sub_fields
但我不知道这是从哪里来的?
formset = app_forms.get_custom_formset(submodel, sub_fields, 'create')
错误在于您定义表单集前缀的方式。在您传递的 GET 中model_names[0]
,对于正常的关系,模型名称将是小写的,没有任何空格。让我们使用一个名为MyModel
例如的模型
main_field.name # 'mymodel_set'
model_names = str(main_field.name).split("_") # ['mymodel', 'set']
model_names[0] # 'mymodel'
formset = formset(queryset=queryset, prefix=model_names[0])
当您将表单集分配给formsets
字典时,您使用的是不同的东西,即使您对待它是一样的
formsets[submodel._meta.verbose_name.lower()] = formset
...
for prefix, formset in formsets.items():
formset = formset.__class__(request_post, prefix=prefix)
submodel._meta.verbose_name
将返回带有空格的模型名称。因此,任何在其详细名称中包含 2 个“单词”的模型都不会设置正确的前缀(例如MyModel._meta.verbose_name.lower() == 'my model'
but model_names[0] == 'mymodel'
)
推荐阅读
- ios - 在保持设备横向样式时关闭 imagePickerController 会导致我的应用程序旋转到横向模式(但我的应用程序仅是纵向的)
- python - 什么激活函数适用于 Keras 中回归神经网络的输入范围 (0,1) 和输出范围 (-∞,∞)
- c# - xamarin 形式中是否有类似于 Unity void Update() 的东西?
- r - 在基础 R、ggplot2 或 levelplot 中绘制带有栅格的多边形
- php - 以 HTML 格式发送 Shell 脚本
- r - 美学必须是长度 1
- php - 带有 EFS 和 docker 容器的 ec2 实例上的“配额超出 (122)”错误
- python - 以小数形式返回量子位状态的机会
- c# - Mathf.PingPong 从 1 到 0
- amazon-web-services - 如何使用 AWS Gateway 和 S3 代理上传大文件