我正在使用Django Web应用程序。该应用程序在同一页面中包含两种形式。第一种形式用于上传图像,第二种形式用于图像描述。用户上传图像并单击“上传图像”按钮后,图像分类器应对图像进行分类并自动填充第二个表单的某些部分。
到目前为止,这是我的代码
class Item(models.Model):
title = models.CharField(max_length=100)
color = models.CharField(max_length=100)
img = models.ImageField(upload_to='item/img/', null=False, blank=False)
def __str__(self):
return self.title
def delete(self, *args, **kwargs):
self.img.delete()
super().delete(*args, **kwargs)
from .models import Item
class ItemImage(forms.ModelForm):
class Meta:
model = Item
fields = ('img',)
class ItemForm(forms.ModelForm):
class Meta:
model = Item
fields = ('title', 'color')
from .forms import ItemForm, ItemImage
from .models import Item
def upload_item(request):
if request.method == 'POST':
form_img = ItemImage(request.POST, request.FILES)
if form_img.is_valid():
form_img.save()
form_des = ItemForm(request.POST, request.FILES)
if form_des.is_valid():
form_des.save()
return redirect('item_list')
else:
form_img = ItemImage()
form_des = ItemForm()
return render(request, 'upload_item.html', {'form_img': form_img, 'form_des': form_des})
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %} upload_item {% endblock title %}
{% block content %}
<div class="row justify-content-center">
<div class="col-6">
<h2>Upload item</h2>
<div class="card mb-5 mt-1">
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form_img|crispy}}
<button type="submit" class='btn btn-primary'>upload img</button>
</form>
</div>
</div>
<div class="card mb-5 mt-1">
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form_des|crispy}}
<button type="submit" class='btn btn-primary'>Save item</button>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
我面临的问题是上传图像后,当我按“上传图像”按钮时,页面重新加载,我必须重新开始。我想当我按下按钮时,页面正在尝试保存表单。我该如何纠正?
[注意]我尚未编写图像分类代码。解决此问题后,我将在 views.py 中的 upload_item 函数下编写该代码
我对模板文件做了一些更改。现在,我可以上传图像并在图像上运行分类器。
这些是我所做的更改
{% block content %}
<div class="row justify-content-center">
<div class="col-6">
<h2>Upload item</h2>
<div class="card mb-5 mt-1">
<div class="card-body">
<form action="{{ request.build_absolute_uri }}image_classification/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input id="search" , type="file" name="file"/>
<input class='btn btn-primary' , type="submit" value="Upload image" />
</form>
</div>
</div>
<div class="card mb-5 mt-1">
<div class="card-body">
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{form_des|crispy}}
<button type="submit" class='btn btn-primary'>Save item</button>
</form>
</div>
</div>
</div>
</div>
{% endblock content %}
def handle_uploaded_file(file, filename):
if not os.path.exists('media/classification/'):
os.mkdir('media/classification/')
with open('media/classification/' + filename, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
def image_classification(request):
form = ItemForm()
cascade_path = "./classifier.h5"
classifier = load_model(cascade_path)
if request.method == 'POST':
handle_uploaded_file(request.FILES['file'], str(request.FILES['file']))
img = np.expand_dims(cv2.resize(cv2.imread(os.path.join('./media/classification/', str(request.FILES['file']))), (170, 100)), axis=0)
pred_class = str(classifier.predict_classes(img)[0])
print(pred_class)
form.fields['title'].widget.attrs['value'] = pred_class
return render(request, 'upload_item.html', {'form': form})
return HttpResponse("Failed")
我添加了@Alexander Strakhov建议的代码。这就是我得到的结果。
我在做什么错了?
预先感谢
答案 0 :(得分:1)
当您按下“上传图片”按钮时,您将请求发送到upload_item网址。那里您的意见:
1)将ItemImage表单绑定到request.Post(这是带有csrf令牌的QueryDict),并绑定到带有上传文件的request.FILES。
2)保存图像表格(假设图像有效)。
3)将ItemForm 绑定到与ItemImage相同的请求数据。
4)再次在上下文中使用有界的form_img和form_des渲染upload_item.html。
咨询Django文档:https://docs.djangoproject.com/en/2.1/topics/forms/#the-view
按下“上传图片”时出现空白页面的原因是:
a)“标题”和“颜色”两个字段都绑定到QueryDict中的一个空值,因为按“上传图像”不会提交第二个表单,“标题”和“颜色”是其中的一部分。
b)似乎Django渲染回表格时没有将表格绑定到文件,而将表格留空(我会向社区咨询)。我建议在这里使用AJAX来验证您的图像并稍后运行分类。使用AJAX可以将图像保留在页面上,因为不会刷新页面,因此您以后可以使用“保存项目”按钮提交这两种表单。
修改
看到更新的代码后,我建议初学者进行以下操作:
替换def webhook():
data = request.get_json()
log(data)
if data['object'] == 'page':
for entry in data['entry']:
for messaging_event in entry['messaging']:
sender_id = messaging_event['sender']['id']
recipient_id = messaging_event['recipient']['id']
if messaging_event.get('message'):
if 'text' in messaging_event['message']:
messaging_text = messaging_event['message']['text']
else:
messaging_text = 'no text'
response = None
entity, value = wit_response(messaging_text)
if entity == 'newstype':
response = "OK. I will send you {} news".format(str(value))
elif entity == 'cust_greet':
response = get_message()
elif entity == 'cust_greet2':
response = get_message2()
elif entity == 'cust_offer':
#response = offer_response
response = " Generic Offer 1"+"\n"+" Generic Offer 2"+"\n"+" Generic Offer 3"+"\n"+" ️ for more offer enter your cust id"
#val_off = test.val_off
bot.send_text_message(sender_id, response)
使用
form.fields['title'].widget.attrs['placeholder'] = pred_class