I cannot show the value in html - python

I cannot show the value in html.
I wrote in views.py
def score_test(request):
results = TestScore.objects.filter(user=request.user).all()
print(results)
return render(request, 'score_test.html',{'results': results})
in score_test.html
<div class="col-xs-12">
<h2 class="result_title">Test Score</h2>
<h3>Your score is
 {% for result in results.all %}
{% if result.score > 95 %}
<h4 class="one"> {{ result.score }} </h4>
{% else %}
{% if result.score > 80 %}
<h4 class="two"> {{ result.score }} </h4>
{% else %}
{% if result.score > 60 %}
<h4 class="three"> {{ result.score }} </h4>
{% else %}
{% if result.score > 40 %}
<h4 class="four"> {{ result.score }} </h4>
{% else %}
<h4 class="five"> {{ result.score }} </h4>
{% endif %}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
</h3>
</div>
in models.py
class TestScore(models.Model):
score = models.FloatField(null=True, blank=True, default=None)
In print(results) of views.py, I got <function tc at 0x105a15d70>, so I think I can get score of TestScore model in results. So, how can I fix this? Am I wrong to write if-else statement in template of score_test.html?

"function tc at 0x105a15d70" is definitely not what TestCore.objects.filter() should return (it should be a queryset), and certainly not what the code you posted could yield, so no surprise you don't see anything in your template.
This being said there are a couple possible improvements to your code...
First, in your view:
results = TestScore.objects.filter(user=request.user).all()
the .all() is redundant. You just need:
results = TestScore.objects.filter(user=request.user)
You could even just use the reverse relation (assuming you didn't specify a related_name in your TestScore.user field):
results = request.user.testscore_set.all()
Then in your templates:
 {% for result in results.all %}
The ".all" is once again useless, and possibly (or not) the cause of your problem. But well, it's useless so don't use it ;)
 {% for result in results %}
