1fromplain.assets.urlsimportget_asset_url 2fromplain.httpimportResponseRedirect 3fromplain.runtimeimportsettings 4fromplain.utils.module_loadingimportimport_string 5fromplain.viewsimportFormView,View 6fromplain.views.csrfimportCsrfExemptViewMixin 7 8 9classSupportFormView(FormView):10template_name="support/page.html"1112defget_form(self):13form_slug=self.url_kwargs["form_slug"]14form_class=import_string(settings.SUPPORT_FORMS[form_slug])15returnform_class(**self.get_form_kwargs())1617defget_template_context(self):18context=super().get_template_context()19form_slug=self.url_kwargs["form_slug"]20context["form_action"]=self.request.build_absolute_uri()21context["form_template_name"]=f"support/forms/{form_slug}.html"22context["success_template_name"]=f"support/success/{form_slug}.html"23context["success"]=self.request.query_params.get("success")=="true"24returncontext2526defget_form_kwargs(self):27kwargs=super().get_form_kwargs()28kwargs["user"]=self.request.user29kwargs["form_slug"]=self.url_kwargs["form_slug"]30returnkwargs3132defform_valid(self,form):33entry=form.save()34form.notify(entry)35returnsuper().form_valid(form)3637defget_success_url(self,form):38# Redirect to the same view and template so we39# don't have to create two additional views for iframe and non-iframe.40return"?success=true"414243classSupportIFrameView(CsrfExemptViewMixin,SupportFormView):44template_name="support/iframe.html"4546defget_response(self):47response=super().get_response()4849# X-Frame-Options are typically in DEFAULT_RESPONSE_HEADERS,50# which will know to drop the header completely if an empty string.51# We can't del/pop it because DEFAULT_RESPONSE_HEADERS may add it back.52response.headers["X-Frame-Options"]=""5354returnresponse555657classSupportFormJSView(View):58defget(self):59returnResponseRedirect(get_asset_url("support/embed.js"))