我有一个表单,它接受一些用户输入,发布到视图,进行一些计算,然后重定向到输出。
当计算运行时,我可以看到我的浏览器标签中的小轮子旋转,但是用户必须在他们等待的时候看着他们的表格。
我想制作各种类型的状态视图,在某些部分进行计算时,它会向用户显示有关其进度的消息,例如“在流程的第3部分”,并在完成后重定向到结果。
所以我要求有人帮助我这样做。
e.g。在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')
答案 0 :(得分:1)
您需要在计算过程中将进度存储在某处。
每次客户端通过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)
答案 1 :(得分:1)
我已经给了你足够的开始,但你必须自己学习一些jquery和javascript来处理你从轮询中得到的消息。没那么糟糕;您可以在堆栈溢出和整个互联网上使用大量示例。希望这会有所帮助。
添加到models
:
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]
运行python manage.py makemigrations
,调试我所犯的任何错误,并运行python manage.py migrate
。
导入新模型和json内容并修改view
:
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
})
添加到您的urls
:
url(r'^calculation_poll/$', view.poll_view, name='poll_view')
确保将{% load url %}
添加到模板顶部,
如果你还没有在标题中包含<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
,请添加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>
答案 2 :(得分:0)
您不应该一直更新状态(约%)
当您调用Ajax时,只需弹出一个对话框(或某些图像,gif ...)进行处理
然后,当Ajax完成(成功或失败)时,只需将其关闭。
像:
$('#btn').click(function(){
$('#loading').show();
ajaxAction = $.ajax({
dataType: "json",
url:"some/url/",
data: data_to_send,
success: function (data){
# Some code
$('#loading').hide(1500);
}
});
});
请记住创建id =&#34的html; loading&#34; (正如我所说)