Встроенный набор форм, вызывающий ошибку: объект 'NoneType' не имеет атрибута 'is_ajax' - PullRequest
0 голосов
/ 08 мая 2019

Я использую 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)

My 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,
)

My 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)

Я ожидаю, что пользователь сможет добавлять столько изображений в модальный набор форм, сколько ему захочется.

1 Ответ

1 голос
/ 08 мая 2019

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})

Обратите внимание, что я думаю, что form, установленный в ProjectFormSet, неверен, потому что это должна быть форма для модели ProjectImage, а не Project.На самом деле его следует назвать ProjectImageFormSet, чтобы лучше отразить, что это такое.

Вы, вероятно, хотите удалить form=ProjectForm, поскольку это, вероятно, не обязательно должен быть BSModalForm (не уверен в этом).В этом случае вы не должны передавать request в form_kwargs.Если нет, вам просто нужно создать еще один ProjectImageForm класс.

Наконец, вам не следует return super().form_valid(), потому что это сохранит основную форму во второй раз (вы это уже сделали).Сделайте перенаправление самостоятельно.

...