Django - объект не имеет атрибута 'object' при инъекции данных POST-формы

Гол

Я пытаюсь внедрить адреса/объекты электронной почты Job Site "Send BCC" в форму в качестве начального значения по умолчанию. Трудность, похоже, заключается в том, как он интерпретирует super().get_context_data(**kwargs), и представление каким-то образом пропускает объект(), который он ищет. Я не могу понять, в чем дело, несмотря на проверку на дублирование имен, определение self.object внутри post и get.

GitHub: https://github.com/varlenthegray/wcadmin/blob/dev/communication/views.py#L21

В попытках найти решение возникли следующие переполнения стека:

Ошибка

Environment:


Request Method: POST
Request URL: http://localhost:3003/email/compose_email

Django Version: 4.0.6
Python Version: 3.8.10
Installed Applications:
['customer',
 'equipment',
 'service',
 'supplier',
 'users',
 'qb',
 'communication',
 'main',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'django.contrib.humanize',
 'dateutil',
 'widget_tweaks',
 'intuitlib',
 'quickbooks',
 'rest_framework',
 'rest_framework_datatables',
 'markdownify']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback (most recent call last):
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/views/generic/base.py", line 84, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/contrib/auth/mixins.py", line 73, in dispatch
    return super().dispatch(request, *args, **kwargs)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/views/generic/base.py", line 119, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/wcadev/public_html/wcadmin/communication/views.py", line 92, in post
    response = super().form_invalid(form)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/views/generic/edit.py", line 69, in form_invalid
    return self.render_to_response(self.get_context_data(form=form))
  File "/home/wcadev/public_html/wcadmin/communication/views.py", line 28, in get_context_data
    context = super().get_context_data(**kwargs)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/views/generic/edit.py", line 75, in get_context_data
    return super().get_context_data(**kwargs)
  File "/home/wcadev/public_html/lib/python/Django-4.0.6-py3.8.egg/django/views/generic/detail.py", line 95, in get_context_data
    if self.object:

Exception Type: AttributeError at /email/compose_email
Exception Value: 'EmailHomepage' object has no attribute 'object'

Вид

class EmailHomepage(LoginRequiredMixin, generic.CreateView):
    model = EmailHistory
    template_name = 'communication/compose_email.html'
    form_class = CreateEmail
    success_url = '?sent=true'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['customers'] = JobSite.objects.filter(active=True).exclude(email=None)
        context['existing_templates'] = EmailTemplates.objects.all()
        return context

    def post(self, request, *args, **kwargs):
        data = request.POST.get('data')

        if data:
            # fancy footwork to get POST data and represent it as an array, then get objects from the array
            raw_job_site_ids = simplejson.loads(request.POST['data'])['body']
            job_site_ids = []

            # this has to be done, it's a 3D array initially with 1 array, [0] didn't work
            for js_id in raw_job_site_ids:
                job_site_ids.append(js_id[0])

            job_sites = JobSite.objects.filter(pk__in=job_site_ids)

            form = CreateEmail(request.POST, initial={'send_bcc': job_sites})
        else:
            form = CreateEmail(request.POST)

        if form.is_valid():
            form_save = form.save(commit=False)
            form_save.user = self.request.user
            draft = self.request.GET.get('draft')

            if draft:
                form_save.status = 'draft'
            else:
                form_save.status = 'sent'

                send_cc = []
                send_bcc = []

                for customer in form.cleaned_data.get('send_cc'):
                    send_cc.append(customer.email)

                for customer in form.cleaned_data.get('send_bcc'):
                    send_bcc.append(customer.email)

                message = EmailMultiAlternatives(
                    subject=form.cleaned_data.get('subject'),
                    body=form.cleaned_data.get('message'),
                    from_email='info@wcwater.com',
                    to=['info@wcwater.com'],
                    bcc=send_bcc,
                    cc=send_cc,
                )

                message.attach_alternative(markdown.markdown(form.cleaned_data.get('message')), 'text/html')

                message.send(fail_silently=False)

            form.save()

            if not draft:
                return super().form_valid(form)
            else:
                return HttpResponseRedirect('?save_draft=true')
        else:
            logger.warning('Email Form Invalid.')

            response = super().form_invalid(form)

            if self.request.accepts('text/html'):
                return response
            else:
                return JsonResponse(form.errors, status=400)

Модель

class EmailHistory(models.Model):
    send_bcc = models.ManyToManyField(Customer, blank=True, related_name='send_bcc')
    send_cc = models.ManyToManyField(Customer, blank=True, related_name='send_cc')
    subject = models.CharField(max_length=200)
    message = models.TextField()
    template_used = models.ForeignKey(EmailTemplates, on_delete=models.CASCADE, blank=True, null=True)
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, editable=False)
    status = models.CharField(max_length=50)
    timestamp = models.DateTimeField(auto_now_add=True, editable=False)

    class Meta:
        ordering = ['-timestamp']

    @property
    def bcc_as_comma(self):
        all_bcc = ''

        for customer in self.send_bcc.all():
            all_bcc += customer.email

            if self.send_bcc.count() > 1:
                all_bcc += ', '

        if self.send_bcc.count() > 1:
            return all_bcc[:-2]
        else:
            return all_bcc

    @property
    def cc_as_comma(self):
        all_cc = ''

        for customer in self.send_cc.all():
            all_cc += customer.email

            if self.send_cc.count() > 1:
                all_cc += ', '

        if self.send_bcc.count() > 1:
            return all_cc[:-2]
        else:
            return all_cc

Форма

class CreateEmail(forms.ModelForm):
    send_bcc = SendField(queryset=Customer.objects.all().exclude(email=None)
                         .order_by('first_name', 'last_name', 'company', 'email'), required=False)
    send_cc = SendField(queryset=User.objects.all().exclude(email='')
                        .order_by('first_name', 'last_name', 'username'), required=False)
    template_used = forms.ModelChoiceField(queryset=EmailTemplates.objects.all(), required=False)

    class Meta:
        model = EmailHistory
        fields = ['send_bcc', 'send_cc', 'subject', 'message', 'template_used']

Ну, я почти уверен, что это сводится к переходу от form_valid() и form_invalid(). Как только я переместил свой код обратно в этот метод (у меня он работал через этот метод), я решил эту конкретную ошибку. К сожалению, я все еще испытываю трудности с предварительным выбором значений, но, по крайней мере, это больше не мертво.

Вернуться на верх