Inline formset causing error: 'NoneType' object has no attribute 'is_ajax'
Inline formset causing error: 'NoneType' object has no attribute 'is_ajax'
我正在使用 bootstrap-modal-forms 向用户显示带有一些内联表单的表单集。如果数据仅输入到原始表单中,用户可以保存表单,但如果内联表单集有数据,则会出现以下错误:
'NoneType' object has no attribute 'is_ajax'
在我尝试以模态形式实现内联表单集之前,它们工作正常。问题似乎只有在保存内联表单集 (projectimages) 时才会出现,它是 NoneType。
我的views.py
class ProjectCreate(BSModalCreateView):
form_class = ProjectForm
template_name = 'project_form.html'
success_message = 'Success: %(project_name)s was created.'
def get_success_url(self):
return reverse_lazy('project-detail', kwargs={'project': self.object.slug})
def get_context_data(self, **kwargs):
data = super(ProjectCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['projectimages'] = ProjectFormSet(self.request.POST, self.request.FILES,)
else:
data['projectimages'] = ProjectFormSet()
return data
def form_valid(self, form):
form.instance.date_created = timezone.now()
context = self.get_context_data()
projectimages = context['projectimages']
with transaction.atomic():
self.object = form.save()
if projectimages.is_valid():
projectimages.instance = self.object
projectimages.save()
return super(ProjectCreate, self).form_valid(form)
我的forms.py
class ProjectForm(BSModalForm):
class Meta:
model = Project
exclude = ['date_created', 'slug']
ProjectFormSet = inlineformset_factory(
Project,
ProjectImage,
can_delete=True,
form=ProjectForm,
extra=1,
)
我的models.py
class Project(models.Model):
project_name = models.CharField(max_length=100)
date_created = models.DateTimeField('Created on')
slug = models.SlugField(unique=True)
def __str__(self):
return self.project_name
def save(self, *args, **kwargs):
self.slug = slugify(str(self))
super(Project, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('project-list')
class ProjectImage(models.Model):
image = models.ImageField(verbose_name='Additional Images', upload_to=project_directory_path)
project = models.ForeignKey(Project, on_delete=models.PROTECT)
annotation = models.CharField(max_length=200, blank=True)
我希望用户能够向模态表单集添加任意数量的图像。
BSModalForm
希望您使用 request
对其进行初始化。这发生在您的 BSModalCreateView
主表单中,但不是您的表单集,因为您手动初始化它。
所以在初始化时,只需添加form_kwargs
属性:
if self.request.POST:
data['projectimages'] = ProjectFormSet(
self.request.POST, self.request.FILES,
form_kwargs={'request': self.request})
else:
data['projectimages'] = ProjectFormSet(form_kwargs={'request': self.request})
请注意,我认为您在ProjectFormSet
中设置的form
是错误的,因为它应该是ProjectImage
模型的形式,而不是Project
。它实际上应该被称为 ProjectImageFormSet
以更好地反映它是什么。
您可能想要删除 form=ProjectForm
,因为它可能不需要是 BSModalForm
(对此不确定)。在那种情况下,您不应在 form_kwargs
中传递 request
。如果没有,你只需要创建另一个 ProjectImageForm
class.
最后,您不应该 return super().form_valid()
因为那样会再次保存主窗体(您已经这样做了)。自己做重定向。
我正在使用 bootstrap-modal-forms 向用户显示带有一些内联表单的表单集。如果数据仅输入到原始表单中,用户可以保存表单,但如果内联表单集有数据,则会出现以下错误:
'NoneType' object has no attribute 'is_ajax'
在我尝试以模态形式实现内联表单集之前,它们工作正常。问题似乎只有在保存内联表单集 (projectimages) 时才会出现,它是 NoneType。
我的views.py
class ProjectCreate(BSModalCreateView):
form_class = ProjectForm
template_name = 'project_form.html'
success_message = 'Success: %(project_name)s was created.'
def get_success_url(self):
return reverse_lazy('project-detail', kwargs={'project': self.object.slug})
def get_context_data(self, **kwargs):
data = super(ProjectCreate, self).get_context_data(**kwargs)
if self.request.POST:
data['projectimages'] = ProjectFormSet(self.request.POST, self.request.FILES,)
else:
data['projectimages'] = ProjectFormSet()
return data
def form_valid(self, form):
form.instance.date_created = timezone.now()
context = self.get_context_data()
projectimages = context['projectimages']
with transaction.atomic():
self.object = form.save()
if projectimages.is_valid():
projectimages.instance = self.object
projectimages.save()
return super(ProjectCreate, self).form_valid(form)
我的forms.py
class ProjectForm(BSModalForm):
class Meta:
model = Project
exclude = ['date_created', 'slug']
ProjectFormSet = inlineformset_factory(
Project,
ProjectImage,
can_delete=True,
form=ProjectForm,
extra=1,
)
我的models.py
class Project(models.Model):
project_name = models.CharField(max_length=100)
date_created = models.DateTimeField('Created on')
slug = models.SlugField(unique=True)
def __str__(self):
return self.project_name
def save(self, *args, **kwargs):
self.slug = slugify(str(self))
super(Project, self).save(*args, **kwargs)
def get_absolute_url(self):
return reverse('project-list')
class ProjectImage(models.Model):
image = models.ImageField(verbose_name='Additional Images', upload_to=project_directory_path)
project = models.ForeignKey(Project, on_delete=models.PROTECT)
annotation = models.CharField(max_length=200, blank=True)
我希望用户能够向模态表单集添加任意数量的图像。
BSModalForm
希望您使用 request
对其进行初始化。这发生在您的 BSModalCreateView
主表单中,但不是您的表单集,因为您手动初始化它。
所以在初始化时,只需添加form_kwargs
属性:
if self.request.POST:
data['projectimages'] = ProjectFormSet(
self.request.POST, self.request.FILES,
form_kwargs={'request': self.request})
else:
data['projectimages'] = ProjectFormSet(form_kwargs={'request': self.request})
请注意,我认为您在ProjectFormSet
中设置的form
是错误的,因为它应该是ProjectImage
模型的形式,而不是Project
。它实际上应该被称为 ProjectImageFormSet
以更好地反映它是什么。
您可能想要删除 form=ProjectForm
,因为它可能不需要是 BSModalForm
(对此不确定)。在那种情况下,您不应在 form_kwargs
中传递 request
。如果没有,你只需要创建另一个 ProjectImageForm
class.
最后,您不应该 return super().form_valid()
因为那样会再次保存主窗体(您已经这样做了)。自己做重定向。