Как обрабатывать три функции с помощью celery в django?
У меня есть три функции в моих представлениях сайта django, но я могу запустить только одну. Я никогда не использовал celery, можете ли вы помочь мне преобразовать это в задачи celery?
Как вы видите, я хочу сохранить документ, загруженный пользователем, затем я хочу сделать некоторые вещи pandas с этим файлом, и после этого я хочу показать вещи pandas на html-странице.
Это forms.py
class DocumentForm(forms.Form):
docfile = forms.FileField(label='Select a file')
Это views.py
def save_exls(request):
if request.method == 'POST':
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
newdoc = Document(docfile=request.FILES['docfile'])
newdoc.save()
return redirect('html_exls')
else:
form = DocumentForm()
documents = Document.objects.all()
context = {'documents': documents, 'form': form,}
return render(request, 'list.html', context)
def pandas_exls(request):
if request.method == "POST":
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
output = io.BytesIO()
newdoc = request.FILES['docfile']
dfs = pd.read_excel(newdoc, sheet_name=None, index_col=[0])
writer = pd.ExcelWriter(output)
for name, df in dfs.items():
#pandas stuff
done.to_excel(writer, sheet_name=name)
output.seek(0)
response = HttpResponse(
output, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
else:
form = DocumentForm()
return render(request, 'list.html', {'form': form})
def html_exls(request):
if request.method == "POST":
form = DocumentForm(request.POST, request.FILES)
if form.is_valid():
output = io.BytesIO()
newdoc = request.FILES['docfile']
dfs = pd.read_excel(newdoc, sheet_name=None, index_col=[0])
writer = pd.ExcelWriter(output)
for name, df in dfs.items():
#pandas stuff for html
done.to_excel(writer, sheet_name=name)
html = done.to_html()
print(html)
output.seek(0)
response = HttpResponse(
output, content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
else:
form = DocumentForm()
return render(request, 'list.html', {'form': form})
Это html-файл, list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Django site</title>
</head>
<body>
<!-- Upload form. Note enctype attribute! -->
<form action="{% url "pandas_exls" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload"/></p>
</form>
<br/>
{{html|safe}}
</body>
</html>
не логично запускать render returning function views в задачах celery. вам нужно использовать render to string и js, чтобы это произошло. вам буквально не нужен celery. и я не понимаю, почему вы пытаетесь сгенерировать новую форму в 3 разных представлениях на одной html-странице? вы загружаете новые файлы или что-то в pandas и html представлениях
Я использую для этого task_api, это проект django, который отслеживает функции и предоставляет некоторый javascript для опроса бэкенда на предмет изменений и обновлений, когда функции закончат выполняться. Он пока не поддерживает параметры файлов, но вы можете сначала сохранить файл, а затем на javascript вызвать следующий метод для работы с этим файлом после сохранения и отображения прогресса.
Я бы написал 3 конечные точки, 1 для загрузки файла, используя форму, затем 1 конечная точка ajax, которую вы вызываете на javascript для обработки файла, она вернется, когда все будет готово, и тогда вы сможете перенаправить на 3-ю конечную точку, которая загрузит файл.
например. views.py
и в вашем list.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Django site</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="{% static 'django-task-api.min.js' %}"></script>
<script type="text/javascript">
function runtask(task, documentid, progressdivname) {
TaskAPI.run(task, documentid, function(json) {
if (json.target === null || json.progress === null) {
return false
}
document.getElementById(progressdivname).innerHTML = 'Progress: ' + json.progress + ' / ' + json.target
})
.then(function(json) {
# panda's is done, download doc
window.location = '/download/' + json.outputs.documentid;
})
return false
}
$(document).ready(function (e) {
$("#form").on('submit',(function(e) {
e.preventDefault();
$.ajax({
url: "/upload",
type: "POST",
data: new FormData(this),
contentType: false,
cache: false,
processData:false,
beforeSend : function()
{
//$("#preview").fadeOut();
$("#err").fadeOut();
},
success: function(documentid)
{
// process uploaded file.
runtask('pandas', {'documentid': documentid}, 'progress')
}
,
error: function(e)
{
$("#err").html(e).fadeIn();
}
});
}));
});
</script>
</head>
<body>
<!-- Upload form. Note enctype attribute! -->
<form action="{% url "pandas_exls" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<p>{{ form.non_field_errors }}</p>
<p>{{ form.docfile.label_tag }} {{ form.docfile.help_text }}</p>
<p>
{{ form.docfile.errors }}
{{ form.docfile }}
</p>
<p><input type="submit" value="Upload"/></p>
</form>
<br/>
<div id="progress"></div>
</body>
</html>