POST 后的 Django 表单重定向不可靠,需要 success_url
Django form redirect after POST is unreliable and needed a success_url
我完全无法理解这种行为,并找到了一个我不太喜欢的解决方法。任何人都可以帮助启发我吗?上下文是我有一个 bootstrap 样式的表单来创建新记录(继承自 generic.CreateView)
url.py:
url(r'^$', home, name='home'),
url(r'^main/$', views.MainView.as_view(), name='MainView'),
url(r'^topic/(?P<pk>[0-9]+)/$', catalogue_views.TopicView.as_view(), name='TopicView'),
url(r'^resource/(?P<pk>[0-9]+)/$', catalogue_views.DetailView.as_view(), name='ResourceDetail'),
url(r'^contribute/$', catalogue_views.ContributeView.as_view(success_url="/main/"), name='Contribute'),
views.py:
class ContributeView(generic.CreateView):
template_name = "openeye/contribute.html"
form_class = ContributeForm
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ContributeView, self).dispatch(*args, **kwargs)
class MainView(generic.ListView):
template_name = "openeye/main.html"
context_object_name = 'topic_list'
# TODO Make this only active topic areas?
def get_queryset(self):
return TopicArea.objects.all().order_by('name')
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(MainView, self).dispatch(*args, **kwargs)
forms.py:
class ContributeForm(forms.ModelForm):
class Meta:
model = CatalogueItem
fields = ['title', 'topic_area', 'description', 'link', 'what_learn', 'how_apply', 'level', 'relevant_to', 'discovered_by']
ROLE_CHOICES = [[x.id, x.job] for x in JobType.objects.all()]
title = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'To sell this resource to others'}), max_length=80, required=True)
description = forms.CharField(widget=forms.Textarea(attrs={'rows': 2, 'placeholder': 'Clear, e.g. format, duration, activities...'}))
link = forms.CharField(widget=forms.URLInput(attrs={'placeholder': 'If required, link to resource http://...'}), required=False)
what_learn = forms.CharField(widget=forms.Textarea(attrs={'rows': 3, 'placeholder':"This is important,."}), label='What will you learn?')
how_apply = forms.CharField(widget=forms.Textarea(attrs={'rows': 3, 'placeholder':"How could this be put into action afterwards?"}), label='How could you apply this?')
relevant_to = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=ROLE_CHOICES)
和一个带有表单的模板:
<div class="container">
<div class="entry-form row">
<div class="col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-10 col-xs-offset-1">
<form action="{% url 'MainView' %}" method="post" class="form">
<input type="hidden" name="next" value="{{ next }}">
{% bootstrap_form form %}
<button class="btn btn-primary btn-lg" type="submit">Submit Suggestion</button>
{% csrf_token %}
</form>
</div>
</div>
表单完美运行,数据很好地保存到数据库中。问题是之后,浏览器转到正确的 URL /main/ 但屏幕是空白的。服务器显示 HTTP 405 0,如果我刷新页面,它就会工作。
如果我改变模板,使 action="{% url 'Contribute' %}" 到 return 相同的形式,我会收到 HTTP 500 和一条 Django 消息关于'No URL to redirect to'。所以由重定向位置决定的两个不同的错误。在这两种情况下,如果我只是点击浏览器 url 字段并点击 return 就可以了。
我确信这最初是有效的,然后就坏了,但我按如下方式解决了它。 success_url 中的硬代码使用它的路径
url(r'^contribute/$', catalogue_views.ContributeView.as_view(success_url="/main/"), name='Contribute'),
正在删除模板中的任何操作 link:
<form action="" method="post" class="form">
这是正确的做法吗?为什么,尽管转到了正确的 URLs,页面仍然无法加载或使用我的原始方法出错?我很想了解这一点。
您确定您的数据确实保存在服务器上吗?从您发布的内容来看,这似乎不太可能。下面是Django遵循的正常流程:
- 在表单视图 (ContributeView) 上获取
→ returns 一个空表格
- POST 在表单视图 (ContributeView) 上
→ 如果无效,返回步骤 1。如果有效 return a
302 Redirect
to success_url
.
- 在 success_url
上获得
所以通常情况下,在您的模板中,表单操作应该是空的,这样表单就会被发送回生成它的视图。 ContributeView
应该会成功 url 重定向到你想发送给用户的任何地方:
from django.core.urlresolvers import reverse_lazy
class ContributeView(generic.CreateView):
# other stuff
success_url = reverse_lazy('MainView')
你得到的 405 行为是因为浏览器试图将表单直接发送到 MainView
,它不是表单视图,告诉浏览器它不知道如何处理POST
方法。
我完全无法理解这种行为,并找到了一个我不太喜欢的解决方法。任何人都可以帮助启发我吗?上下文是我有一个 bootstrap 样式的表单来创建新记录(继承自 generic.CreateView)
url.py:
url(r'^$', home, name='home'),
url(r'^main/$', views.MainView.as_view(), name='MainView'),
url(r'^topic/(?P<pk>[0-9]+)/$', catalogue_views.TopicView.as_view(), name='TopicView'),
url(r'^resource/(?P<pk>[0-9]+)/$', catalogue_views.DetailView.as_view(), name='ResourceDetail'),
url(r'^contribute/$', catalogue_views.ContributeView.as_view(success_url="/main/"), name='Contribute'),
views.py:
class ContributeView(generic.CreateView):
template_name = "openeye/contribute.html"
form_class = ContributeForm
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(ContributeView, self).dispatch(*args, **kwargs)
class MainView(generic.ListView):
template_name = "openeye/main.html"
context_object_name = 'topic_list'
# TODO Make this only active topic areas?
def get_queryset(self):
return TopicArea.objects.all().order_by('name')
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(MainView, self).dispatch(*args, **kwargs)
forms.py:
class ContributeForm(forms.ModelForm):
class Meta:
model = CatalogueItem
fields = ['title', 'topic_area', 'description', 'link', 'what_learn', 'how_apply', 'level', 'relevant_to', 'discovered_by']
ROLE_CHOICES = [[x.id, x.job] for x in JobType.objects.all()]
title = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'To sell this resource to others'}), max_length=80, required=True)
description = forms.CharField(widget=forms.Textarea(attrs={'rows': 2, 'placeholder': 'Clear, e.g. format, duration, activities...'}))
link = forms.CharField(widget=forms.URLInput(attrs={'placeholder': 'If required, link to resource http://...'}), required=False)
what_learn = forms.CharField(widget=forms.Textarea(attrs={'rows': 3, 'placeholder':"This is important,."}), label='What will you learn?')
how_apply = forms.CharField(widget=forms.Textarea(attrs={'rows': 3, 'placeholder':"How could this be put into action afterwards?"}), label='How could you apply this?')
relevant_to = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple, choices=ROLE_CHOICES)
和一个带有表单的模板:
<div class="container">
<div class="entry-form row">
<div class="col-md-10 col-md-offset-1 col-sm-10 col-sm-offset-1 col-xs-10 col-xs-offset-1">
<form action="{% url 'MainView' %}" method="post" class="form">
<input type="hidden" name="next" value="{{ next }}">
{% bootstrap_form form %}
<button class="btn btn-primary btn-lg" type="submit">Submit Suggestion</button>
{% csrf_token %}
</form>
</div>
</div>
表单完美运行,数据很好地保存到数据库中。问题是之后,浏览器转到正确的 URL /main/ 但屏幕是空白的。服务器显示 HTTP 405 0,如果我刷新页面,它就会工作。
如果我改变模板,使 action="{% url 'Contribute' %}" 到 return 相同的形式,我会收到 HTTP 500 和一条 Django 消息关于'No URL to redirect to'。所以由重定向位置决定的两个不同的错误。在这两种情况下,如果我只是点击浏览器 url 字段并点击 return 就可以了。
我确信这最初是有效的,然后就坏了,但我按如下方式解决了它。 success_url 中的硬代码使用它的路径
url(r'^contribute/$', catalogue_views.ContributeView.as_view(success_url="/main/"), name='Contribute'),
正在删除模板中的任何操作 link:
<form action="" method="post" class="form">
这是正确的做法吗?为什么,尽管转到了正确的 URLs,页面仍然无法加载或使用我的原始方法出错?我很想了解这一点。
您确定您的数据确实保存在服务器上吗?从您发布的内容来看,这似乎不太可能。下面是Django遵循的正常流程:
- 在表单视图 (ContributeView) 上获取 → returns 一个空表格
- POST 在表单视图 (ContributeView) 上
→ 如果无效,返回步骤 1。如果有效 return a
302 Redirect
tosuccess_url
. - 在 success_url 上获得
所以通常情况下,在您的模板中,表单操作应该是空的,这样表单就会被发送回生成它的视图。 ContributeView
应该会成功 url 重定向到你想发送给用户的任何地方:
from django.core.urlresolvers import reverse_lazy
class ContributeView(generic.CreateView):
# other stuff
success_url = reverse_lazy('MainView')
你得到的 405 行为是因为浏览器试图将表单直接发送到 MainView
,它不是表单视图,告诉浏览器它不知道如何处理POST
方法。