#python #django
#python #django
Вопрос:
Я отображаю данные из моей базы данных MySQL. Я хотел бы удалить начальные нули в определенных полях ( ops
и obp
fields), только когда значение слева от десятичной точки равно 0. Если цифра (ы) слева от десятичной точки не равна 0, то я, очевидно, хочу, чтобы это отображалось.
Например,
-
0,750 становится .750
-
1.000 остается как есть
Я подозреваю, что это можно сделать при вызове данных с использованием шаблона django или в views.py . Как бы я сделал любой из них?
Любая помощь по этому вопросу была бы очень признательна! Спасибо.
views.py
from django.shortcuts import render
from .models import BattingRegStd
# Create your views here.
def batting(request):
battingregstd2018 = BattingRegStd.objects.filter(year=2018)
return render(request, 'playerstats/battingReg2018.html', {'battingregstd2018':battingregstd2018})
models.py
class BattingRegStd(models.Model):
id = models.IntegerField(db_column='ID', primary_key=True) # Field name made lowercase.
obp = models.FloatField(db_column='OBP', blank=True, null=True) # Field name made lowercase.
ops = models.FloatField(db_column='OPS', blank=True, null=True) # Field name made lowercase.
tb = models.IntegerField(db_column='TB', blank=True, null=True) # Field name made lowercase.
HTML
{% extends "base.html" %}
{% block contents %}
<div>
<table>
<thead>
<tr>
<th>OBP</th>
<th>OPS</th>
<th>TB</th>
</tr>
</thead>
<tbody>
{% for index in battingregstd2018%}
<td>{{ index.obp}}</td>
<td>{{ index.ops}}</td>
<td>{{ index.tb}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
Ответ №1:
Вы можете использовать
def batting_avg_format(num):
numstr = str(num)
if numstr[0]!='0':
return numstr
else:
return numstr[1:]
Либо включите это как метод в свою BattingRegStd
модель и примените его, либо непосредственно выполните понимание списка после того, как вы отфильтровали модель, но перед тем, как отрендерить свой HTML. Преимущество включения его в качестве метода модели заключается в том, что теперь вы можете вызывать его из шаблона, при условии, что единственным параметром в вашем методе является self
.
Комментарии:
1. если вы добавите это в свою модель, вы сделаете это немного по-другому, поскольку это будет метод-член. для ods вы бы сделали что-то вроде
def batting_avg_format(self): numstr=str(self.obs)
т.е. num будет заменен атрибутом, который вы хотите отформатировать.2. Таким образом, для этого не понадобились бы никакие параметры, и теперь вы могли бы сделать это
{{someobj.batting_avg_format}}
из своего шаблона, гдеsomeobj
указано имя вашегоBattingRegStd
объекта, напримерindex
, в вашем коде.3. Может кто-нибудь просмотреть мой код, чтобы увидеть, что я делаю не так с подходом Хуана? Нажмите на эту ссылку, она приведет вас к моему коду: codeshare.io/aybOWo
Ответ №2:
Я предполагаю, что это значение больше нуля.
views.py
def batting(request):
battingregstd2018 = BattingRegStd.objects.filter(year=2018)
for i in range(0, len(battingregstd2018)):
# if need to edit value
if battingregstd2018[i].obp is not None and battingregstd2018[i].obp < 1:
# data edit as string
# data type does not matter in template
battingregstd2018[i].obp = str(battingregstd2018[i].obp)[1:]
if battingregstd2018[i].ops is not None and battingregstd2018[i].ops < 1:
battingregstd2018[i].ops = str(battingregstd2018[i].ops)[1:]
return render(request, 'playerstats/battingReg2018.html', {'battingregstd2018':battingregstd2018})
чем вторая попытка,
давайте просто исправим шаблон на этот раз. используйте оригинальный view.py
{% for index in battingregstd2018%}
<td>
{% if index.obp is None %}
-
{% elif index.obp < 1 %}
.{{index.obp|slugify|slice:"1:"}}
{% else %}
{{index.obp}}
{% endif %}
</td>
{% endfor %}
.{{index.obp|slugify|slice:"1:"}}
|slice
может использоваться только в строковом типе данных.
|slugify
преобразует в ASCII для использования |slice
. но десятичная точка удаляется.
поэтому я добавил .
в начало.
ps)
возможно, тип float будет сохраняться 0.750
как 0.75
. если вы хотите 0.750
, чем использовать его .{{index.obp|floatformat:"3"|slugify|slice:"1:"}}
Комментарии:
1. это отображается
'<' not supported between instances of 'NoneType' and 'int'
… Кроме того, как бы я вызвал ops в своих шаблонах?2. @NickT если раньше это хорошо работало (0.750, 1.000, …), не нужно изменять шаблон. я не видел, чтобы значение было пустым. я добавил условие в оператор if.
3. Облом. Все еще не работает. Теперь шаблон будет отображаться без ошибки, но без изменений. По-прежнему отображается 0 перед десятичными точками. Должен ли я был буквально просто скопировать и вставить это в представления, изменить urls.py чтобы указать на
batting
представление и вызвать шаблон как<td>{{index.ops|default_if_none:"—"|floatformat:3}}</td>
?4. @NickT я пробую другой способ.
5. предсказуемость… этот второй вариант работает, и он самый простой! По-видимому, не так много людей знают об этом. Я спрашивал на паре форумов. Множество просмотров, всего пара ответов и одно решение! Единственное, что я бы добавил, это
|floatformat:"3"
в инструкции else
Ответ №3:
Примеры, которые вы можете подтвердить в оболочке Python, протестированной с Python 3.5.3:
x = "0.750"
x.lstrip("0")
> '.750'
# Included because a normal floating point type won't print trailing zeroes:
from decimal import Decimal
x = Decimal("0.750")
x.to_eng_string().lstrip("0")
> '.750'
str(x).lstrip("0")
> '.750'
Хотя вы не сможете сделать это в шаблонах Django, если вы не заменили движок на jinja2 или что-то еще, что позволяет использовать скобки в вызовах методов, вы можете сделать это либо в представлении (возможно, некрасиво, в зависимости от того, как вы извлекаете эти данные), либо в простом пользовательском шаблоне filter.