Then you could use {% elif <condition> %} instead of nested{% else %}{% if %}`:
{% if result.score > 95 %}
<h4 class="one"> {{ result.score }} </h4>
{% elif result.score > 80 %}
<h4 class="two"> {{ result.score }} </h4>
{% elif result.score > 60 %}
<h4 class="three"> {{ result.score }} </h4>
{% elif result.score > 40 %}
<h4 class="four"> {{ result.score }} </h4>
{% else %}
<h4 class="five"> {{ result.score }} </h4>
{% endif %}
But using a custom template filter would make your code simpler:
# <yourapp>/templatetags/<yourlibname>.py
from django import template
register = template.Library()
#register.filter
def score_grade(score):
try:
score = int(score)
except (TypeError, ValueError):
# XXX should at least log the exception
return ""
if score > 95:
return "one"
elif score > 80:
return "two"
elif score > 60:
return "three"
elif score > 40:
return "four"
else:
return "five"
and in your template:
{% load <yourlibname> %}
{% for result in results %}
<h4 class="{{ result.score|score_grade }}"> {{ result.score }} </h4>
{% endfor %}

You can use elif command.
{% if result.score > 95 %}
<h4 class="one"> {{ result.score }} </h4>
{% elif result.score > 80 %}
<h4 class="two"> {{ result.score }} </h4>
...
{% else %}
<h4 class="five"> {{ result.score }} </h4>
{% endif %}

Related

I am stuck when accessing the DetailView template in Django

urls.py
urlpatterns = [
path('',CourseList.as_view(),name='course_list'),
path('create/',CourseCreate.as_view(),name='course_create'),
path('<int:cid>/',CourseView.as_view(),name='course_view'),
]
views.py
COURSE_PERM_GUEST = 0
COURSE_PERM_STUDENT = 1
COURSE_PERM_TEACHER = 2
COURSE_PERM_MEMBER = 3
class CourseAccessMixin(AccessMixin):
permission = None
extra_context = {}
def dispatch(self,request,*args,**kwargs):
if not request.user.is_authenticated:
return super().handle_no_permission()
self.course = get_object_or_404(Course,id=kwargs['cid'])
user_perm = COURSE_PERM_GUEST
if self.course.teacher == request.user:
user_perm = COURSE_PERM_TEACHER
elif self.course.enroll_set.filter(student=request.user).exists():
user_perm = COURSE_PERM_STUDENT
if not request.user.is_superuser and self.permission is not None:
is_accessible = False
if self.permission == COURSE_PERM_GUEST and \
user_perm == COURSE_PERM_GUEST:
is_accessible = True
elif (self.permission & user_perm) != 0:
is_accessible = True
if not is_accessible:
return super().handle_no_permission()
self.extra_context.update({'course':self.course})
return super().dispatch(request,*args,**kwargs)
class CourseView(CourseAccessMixin,DetailView):
extra_context = {'title':'檢視課程'}
model = Course
pk_url_kwarg = 'cid'
models.py
class Course(models.Model):
name = models.CharField('課程名稱',max_length=50)
enroll_password = models.CharField('選課密碼',max_length=50)
teacher = models.ForeignKey(User,models.CASCADE)
def __str__(self):
return '{}#{} ({})'.format(
self.id,
self.name,
self.teacher.first_name)
course_list.html
{% extends "base.html" %}
{% load user_tags %}
{% block content %}
{% if user|is_teacher %}
<div class="mb-2">
建立課程
</div>
{% endif %}
<div id="course_list">
{% for course in course_list %}
<div class="list-group">
<div class="list-group-item d-flex">
{% if user.is_authenticated %}
{{ course.name }}
{% else %}
{{ course.name }}
{% endif %}
<small class="ml-auto">{{ course.teacher.first_name }} 老師</small>
</div>
</div>
{% endfor %}
</div>
{% include 'pagination.html' %}
{% endblock %}
course_detail.html
{% extends 'base.html' %}
{% load user_tags %}
{% block content %}
<div id="course_view" class="card">
{% with b1 = "btn btn-sm btn-primary" b2 = "btn btn-sm btn-secondary" %}
<div class="card-header d-flex">
<div>
{{ course.name }}
<small>{{ course.teacher.first_name }} 老師</small>
</div>
{% if user.is_superuser or course.teacher == user %}
<div class="ml-auto">
<span class="badge badge-light">
選課密碼: {{ course.enroll_password }}
</span>
<a href="{% url 'course_edit' course.id %}" class="{{ b1 }}">
<i class="fas fa-edit"></i>編輯
</a>
</div>
{% endif %}
</div>
<div class="card-body">
{% block course_detail_body %}
<div id="student_op" class="btn-group">
{% if not course|has_member:user and not user.is_superuser %}
<a href="{% url 'course_enroll' course.id %}" class="{{ b1 }}">
<i class="fas fa-id-badge"></i>選修
</a>
{% else %}
<a href="{% url 'course_users' course.id %}" class="{{ b1 }}">
<i class="fas fa-users"></i>修課名單
</a>
{% if course|has_student:user %}
<a href="{% url 'course_seat' course.id %}" class="{{ b1 }}">
<i class="fas fa-chair"></i>更改座號
</a>
{% endif %}
{% endif %}
</div>
{% endblock %}
</div>
{% endwith %}
</div>
{% endblock %}
Error:
ValueError at /course/1/
The view course.views.CourseView didn't return an HttpResponse object. It returned None instead.
I had a view CourseView and when I try to access the detail of the corresponding course by clicking the hyperlink {{ course.name }} from the template course_list.html, I received the error message showing that it didn't return an HttpResponse object. I do not know what is missing in order to have the details accessible even though I had set the pk_url_kwarg?
You forget to add return super().dispatch(request,*args,**kwargs) and the end of dispatch function (you add it, only in if condition)
change this
self.extra_context.update({'course':self.course})
return super().dispatch(request,*args,**kwargs)
To this:
self.extra_context.update({'course':self.course})
return super().dispatch(request,*args,**kwargs)
return super().dispatch(request,*args,**kwargs)

WTF form.validate_on_submit() Strange Issue

When I click on the submit button, my form validation is equal to True, however nothing displays. The catch is, if I press the submit button again, then everything displays and I no longer have to click the button twice going forward. Up until I restart the server again. I am perplexed and I would greatly appreciate if anyone can tell me what I'm doing wrong.
If I were to remove the validate_on_submit() function the form works fine, but doesn't validate. Which I do not want.
Edit 1
I've added print('------ {0}'.format(request.form)) and print(form.errors) to my code for debugging purposes.
When I insert the values into my form print('------ {0}'.format(request.form)) it prints out the following below:
------ ImmutableMultiDict([('csrf_token', 'IjFiMDE3OGVlZjVjYTYzODQ0MGE2MGMyYWI5NWFjOWYwNjZjMjlmN2Ii.YMFPNw.UtuYhwUnCAlmzdsGNaTEFPM9eek'), ('name', 'Bitcoin'), ('intial_investment', '1500'), ('coin_price', '500'), ('submit', 'Submit')])
While print(form.errors) prints the following:
{'csrf_token': ['The CSRF token is invalid.']}
I would like to believe the root cause of my issue is due to the CSRF being invalid.
However, how can it be invalid when the actual token is listed above?
Edit 2
I've removed {{ form.csrf_token() }} and request.form. Since I don't need to pass in the request when I instance the form.
However, the original issue still persist.
My routes.py
#application.route("/", methods=["GET", "POST"])
def home():
form = Crypto_Form()
coins = None
print('------ {0}'.format(request.form))
print(form.errors)
if form.validate_on_submit():
try:
TWOPLACES = Decimal(10) ** -2
Decimal('3.214').quantize(TWOPLACES)
user_input = form.name.data
coin_name = user_input.lower().replace(" ", "-")
coin_gecko_name = cg.get_coins_markets(vs_currency='usd', ids=[coin_name.lower()], order='market_cap_desc', per_page='1', page='1', sparkline='false')[0]
initial_investment = form.intial_investment.data
coin_image = cg.get_coins_markets(vs_currency='usd', ids=[coin_name.lower()], order='market_cap_desc', per_page='1', page='1', sparkline='false')[0]
coin_price = float(cg.get_price(ids=[coin_name.lower()], vs_currencies='usd')[coin_name.lower()]['usd'])
presale_price = form.coin_price.data
multiplier = Decimal(float(coin_price) / float(presale_price)).quantize(TWOPLACES)
profit = round((float(initial_investment) / float(presale_price)) * float(coin_price))
twenty_four_hour_change = Decimal(cg.get_price(ids=[coin_name.lower()], vs_currencies='usd', include_24hr_change='true')[coin_name.lower()]['usd_24h_change']).quantize(TWOPLACES)
ath = cg.get_coins_markets(vs_currency='usd', ids=[coin_name.lower()], order='market_cap_desc', per_page='1', page='1', sparkline='false')[0]
ath_change_percentage = cg.get_coins_markets(vs_currency='usd', ids=[coin_name.lower()], order='market_cap_desc', per_page='1', page='1', sparkline='false')[0]
coin = Coin(
crypto_name=coin_gecko_name['name'],
coin_initial_invesment=initial_investment,
image=coin_image['image'],
current_price=coin_price,
presale_price=presale_price,
multiple= multiplier,
profit=profit,
twenty_four_hour=twenty_four_hour_change,
all_time_high=ath['ath'],
all_time_percentage_change=Decimal(ath['ath_change_percentage']).quantize(TWOPLACES)
)
db.session.add(coin)
db.session.commit()
except Exception as e:
db.session.rollback()
print('Failed to add coin')
print(e)
coins = Coin.query.all()
coin_profit = Coin.query.with_entities(func.sum(Coin.profit).label('total')).first().total
if coin_profit is None:
coin_profit = 0
return render_template("home.html", coins=coins, value=coin_profit, form=form)
My forms.py
class Crypto_Form(Form):
name = StringField("Enter Coin Name", [validators.DataRequired(message="Please enter the Crypto Currency name.")])
intial_investment = DecimalField("Enter Initial Investment", [validators.DataRequired(message="Please enter a number")])
coin_price = DecimalField("Enter Coin Price", [validators.DataRequired(message="Please enter a number")])
submit = SubmitField("Submit")
My Jinja form
<form class="justify-content-center" method="POST" name="Crypto_Info" role="form">
{{ form.hidden_tag()
<div class="form-group">
{{ form.name.label(class="form-control-label") }}
{% if form.name.errors %}
{{ form.name(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in form.name.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.name(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.intial_investment.label(class="form-control-label") }}
{% if form.intial_investment.errors %}
{{ form.intial_investment(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in form.intial_investment.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.intial_investment(class="form-control form-control-lg") }}
{% endif %}
</div>
<div class="form-group">
{{ form.coin_price.label(class="form-control-label") }}
{% if form.coin_price.errors %}
{{ form.coin_price(class="form-control form-control-lg is-invalid")}}
<div class="invalid-feedback">
{% for error in form.coin_price.errors %}
<span>{{ error }}</span>
{% endfor %}
</div>
{% else %}
{{ form.coin_price(class="form-control form-control-lg") }}
{% endif %}
</div>
<div>
{{ form.submit(class="btn btn-primary") }}
</div>
</form>

Python Jinjna variable doesnt keep value outside loop

I am currently trying to fix an issue by using jinja variables, but somehow the variable does not keep the value outside the loop, even though I declared it before the loop begins:
{% set disablecounter = 0 %}
{% if disablecounter == 0 %}
{% for einzelroom in all_einzelzimmer %}
{% if zimmer.id == einzelroom.zimmer_id %}
{% set price = einzelroom.preis %}
<div class="preis-element">
<p class="preis"> <span class="smallab"> ab </span> {{ price|int }}€ </p>
</div>
{% set disablecounter = disablecounter + 1 %}
{{ disablecounter }}
{% endif %}
{% endfor %}
{% endif %}
{{ disablecounter }}
The variable is disablecounter inside the loop it is 1 but outside it is still 0
Thanks!
EDIT
Surrounding with a with statement also didnt worked:
{% with foo = 42 %}
{{ foo }}
{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}
{% endwith %}
I found a great solution here on SO by #Chris Warth.
Original answer by #Peter Hollingsworth:
https://stackoverflow.com/a/32700975/5291566
{% with disablecounter = [0] %}
{% if disablecounter == [0] %}
{% for einzelroom in all_einzelzimmer %}
{% if zimmer.id == einzelroom.zimmer_id %}
<div class="preis-element">
<p class="preis"> <span class="smallab"> ab </span> {{ einzelroom.preis|int }}€ </p>
</div>
{% if disablecounter.append(disablecounter.pop() + 1) %}{% endif %}
{% endif %}
{% endfor %}
{% endif %}

Django Template - neat 1-1 translation of values (dictionary lookup)

I've an object containing an attribute defined by a series of choices - here's it's class definition:
class StashURLJobRequest(models.Model):
STATUS_CHOICES = ((0,"Requested"),(1,"Done"),(2,"Failed"))
url = models.URLField()
created = models.DateTimeField(auto_now_add = True, auto_now=False)
processed = models.DateTimeField(auto_now_add = False, auto_now = True)
status = models.IntegerField(choices=(STATUS_CHOICES))
requestBy = models.CharField(max_length=32)
def __unicode__(self):
return smart_unicode(self.url + str(self.created))
def status_display(self):
status_dict = dict(self.STATUS_CHOICES)
return status_dict[self.status]
I get a list of these and pass through into a template, intending to render each one as an individual row, again, here's the template code:
{% for job_instance in jobs %}
<div class="width100pc">
<div class="width10pc"> <img src="{% static 'img/empty.png' %}" /> </div>
<div class="width80pc">
<div class="width70pc textleft sans textsmall "> {{ job_instance.url }} </div>
<div class="width15pc textcentre sans texttiny "> {{ job_instance.processed }} </div>
<div class="width5pc textcentre sans texttiny {% ifequal job_instance.status_display 'Done' %} status_green {% endifequal %}
{% ifequal job_instance.status_display 'Requested' %} status_amber {% endifequal %}
{% ifequal job_instance.status_display 'Failed' %} status_red {% endifequal %}"> {{ job_instance.status_display }} </div>
<div class="width10pc textcentre sans texttiny"> {{ job_instance.requestBy }} </div>
</div>
<div class="width10pc"> <img src="{% static 'img/empty.png' %}" /> </div>
</div>
{% endfor %}
In particular, note the section:
{% ifequal job_instance.status_display 'Done' %} status_green {% endifequal %}
{% ifequal job_instance.status_display 'Requested' %} status_amber {% endifequal %}
{% ifequal job_instance.status_display 'Failed' %} status_red {% endifequal %}
Each of {status_green, status_amber and status_red} refer to a different css class, and allows me to render the status in an appropriate colour.
This seems a little unwieldy, and I don't want to code the css-class into the model, or the view (preferring to leave format and display to the template/html definitions) - so the question is, is there a way to do this that's more "pythonic" - ideally, I'd like to use something like:
{{ class_dict = {'Done' : 'status_green', 'Requested' : 'status_amber', 'Failed' : 'status_red' } }}
< ... some code ... >
{{ class_dict[job_instance.status_display] }}
(dodgy curly-braces aside!)
Add a helper function to the object, so that you don't need any logic in the template?
Add to StashURLJobRequest
def status_display_colour(self):
return {
"Done":"status_green",
"Requested":"status_amber",
"Failed":"status_red"
}[ self.status_display() ]
And the template becomes <div class="width5pc textcentre sans texttiny {{ job_instance.status_display_colour }} ...
Another way would be class="... my-class-{{job_instance.status_display}}" with my-class-Done, my-class-Requested, my-class-Failed appropriately defined in your css. It's inferior because it depends implicitly on status_display remaining a single word with no spaces or other special characters.

Break items into columns evenly in Jinja2 template

I have a list of cities names that is variable and I want to break it into 4 columns evenly. I have some solution but it looks overwhelmed and dirty. What's the best and simplest way to do it?
My solution is here:
{% set cities_in_column = cities|length/4|int %}
{% set step=0 %}
<div class="four columns">
{% for city in cities|sort %}
{% if step > cities_in_column %}
{% set step = 0 %}
</div>
<div class="four columns">
{% endif %}
<h5>{{ city.name }} <span style="float:right;">({{ city.users_count }})</span></h5>
{% set step=step + 1 %}
{% endfor %}
</div>
You are looking for the slices filter:
{% for column in cities | sort | slice(4) -%}
<div class="four columns">
{%- for city in column -%}
<h5>{{ city.name }}
<span style="float:right;">({{ city.users_count }})</span></h5>
{%- endfor -%}
</div>
{%- endfor %}
There is also a complement to slices called batch that provides runs of n (rather than splitting up the iterable into n groups).
This is a job for CSS*:
<ol style="column-count: 4;">
{% for city in cities|sort %}
<li>
{{ city.name }} ({{ city.users_count }})
</li>
{% endfor %}
</ol>
(*Be it column-count, float, flex, etc..)

Categories