Django:使用相同的视图在两个单独的页面上处理相同的表单

Posted

技术标签:

【中文标题】Django:使用相同的视图在两个单独的页面上处理相同的表单【英文标题】:Django: Use same view to process same form on two separate pages 【发布时间】:2016-04-20 00:10:23 【问题描述】:

我可能想多了,也可能没有。我有一个注册表单,我想在索引页面上使用它并作为一个独立的表单。出于某种原因,独立表单工作得很好,但索引页面上的表单在提交时给了我一个 403 错误。稍后我将使用 jQuery,但我需要在没有 javascript 的情况下也能工作。

呈现类似于 Facebook 主页的注册表单

# views.py snippet
class IndexPageTemplateView(TemplateView):  #  index page(http://localhost)
    template_name = 'fld/index.html'

    def get(self, request, *args, **kwargs):
    # prevent logged in users from accessing welcome page
    if self.request.user.is_authenticated():
        return HttpResponse(reverse("member_homepage", args=some_args))
    else:
        return render_to_response(self.template_name)

# Account view

class AccountCreateView(CreateView):  # standalone(http://localhost/signup)
      model = Account
      form_class = CreateAccountForm
      template_name = 'fld2/account_form'
      success_url = 'thanks'

    def get(self, request, *args, **kwargs):
    # prevent logged in users from seeing this form
    if self.request.user.is_authenticated():
        # get the username of logged in user
        ...
        # redirect to homepage
        return HttpResponseRedirect(reverse('some_args', args=(args,)))
    else:
        # display form to non members
        return render(request, self.template_name, 'form': self.get_form_class())

    def form_valid(self, form):
        clean = form.cleaned_data
        form.instance = form.save()
        if form.instance:
           try:
               # send email
           except Account.DoesNotExist:
           ...
        return super(AccountCreateView, self).form_valid(form)

我实际上是在使用具有不同动作属性的完全相同的形式。我尝试交换属性值,使用相同的属性值,并且不使用任何属性值。我似乎根本无法从索引页面访问我的视图,即使我在其中进行硬编码时也会收到 403 错误。基本上,访问者应该能够在主页(如 Facebook)或注册页面(如 Twitter)上注册。我在想我可能必须使用信号来完成这项工作。

http://localhost/

 <!--index.html snippet-->
 <form action="% url "create_account" %" method="post">% csrf_token %
    <input name="username" type="text" required>
    <input name="password" type="password" required>
    <input name="email" type="email" required>
    <input name="signup1" type="submit" value="Create account">
 </form>

http://localhost/signup

 <!--account_form.html-->
 <form action="." method="post">% csrf_token %
    <input name="username" type="text" required>
    <input name="password" type="password" required>
    <input name="email" type="email" required>       
    <input name="signup2" value="Create account" type="submit">
 </form>

主 urls.py sn-p

url(
    regex=r'^$',
    view=WelcomePageTemplateView.as_view(),
    name='index'
),
url(
    regex=r'^signup$',
    view=include('account.urls'),
    # name='signup'
),
url(
    regex=r'^(?P<slug>[\w]+)/settings/?',
    view=include('account.urls'),
)

帐户 urls.py

url(
    regex=r'^$',
    view=AccountCreateView.as_view(),
    name="create_account"
),

【问题讨论】:

不相关,但是为什么要手动渲染表单呢?你不能用 form.as_table form.as_table 之类的东西吗? 我想要更多地控制表单的呈现方式。 as_p 并没有真正为我提供。另外,我个人从不将表格用于非表格数据。 【参考方案1】:

% csrf_token % 标签需要访问模板中的请求对象。您在AccountCreateView 中使用了render,默认情况下包含请求,但在您的IndexPageTemplateView 中使用了render_to_response,但没有。

修复索引视图最简单的方法是使用render 而不是render_to_response

def get(self, request, *args, **kwargs):
    # prevent logged in users from accessing welcome page
    if self.request.user.is_authenticated():
        return HttpResponse(reverse("member_homepage", args=some_args))
    else:
        return render(request, self.template_name)

当您覆盖基于类的视图时,覆盖getpost 通常是个坏主意,因为您最终会复制(或破坏)功能。在您的情况下,最好调用 super() 而不是编写自己的代码来返回响应。

def get(self, request, *args, **kwargs):
    # prevent logged in users from accessing welcome page
    if self.request.user.is_authenticated():
        return HttpResponse(reverse("member_homepage", args=some_args))
    else:
        return super(IndexPageTemplateView, self).get(request, *args, **kwargs)

【讨论】:

谢谢。只是好奇,render_to_response 不只是在 render 之上的一层抽象吗? renderrender_to_response 都是快捷方式。不同之处在于render 使请求在模板上下文中可用,但render_to_response 没有。 render 快捷方式是在 render_to_response 之后添加的,但它早在 Django 1.3 中就已经可用。不推荐使用 render_to_response 快捷方式,将来可能会弃用。如果你总是使用render,那么你就不会出错! 太棒了!谢谢你。我有一些重构要做。

以上是关于Django:使用相同的视图在两个单独的页面上处理相同的表单的主要内容,如果未能解决你的问题,请参考以下文章

Django 在基于类的视图中处理多个表单

如何不在 Python、Django 中生成两次相同的动态图像?

如何使用 Vuejs 在单独的页面上显示详细视图

Django - 在多个页面上重用用户注册表单的系统架构

在每个页面上放置一个 django 登录表单

基本模板上的 Django 表单