Python Django:带有状态视图的POST表单(ajax?)
我有一个表单,它接受一些用户输入,发布到视图,进行一些计算,然后重定向到输出 当计算运行时,我可以在我的浏览器选项卡中看到小轮子旋转,但是用户必须在等待时查看他们的表单 我想做一个排序的状态视图,当计算在某些部分进行时,它会向用户显示一条关于其进度的消息,例如“在流程的第3部分”,完成后会重定向到结果 所以我请求有人帮我做这件事 e、 g.在Python Django:带有状态视图的POST表单(ajax?),python,ajax,django,python-3.x,Python,Ajax,Django,Python 3.x,我有一个表单,它接受一些用户输入,发布到视图,进行一些计算,然后重定向到输出 当计算运行时,我可以在我的浏览器选项卡中看到小轮子旋转,但是用户必须在等待时查看他们的表单 我想做一个排序的状态视图,当计算在某些部分进行时,它会向用户显示一条关于其进度的消息,例如“在流程的第3部分”,完成后会重定向到结果 所以我请求有人帮我做这件事 e、 g.在views.py中 def form(request): if request.method == 'POST' form = MyForm
views.py中
def form(request):
if request.method == 'POST'
form = MyForm(request.POST)
if form.is_valid():
form = convert_form_to_model(form.cleaned_data, MyModel)
# DO calculations
send_message_to_user_waiting_screen('Part One Complete')
# DO more calculations
send_message_to_user_waiting_screen('Part two Complete')
....
return HttpResponseRedirect(reverse('my_app:results', args(form.id,)))
else:
return render(request, 'my_app/form.html')
else:
form = MyForm()
render(request, 'my_app/form.html')
您不应该一直更新状态(大约%)
调用Ajax时,只需弹出一个对话框(或一些图像、gif…)进行处理
然后,当Ajax完成(成功或失败)时,将其关闭
比如:
记住用id=“loading”(正如我提到的)创建html您不应该一直更新状态(大约%)
调用Ajax时,只需弹出一个对话框(或一些图像、gif…)进行处理
然后,当Ajax完成(成功或失败)时,将其关闭
比如:
请记住使用id=“loading”(如我所述)创建html在计算过程中,您需要将进度存储在某个地方
每次客户端通过GET请求进行轮询时,您都可以发送存储的进度数据
在伪代码中:
def form(request):
if request.method == 'POST'
form = MyForm(request.POST)
if form.is_valid():
form = convert_form_to_model(form.cleaned_data, MyModel)
# DO calculations
save('part1 complete')
send_message_to_user_waiting_screen('Part One Complete')
# DO more calculations
save('part2 complete')
send_message_to_user_waiting_screen('Part two Complete')
....
return HttpResponseRedirect(reverse('my_app:results', args(form.id,)))
else:
return render(request, 'my_app/form.html')
else:
form = MyForm()
render(request, 'my_app/form.html')
#Another endpoint to respond to polling
def progress():
return fetchprogress(uid, some other arg)
在计算过程中,您需要将进度存储在某个位置
每次客户端通过GET请求进行轮询时,您都可以发送存储的进度数据
在伪代码中:
def form(request):
if request.method == 'POST'
form = MyForm(request.POST)
if form.is_valid():
form = convert_form_to_model(form.cleaned_data, MyModel)
# DO calculations
save('part1 complete')
send_message_to_user_waiting_screen('Part One Complete')
# DO more calculations
save('part2 complete')
send_message_to_user_waiting_screen('Part two Complete')
....
return HttpResponseRedirect(reverse('my_app:results', args(form.id,)))
else:
return render(request, 'my_app/form.html')
else:
form = MyForm()
render(request, 'my_app/form.html')
#Another endpoint to respond to polling
def progress():
return fetchprogress(uid, some other arg)
我已经为您提供了足够的入门知识,但是您必须自己学习一些jquery和javascript来处理从轮询中获得的消息。没那么糟;您可以在堆栈溢出和整个internet上使用许多示例。希望这有帮助
添加到型号中
:
class UserCalculationUpdate(models.Model)
user = models.ForeignKey(User)
stage = models.SmallIntegerField(default=0, max_length=1)
message = models.TextField(default='')
_stage_dict = {-1: 'Failed.', 0: 'On stage 1 of 3', 1: 'On stage 2 of 3',
2: 'On stage 3 of 3', 3: 'Calculation Complete!'}
def get_stage(self):
return self._stage_dict[self.stage]
url(r'^calculation_poll/$', view.poll_view, name='poll_view')
运行python manage.py makemigrations
,调试我犯的任何错误,然后运行python manage.py migrate
导入您的新模型和json内容并编辑您的视图
:
from django.http import JsonResponse
from my_app.models import UserCalculationUpdate
# I'd rename your view to something else.
def form(request):
if request.method == 'POST'
form = MyForm(request.POST)
if form.is_valid():
form = convert_form_to_model(form.cleaned_data, MyModel)
"""
looks to see if there is a UserCalculationUpdate object
corresponding to the present user. If not, it creates one
and sets obj.stage = 0 and sets created = True, otherwise,
it sets obj.stage = 0 for the object already in the db
and sets created = False
"""
obj, created = UserCalculationUpdate.objects \
.update_or_create(user=request.user,
defaults={'stage':0})
result1, success, message = step_one_calc(form)
# storing the progress in our new model, success should be
# a boolean
if success:
obj.update(stage=1)
else obj.update(stage=-1, message=message)
return HttpResponse() # whatever you want to happen when fails
result2, success, message = step_two_calc(result1, success)
if success:
obj.update(stage=2)
else obj.update(stage=-1,
message=message)
return HttpResponse() # whatever you want to happen when fails
"""
. . . and so on . . .
"""
return HttpResponseRedirect(reverse('my_app:results', args(form.id,)))
else:
return render(request, 'my_app/form.html')
else:
form = MyForm()
render(request, 'my_app/form.html')
def poll_view(request):
user_calc_update = UserCalculationUpdate.objects \
.filter(user=request.user):
if len(user_calc_update) != 0:
stage_message = user_calc_update[0].get_stage()
results_message = user_calc_update[0].message
# 0 is incomplete 1 is complete
completion_status = 0 if user_calc_update[0].stage == 3 else 1
return JsonResponse({
'message': f'{stage_message} {results_message}',
'completion_status': completion_status
})
except UserCalculationUpdate.DoesNotExist:
return JsonResponse({
'message': 'Beginning Calculations',
'completion_status': 0
})
添加到您的URL
:
class UserCalculationUpdate(models.Model)
user = models.ForeignKey(User)
stage = models.SmallIntegerField(default=0, max_length=1)
message = models.TextField(default='')
_stage_dict = {-1: 'Failed.', 0: 'On stage 1 of 3', 1: 'On stage 2 of 3',
2: 'On stage 3 of 3', 3: 'Calculation Complete!'}
def get_stage(self):
return self._stage_dict[self.stage]
url(r'^calculation_poll/$', view.poll_view, name='poll_view')
确保将{%load url%}
添加到模板顶部,
如果尚未添加jquery,请在标题中包含
,并将此脚本添加到模板中的某个位置:
<script>
// $('#id') is the jquery selector syntax for selecting an element by its id
// and manipulating it.
$('#calc_submit_button_id').click(function(){ //adding an onclick trigger
$('#loading').show(); //the 'loading' element is where you want your //information about your progress to show, this can
// a modal or a bootstrap alert or whatever you like.
// the .show() method removes any 'display:none' or
// 'display: hidden' from the style of the 'loading'
// element.
pollingFunction = $.ajax({
dataType: "json",
url:"{% url "poll_view" %}",
data: '',
success: function (message){
/* use console.log() and look at the console using inspect element
(ctrl + shift + i in chrome, right click + Q in firefox) to
examine the structure of your message
*/
console.log(message)
# Some code that decides what to do with message
if (you wish to display the message and poll again)
{
//adds message to ('#loading'), should make it prettier, but
//serves our purpose for now
('#loading').empty()
('#loading').html('<h3>' + JSON.stringify(message) + '</h3>')
//wait ten seconds, poll again
setTimeout(pollingFunction, 10000)
}
else(you wish to end polling and hide the ('#loading') element)
{
$('#loading').hide();
}
},
error: function(jqXHR){
console.log(jqXHR)
('#loading').html('<h3>Oh no, something awful happened, better check the logs.</h3>')
}
});
});
</script>
//$('#id')是jquery选择器语法,用于根据元素的id选择元素
//并操纵它。
$(“#计算提交按钮_id”)。单击(函数(){//添加onclick触发器
$(“#加载”).show();//加载”元素是您希望//显示进度信息的地方,可以
//模态警报或引导警报或任何您喜欢的警报。
//.show()方法删除任何“display:none”或
//“加载”样式中的“显示:隐藏”
//元素。
pollingFunction=$.ajax({
数据类型:“json”,
url:“{%url”轮询视图“%}”,
数据:“”,
成功:功能(消息){
/*使用console.log()并使用inspect元素查看控制台
(在chrome中按ctrl+shift+i,在firefox中右键单击+Q)以
检查消息的结构
*/
console.log(消息)
#一些决定如何处理消息的代码
如果(您希望显示消息并再次轮询)
{
//将消息添加到(“#加载”),应使其更美观,但
//这是我们目前的目标
(“#加载”).empty()
('#load').html(''+JSON.stringify(message)+'')
//等待10秒钟,再次投票
设置超时(轮询函数,10000)
}
else(您希望结束轮询并隐藏('#loading')元素)
{
$(“#加载”).hide();
}
},
错误:函数(jqXHR){
console.log(jqXHR)
(“#加载”).html('哦,不,发生了可怕的事情,最好检查一下日志。'))
}
});
});
我已经为您提供了足够的入门知识,但是您必须自己学习一些jquery和javascript来处理从轮询中获得的消息。没那么糟;您可以在堆栈溢出和整个internet上使用许多示例。希望这有帮助
添加到型号中
:
class UserCalculationUpdate(models.Model)
user = models.ForeignKey(User)
stage = models.SmallIntegerField(default=0, max_length=1)
message = models.TextField(default='')
_stage_dict = {-1: 'Failed.', 0: 'On stage 1 of 3', 1: 'On stage 2 of 3',
2: 'On stage 3 of 3', 3: 'Calculation Complete!'}
def get_stage(self):
return self._stage_dict[self.stage]
url(r'^calculation_poll/$', view.poll_view, name='poll_view')
运行python manage.py makemigrations
,调试我犯的任何错误,然后运行python manage.py migrate
导入您的新模型和json内容并编辑您的视图
:
from django.http import JsonResponse
from my_app.models import UserCalculationUpdate
# I'd rename your view to something else.
def form(request):
if request.method == 'POST'
form = MyForm(request.POST)
if form.is_valid():
form = convert_form_to_model(form.cleaned_data, MyModel)
"""
looks to see if there is a UserCalculationUpdate object
corresponding to the present user. If not, it creates one
and sets obj.stage = 0 and sets created = True, otherwise,
it sets obj.stage = 0 for the object already in the db
and sets created = False
"""
obj, created = UserCalculationUpdate.objects \
.update_or_create(user=request.user,
defaults={'stage':0})
result1, success, message = step_one_calc(form)
# storing the progress in our new model, success should be
# a boolean
if success:
obj.update(stage=1)
else obj.update(stage=-1, message=message)
return HttpResponse() # whatever you want to happen when fails
result2, success, message = step_two_calc(result1, success)
if success:
obj.update(stage=2)
else obj.update(stage=-1,
message=message)
return HttpResponse() # whatever you want to happen when fails
"""
. . . and so on . . .
"""
return HttpResponseRedirect(reverse('my_app:results', args(form.id,)))
else:
return render(request, 'my_app/form.html')
else:
form = MyForm()
render(request, 'my_app/form.html')
def poll_view(request):
user_calc_update = UserCalculationUpdate.objects \
.filter(user=request.user):
if len(user_calc_update) != 0:
stage_message = user_calc_update[0].get_stage()
results_message = user_calc_update[0].message
# 0 is incomplete 1 is complete
completion_status = 0 if user_calc_update[0].stage == 3 else 1
return JsonResponse({
'message': f'{stage_message} {results_message}',
'completion_status': completion_status
})
except UserCalculationUpdate.DoesNotExist:
return JsonResponse({
'message': 'Beginning Calculations',
'completion_status': 0
})
添加到您的URL
:
class UserCalculationUpdate(models.Model)
user = models.ForeignKey(User)
stage = models.SmallIntegerField(default=0, max_length=1)
message = models.TextField(default='')
_stage_dict = {-1: 'Failed.', 0: 'On stage 1 of 3', 1: 'On stage 2 of 3',
2: 'On stage 3 of 3', 3: 'Calculation Complete!'}
def get_stage(self):
return self._stage_dict[self.stage]
url(r'^calculation_poll/$', view.poll_view, name='poll_view')
确保将{%load url%}
添加到模板顶部,
如果尚未添加jquery,请在标题中包含
,并将此脚本添加到模板中的某个位置:
<script>
// $('#id') is the jquery selector syntax for selecting an element by its id
// and manipulating it.
$('#calc_submit_button_id').click(function(){ //adding an onclick trigger
$('#loading').show(); //the 'loading' element is where you want your //information about your progress to show, this can
// a modal or a bootstrap alert or whatever you like.
// the .show() method removes any 'display:none' or
// 'display: hidden' from the style of the 'loading'
// element.
pollingFunction = $.ajax({
dataType: "json",
url:"{% url "poll_view" %}",
data: '',
success: function (message){
/* use console.log() and look at the console using inspect element
(ctrl + shift + i in chrome, right click + Q in firefox) to
examine the structure of your message
*/
console.log(message)
# Some code that decides what to do with message
if (you wish to display the message and poll again)
{
//adds message to ('#loading'), should make it prettier, but
//serves our purpose for now
('#loading').empty()
('#loading').html('<h3>' + JSON.stringify(message) + '</h3>')
//wait ten seconds, poll again
setTimeout(pollingFunction, 10000)
}
else(you wish to end polling and hide the ('#loading') element)
{
$('#loading').hide();
}
},
error: function(jqXHR){
console.log(jqXHR)
('#loading').html('<h3>Oh no, something awful happened, better check the logs.</h3>')
}
});
});
</script>
//$('#id')是jquery选择器语法,用于根据元素的id选择元素
//并操纵它。
$(“#计算提交按钮_id”)。单击(函数(){//添加onclick触发器
$(“#加载”).show();//加载”元素是您希望//显示进度信息的地方,可以
//模态警报或引导警报或任何您喜欢的警报。
//.show()方法删除任何“display:none”或
//“加载”样式中的“显示:隐藏”
//元素。
pollingFunction=$.ajax({
数据类型:“json”,
url:“{%url”轮询视图“%}”,
数据:“”,
成功:功能(消息)