I have a flask website. I was to make prediction images using the model that I build in Google Collab. In this, I have 25 classes and I took 3 classes for testing its work or not. I have already run it but when I go to the predict pages it seems to get the error 'jinja2.exceptions.UndefinedError: 'predictions' is undefined' Can anyone help me. Thank u
The Python Code:
with open('CNN.pth','rb') as file:
model=torch.load('CNN.pth',map_location='cpu')
classes=['00','01','02','03','04','05','06','07','08','09','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24']
def predict(filename,model):
img=load_img(filename,target_size=(32,32))
img=img_to_array(img)
img=img.reshape(1,32,32,3)
img = img.astype('float32')
img = img/255.0
result = model.predict(img)
dict_result = {}
for i in range(25):
dict_result[result[0][i]] = classes[i]
res = result[0]
res.sort()
res = res[::-1]
prob = res[:3]
prob_result = []
class_result = []
for i in range(3):
prob_result.append((prob[i]*100).round(2))
class_result.append(dict_result[prob[i]])
return class_result , prob_result
#app.route('/predict' , methods = ['GET' , 'POST'])
def success():
error = ''
target_img = os.path.join(os.getcwd() , 'static/images')
if request.method == 'POST':
if (request.files):
file = request.files['file']
if file and allowed_file(file.filename):
file.save(os.path.join(target_img , file.filename))
img_path = os.path.join(target_img , file.filename)
img = file.filename
class_result , prob_result = predict(img_path , model)
predictions = {
"class1":class_result[0],
"class2":class_result[1],
"class3":class_result[2],
"prob1": prob_result[0],
"prob2": prob_result[1],
"prob3": prob_result[2],
}
else:
error = "Please upload images of jpg , jpeg and png extension only"
if(len(error) == 0):
return render_template('predict.html' , img = img , predictions = predictions)
else:
return render_template('home.html' , error = error)
else:
return render_template('home.html')
Index.html
<tr>
<th>Class</th>
<th>Probability</th>
</tr>
<tr>
<th>{{predictions.class1}}</th>
<th>{{predictions.prob1}}</th>
</tr>
<tr>
<th>{{predictions.class2}}</th>
<th>{{predictions.prob2}}</th>
</tr>
<tr>
<th>{{predictions.class3}}</th>
<th>{{predictions.prob3}}</th>
</tr>
You have put an if - else condition, if you pay attention, the values rendered in the if block and the rendered values in the else block are different.
But all the values are used in the html file.
If your code run else block so:
else:
return render_template('home.html' , error = error)
-> Where is the "prediction" value?
How can html predict a value that is not rendered as a value?
If you want to use like that:
#app.route('/predict' , methods = ['GET' , 'POST'])
def success():
predictions = dict() # if predictions is not empty ok, else doens't matter
error = ''
target_img = os.path.join(os.getcwd() , 'static/images')
if request.method == 'POST':
if (request.files):
file = request.files['file']
if file and allowed_file(file.filename):
file.save(os.path.join(target_img , file.filename))
img_path = os.path.join(target_img , file.filename)
img = file.filename
class_result , prob_result = predict(img_path , model)
predictions = {
"class1":class_result[0],
"class2":class_result[1],
"class3":class_result[2],
"prob1": prob_result[0],
"prob2": prob_result[1],
"prob3": prob_result[2],
}
else:
error = "Please upload images of jpg , jpeg and png extension only"
if(len(error) == 0):
return render_template('predict.html' , img = img , predictions = predictions)
else:
return render_template('home.html' , error = error, predictions = predictions)
else:
return render_template('home.html', predictions = predictions)
And you can use jinja condition like that:
{% if predictions|length > 0 %}
<tr>
<th>Class</th>
<th>Probability</th>
</tr>
<tr>
<th>{{predictions.class1}}</th>
<th>{{predictions.prob1}}</th>
</tr>
<tr>
<th>{{predictions.class2}}</th>
<th>{{predictions.prob2}}</th>
</tr>
<tr>
<th>{{predictions.class3}}</th>
<th>{{predictions.prob3}}</th>
</tr>
{% endif %}
in the last line of code written in python
return render_template('home.html')
you don't specify the predictions variable, unlike you did previously
return render_template('predict.html' , img = img , predictions = predictions)
Related
I want to let the user choose a courseName from a list and show all the files under this directory, how can i achieve that? i am struggling with finding a way to show all the files of a specific course.
here is what i've done so far:
views.py
def showDocuments(request):
if request.POST:
if Document.objects.filter(courses__exact=request.POST["course"]).exists():
print(request.POST["course"])
else:
print("there is no files for this course yet!")
documents = Document.objects.all()
courses = Course.objects.all()
context = {
"documents" : documents ,
"courses" : courses,
}
return render(request , 'dashboard.html' , context )
models.py
class Document(models.Model):
#to do : enum class !
DB = "data structure"
SF = "software enginering"
DS = "discrete structure "
WD = "web dev"
OPTIONS = "options"
courseChoices = (
(DB , "data structure"),
(SF , "software enginering "),
(DS , "discrete structure"),
(WD , "web dev"),
(OPTIONS , "options"),
)
courses = models.CharField(max_length=50, choices=courseChoices, default=OPTIONS)
description = models.TextField(help_text="A little description can be very helpful for others!")
document = models.FileField(upload_to=content_file_name)
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return "{}".format(self.document)
def content_file_name(self, courses):
file_path = "documents/{courses}/{filename}".format(
courses=self.courses, filename=courses)
return file_path
dashboard.html
<div class="col-sm-4">
<select id="crs" class="custom-select custom-select-sm" name="course">
<option selected>option</option>
{% for obj in courses %}
<option value="{{ obj.courseName }}">{{ obj.courseName }}</option>
{% endfor %}
</select>
</div>
So here is my solution:
def showDocuments(request, *args, **kwargs):
""" shows all the files of the requested course """
crs_names = CoursesNames.objects.all()
context = {
"crs_names": crs_names,
"files": [],
"not_found" : "",
}
if request.POST:
file_name = request.POST["course"]
not_found = "There are no files for {0} yet!".format(file_name)
documents = Document.objects.all().filter(course_name__courses__iexact=file_name)
context["documents"] = documents
context["filename"] = file_name
documentObjectList = Document.objects.all().values_list("document").filter(course_name__courses__iexact=file_name)
queryset = CoursesNames.objects.filter(courses__exact=file_name).exists()
if queryset:
while len(context["files"]) > 0: context["files"].pop()
for i in documentObjectList:
context["files"] = i
print(context["files"])
if len(context["documents"]) == 0: context["not_found"] = not_found
return render(request, 'dashboard.html', context)
With Django Listview, is it possible to display new columns that contain the values of floor division and modulo?
I have the following two models:
models.py
class Model_Item(models.Model):
item_name = models.CharField(max_length = 100, null = False, blank = False, unique = True)
item_bottleperpack = models.FloatField(null = True, blank = False) # e.g. 100 bottles per pack
def __unicode__(self):
return self.item_name
class Model_ItemTransaction(models.Model):
item = models.ForeignKey(Model_Item, to_field = "item_name")
item_sold = models.FloatField(null = True, blank = True) # in terms of bottle
def __unicode__(self):
return self.item
With this listview:
views.py
class View_Item(ListView):
def get_queryset(self):
queryset = Model_Item.objects.all()
queryset = queryset.annotate(
sum_ = Sum("model_itemtransaction__item_sold")
)
queryset = queryset.annotate(
floor_division_ = F("sum_") // F("item_bottleperpack"),
module_ = F("sum_") %% F("item_bottleperpack")
)
return queryset
Basically, if I have sold, say 650 bottles, and there is 100 bottles per pack, I would like the listview to display:
6 packs on the "floor-division" column, and
50 bottles on the "modulo" column.
Currently I am receiving the following errors with my current code
unsupported operand type(s) for //: 'F' and 'F'
and
unsupported operand type(s) for %%: 'F' and 'F'
and hoping someone could help me find any solution to this (and it does not have to be with conditional expression).
According to https://docs.djangoproject.com/en/2.0/_modules/django/db/models/expressions/:
Neither class F nor it's parent Combinable implement __floordiv__, so // is not implemented. Combinable does implement __truediv__, which is the / operator.
I haven't heard of the operator %% in Python, but % will work because __mod__ is implemented in Combinable.
Try using models.IntegerField or models.PositiveIntegerField for item_bottleperpack and item_sold, and updating this line in views.py:
queryset = queryset.annotate(
floor_division_ = F("sum_") / F("item_bottleperpack"),
module_ = F("sum_") % F("item_bottleperpack")
)
I'm assuming that Combinable will return an integer as the output of dividing two integers -- this might not be the case. If so, you might want to round down the result.
So I have found a way to solve this, thanks to this post.
First I cleaned the code at views.py,
views.py
class View_Item(ListView):
def get_queryset(self):
queryset = Model_Item.objects.all()
queryset = queryset.annotate(
sum_ = Sum("model_itemtransaction__item_sold")
)
return queryset
then added this code file into the templatetags folder,
app_filters.py
from django import template
register = template.Library()
#register.filter(name = "func_floor_division")
def func_floor_division(num, val):
if num:
floor_division = num // val
return floor_division
else:
return None
#register.filter(name = "func_modulo")
def func_modulo(num, val):
if num:
modulo = num % val
return modulo
else:
return None
and finally modified the tags in the html file.
html
{% load app_filters %}
<table>
<tr>
<th>Floor Division</th>
<th>Modulo</th>
</tr>
{% for obj_ in object_list %}
<tr>
<td>{{ obj_.sum_|func_floor_division:obj_.item_bottleperpack }}</td>
<td>{{ obj_.sum_|func_modulo:obj_.item_bottleperpack }}</td>
</tr>
{% endfor %}
</table>
Hope this helps for anyone who is encountering the same issue.
you can create a new floor_division and module_ fields in your Model_Item, then you use the post save receiver to update the floor_division and module_ fields
from django.db.models.signals import pre_save
class Model_Item(models.Model):
item_name = models.CharField(max_length = 100, null = False, blank = False, unique = True)
item_bottleperpack = models.FloatField(null = True, blank = False) # e.g. 100 bottles per pack
floor_division = models.IntegerField(null=True, blank=True)
module_ = models.IntegerField(null=True, blank=True)
def __unicode__(self):
return self.item_name
def model_item_pre_save(sender, instance, created):
item = Model_Item.objects.get(id=instance.id)
item_transaction = Model_Transaction.objects.get(item_id=instance.id)
item.floor_division = item_transaction.item_sold // item.item_bottleperpack
item.module_ = item_transaction.item_sold %% item.item_bottleperpack
pre_save.connect(model_item_pre_save, sender=Model_Item)
Someone please tell me where I am going wrong. What I'm trying to do is have the user input the quantity of a product that they want and when submitted, if that quantity is more than 0 then display a form equal to the quantity. There are multiple products so I used an if statement to say where the post has this product name, display this form. The result I'm getting is just the forms for the last product sent over. So in a list of [ eggs, ham ], I only get a form for ham . Please help if possible, this is my code below.
View:
if request.method =='POST':
session = request.session._session_key
formtype = request.POST.getlist('name')
i = 0
while i < len(formtype):
for f in formtype:
if f == 'eggs':
item = CompReg.objects.get(sessionid = session, name='eggs')
extra = item.quantity
listmemformset = modelformset_factory(ProBachata, form=ProBachataF,extra=extra)
formset = listmemformset()
elif f == 'ham':
item = CompReg.objects.get(sessionid = session, name='ham')
extra = item.quantity
listmemformset = modelformset_factory(ProBachata, form=ProBachataF,extra=extra)
formset = listmemformset()
i += 1
else:
extra = 0
Template:
{{formset.as_p}}
Actually i didn't fully understand your code (why used while, why you getting item.quantity from db, quantity musn't be in POST data?), but your code can be something like;
if request.method =='POST':
session = request.session._session_key
formtype = request.POST.getlist('name')
formsets = []
for f in formtype:
if f == 'eggs':
item = CompReg.objects.get(sessionid=session, name='eggs')
elif f == 'ham':
item = CompReg.objects.get(sessionid=session, name='ham')
extra = item.quantity
listmemformset = modelformset_factory(ProBachata, form=ProBachataF, extra=extra)
formset = {'name': f, 'form':listmemformset()}
formsets.append(formset)
else:
extra = 0
Template:
{% for formset in formsets %}
name: {{formset.name}}
{{formset.form.as_p}}
{% endfor %}
I'm generating a form from metadata
class MeasureForm(forms.Form):
def __init__(self,*args,**kwargs):
super(MeasureForm,self).__init__()
measure_id = kwargs['measure_id']
m = Measure.objects.get(pk=measure_id);
if (m):
# add the measure identifier as a hidden field
self.fields["measure_id"] = forms.IntegerField(initial = m.id , widget=forms.HiddenInput())
for mp in MeasureParameters.objects.filter(measure = m):
# get the NVL'ed copy of the parameter
p = mp.get_parameter_for_measure()
if not p.is_modifiable:
# the file has a constant value
if (p.values and p.default): # constant must have both values and default index
value_ = p.values[p.values.keys()[p.default-1]];
self.fields[p.name] = forms.IntegerField(
label = p.description ,
initial = value_,
help_text = p.help_text)
self.fields[p.name].widget.attrs['readonly'] = True
else:
raise Exception("Parameter set as unmodifiable but has no value. \
[measure: %s, parameter: %s, measureparameter %s]"
% (m.id , p.id , mp.__unicode__()))
elif (p.values):
# convert hstore dict to list of tuples for the choices to read
values_ = [(v, k) for k, v in p.values.iteritems()];
# set default if exists , else take the first item
default_ = values_[p.default-1][0] if p.default else values_[0][0]
self.fields[p.name] = forms.ChoiceField(
label = p.description ,
choices = values_ ,
initial = default_,
help_text = p.help_text)
else:
self.fields[p.name] = forms.IntegerField(label = p.description, help_text = p.help_text)
if (not p.is_visible):
self.fields[p.name].widget = forms.HiddenInput()
else:
raise Exception ("Could not find measure. [measure %s]" % (m.id))
def clean(self):
return self.cleaned_data;
this is my view
def index(request,measure_id = None):
owners = Owner.objects.all()
form = None
result = None
title = None;
msg = None;
# handle the form
if request.method == 'POST': # the form has been submitted
form = MeasureForm(request.POST, measure_id = request.POST.get('measure_id')) # A form bound to the POST data
result = -100
if form.is_valid(): # All validation rules pass
result = 100
msg = "%s" % repr(form.errors) # list of validation errors
else:
if (measure_id):
title = Measure.objects.get(pk=measure_id).name;
# make an unbound form
form = MeasureForm(measure_id = measure_id)
return render(request, 'calc/index.html' ,
{'owners' : owners,
'form' : form ,
'title' : title ,
'result' : result,
'debug' : msg })
this is a snippet from my template
<div class="content">
{{ form.errors }}
{{ form.non_field_errors }}
{% if form %}
<h2>{{ title }}</h2>
<form action="/calc/{{m.id}}" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Calculate" />
</form>
{% if result %}
The Result is <span class="result"> {{ result }} </span>
{% endif %}
</div>
So i get empty braces {} for "%s" % repr(form.errors), form.errors and form.non_field_errors returns nothing. the form posts and I can see the raw data in the request but i keep getting false from is_valid(). why is that ?
EDIT: when checking if the form is bound i also get false. guessing this is the problem. why isn't the form bound after the call for form = MeasureForm(request.POST, measure_id = request.POST.get('measure_id')) ?
** django newbie, Thanks.
Because you're not passing the arguments into the super call. You should do this:
super(MeasureForm,self).__init__(*args, **kwargs)
otherwise the form will never actually be initialised with the POST data.
Edit after comment The answer to that question didn't recommend removing all the arguments from the super call. If you're passing in measure_id you'll simply need to remove it from kwargs beforehand:
def __init__(self, *args, **kwargs):
measure_id = kwargs.pop('measure_id', None)
super(MeasureForm,self).__init__(*args, **kwargs)
I have created Invoice Pdf text template using pisa. But I want to display logo(image) in the pdf file along with the text. I dont know how to display image in pdf. My views as follows:
def generate_invoice(request, user_id = None):
personal_html = ''
personal_html += 'hai'
fileread = str(settings.TEMPLATE_DIRS[0])+str('/invoice.html')
fr = open(fileread, "r").read()
fr = fr.replace('personal_details', personal_html)
result = StringIO.StringIO()
pdf = pisa.CreatePDF(
fr,result
)
filewrite = str(settings.TEMPLATE_DIRS[0]) + str('/invoice_write.html')
empty = ""
fw = open(filewrite, 'w')
fw.write(empty)
fw.write(fr)
fw.close()
PaymentPdf.objects.filter(invoicepdf = user_id).delete()
pdf_contents = render_to_pdf1('invoice_write.html',result)
file_to_be_saved = ContentFile(pdf_contents)
random_str = ''.join(random.sample((string.ascii_lowercase + string.ascii_uppercase + string.digits), 8))
resume_name = (str(user_id) + "_" + random_str + ".pdf").replace("#", '')
resume = PaymentPdf.objects.create(name = resume_name, invoicepdf_id = user_id, created_by = request.user)
resume.name.save(resume_name ,file_to_be_saved)
file_path = PaymentPdf.objects.get(invoicepdf = user_id).name
pdf_file = str(file_path).split("media")[1]
return HttpResponseRedirect('/site_media' + pdf_file)
def render_to_pdf1(template_src, context_dict):
template = get_template(template_src)
context = Context(context_dict)
html = template.render(context)
result = StringIO.StringIO()
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("ISO-8859-1")), result)
return result.getvalue()
Anyone help me to display image in pdf?
Refer Pisa (XHTML -> PDF) in Django will not display images in PDF, and add the lines
links = lambda uri, rel: os.path.join(settings.MEDIA_ROOT, uri.replace(settings.MEDIA_URL, ''))
pdf = pisa.pisaDocument(StringIO.StringIO(html.encode("UTF-8")),dest=result, link_callback=links)
in render_to_pdf1 of views,
and in html:
<img src="/site_media/img/logo.jpg"/ height="55" width="275">
It will work.
I think that the html contain something like this:
<img src="/media/xxx.jpg"/>
And pisa need something like this:
<img src="http://mydomain.foo/media/xxx.jpg"/>