如何隐式(动态地)在模板中显示模型的属性
How to display model's attributes in template implicitly (dynamically)
我正在为我的游戏制作高分应用程序。
这是我的模型
class Skills(models.Model):
attack = models.IntegerField(default=1)
attack_xp = models.FloatField(default=0)
constitution = models.IntegerField(default=10)
constitution_xp = models.FloatField(default=0)
mining = models.IntegerField(default=1)
mining_xp = models.FloatField(default=0)
strength = models.IntegerField(default=1)
strength_xp = models.FloatField(default=0)
agility = models.IntegerField(default=1)
agility_xp = models.FloatField(default=0)
smithing = models.IntegerField(default=1)
smithing_xp = models.FloatField(default=0)
defence = models.IntegerField(default=1)
defence_xp = models.FloatField(default=0)
herblore = models.IntegerField(default=1)
herblore_xp = models.FloatField(default=0)
fishing = models.IntegerField(default=1)
fishing_xp = models.FloatField(default=0)
ranged = models.IntegerField(default=1)
ranged_xp = models.FloatField(default=0)
thieving = models.IntegerField(default=1)
thieving_xp = models.FloatField(default=0)
cooking = models.IntegerField(default=1)
cooking_xp = models.FloatField(default=0)
prayer = models.IntegerField(default=1)
prayer_xp = models.FloatField(default=0)
crafting = models.IntegerField(default=1)
crafting_xp = models.FloatField(default=0)
firemaking = models.IntegerField(default=1)
firemaking_xp = models.FloatField(default=0)
magic = models.IntegerField(default=1)
magic_xp = models.FloatField(default=0)
fletching = models.IntegerField(default=1)
fletching_xp = models.FloatField(default=0)
woodcutting = models.IntegerField(default=1)
woodcutting_xp = models.FloatField(default=0)
runecrafting = models.IntegerField(default=1)
runecrafting_xp = models.FloatField(default=0)
slayer = models.IntegerField(default=1)
slayer_xp = models.FloatField(default=0)
farming = models.IntegerField(default=1)
farming_xp = models.FloatField(default=0)
construction = models.IntegerField(default=1)
construction_xp = models.FloatField(default=0)
hunter = models.IntegerField(default=1)
hunter_xp = models.FloatField(default=0)
summoning = models.IntegerField(default=1)
summoning_xp = models.FloatField(default=0)
dungeoneering = models.IntegerField(default=1)
dungeoneering_xp = models.FloatField(default=0)
overall_xp = models.FloatField(default=0)
overall = models.IntegerField(default=0)
user_name = models.CharField(max_length=30, primary_key=True)
如您所见,有很多属性。
共有25个技能等级和经验值。
我想按照模型 class 中指定的顺序在我的模板上显示它。
像这样
attack_level | attack_exp
constitutionlvl | constitution_exp
mining_level | mining_exp
在 table.
我知道我可以明确地做到这一点,但我不想那样做。
这是我目前尝试过的方法
我试过像这样执行原始查询
cursor.execute("SELECT * FROM highscores_skills WHERE user_name = %s", [user_name])
这样我就可以获取列表中的数据,然后在模板上循环它,但它按列名对数据进行排序。
攻击 -> 体质 -> 构造 -> 制作..等等。
如果我不使用星号而是使用列名,那么我得到了我想要的,但还有一个问题。
这是我的模板代码
{% for skill in skills %}
<tr>
<td class = "col1 align">
<a href="">{{ skill }}</a>
</td>
<td class = "col2">
<a href="">{{ player|lookup:forloop.counter0 }}</a>
</td>
<td class = "col3 align">
<a href="">{{ player|lookup:forloop.counter }}</a>
</td>
</tr>
{% endfor %}
循环运行了 25 次。 skills 是一组技能名称。
我制作了一个自定义过滤器,以使用循环计数器按索引获取列表数据。
如果我最后设法将循环计数器的值 +1,这个东西就会起作用。
因为现在是这样的:
一个好的解决方案是创建两个模型字段 sub类,一个用于存储技能等级,一个用于存储技能 XP。这会给出类似的东西:
from django.db import models
class XpField(models.FloatField):
'''
Django model field used to store a skill XP.
'''
def __init__(self, *args, **kwargs):
# Have a default "default" set to 0.
if kwargs.get('default') is None:
kwargs['default'] = 0
super(XpField, self).__init__(*args, **kwargs)
class LevelField(models.IntegerField):
'''
Django model field used to store a skill level.
Takes a required argument xp_field which is the XpField
associated with this field's skill.
'''
def __init__(self, *args, **kwargs):
# Have a default "default" set to 1.
if kwargs.get('default') is None:
kwargs['default'] = 1
self.xp_field = kwargs.pop('xp_field')
super(LevelField, self).__init__(*args, **kwargs)
如您所见,LevelField
存储了对 XpField
实例的引用,该实例应该是代表相同技能的 XP 的字段。
然后您可以使用这些字段 类:
来设置您的 Skills
模型
class Skills(models.Model):
attack_xp = XpField()
attack = LevelField(xp_field=attack_xp)
# etc...
def get_skills(self):
'''
Returns a list of dictionnaries containing name, level and XP
for each of the model's skills.
'''
skill_values = []
# Iterate over all the model's fields.
for field in self._meta.get_fields():
if isinstance(field, LevelField):
level = getattr(self, field.name)
xp = getattr(self, field.xp_field.name)
skill_values.append({
'name': field.name,
'level': level,
'xp': xp,
})
return skill_values
get_skills
方法将遍历 Skills
模型字段,检测那些 LevelField
实例并使用它们构建技能数据列表。
Model._meta.get_fields 方法只出现在 Django 1.8 中。如果您使用的是旧版本,我认为 Model._meta.fields
可以解决问题。
然后您可以这样在模板中使用它:
{% for skill in skills.get_skills %}
<tr>
<td class = "col1 align">
<a href="">{{ skill.name }}</a>
</td>
<td class = "col2">
<a href="">{{ skill.level }}</a>
</td>
<td class = "col3 align">
<a href="">{{ skill.xp }}</a>
</td>
</tr>
{% endfor %}
P.S:我没有测试代码,因此它可能包含错误,但我希望这能让您了解如何解决您的问题。
我正在为我的游戏制作高分应用程序。 这是我的模型
class Skills(models.Model):
attack = models.IntegerField(default=1)
attack_xp = models.FloatField(default=0)
constitution = models.IntegerField(default=10)
constitution_xp = models.FloatField(default=0)
mining = models.IntegerField(default=1)
mining_xp = models.FloatField(default=0)
strength = models.IntegerField(default=1)
strength_xp = models.FloatField(default=0)
agility = models.IntegerField(default=1)
agility_xp = models.FloatField(default=0)
smithing = models.IntegerField(default=1)
smithing_xp = models.FloatField(default=0)
defence = models.IntegerField(default=1)
defence_xp = models.FloatField(default=0)
herblore = models.IntegerField(default=1)
herblore_xp = models.FloatField(default=0)
fishing = models.IntegerField(default=1)
fishing_xp = models.FloatField(default=0)
ranged = models.IntegerField(default=1)
ranged_xp = models.FloatField(default=0)
thieving = models.IntegerField(default=1)
thieving_xp = models.FloatField(default=0)
cooking = models.IntegerField(default=1)
cooking_xp = models.FloatField(default=0)
prayer = models.IntegerField(default=1)
prayer_xp = models.FloatField(default=0)
crafting = models.IntegerField(default=1)
crafting_xp = models.FloatField(default=0)
firemaking = models.IntegerField(default=1)
firemaking_xp = models.FloatField(default=0)
magic = models.IntegerField(default=1)
magic_xp = models.FloatField(default=0)
fletching = models.IntegerField(default=1)
fletching_xp = models.FloatField(default=0)
woodcutting = models.IntegerField(default=1)
woodcutting_xp = models.FloatField(default=0)
runecrafting = models.IntegerField(default=1)
runecrafting_xp = models.FloatField(default=0)
slayer = models.IntegerField(default=1)
slayer_xp = models.FloatField(default=0)
farming = models.IntegerField(default=1)
farming_xp = models.FloatField(default=0)
construction = models.IntegerField(default=1)
construction_xp = models.FloatField(default=0)
hunter = models.IntegerField(default=1)
hunter_xp = models.FloatField(default=0)
summoning = models.IntegerField(default=1)
summoning_xp = models.FloatField(default=0)
dungeoneering = models.IntegerField(default=1)
dungeoneering_xp = models.FloatField(default=0)
overall_xp = models.FloatField(default=0)
overall = models.IntegerField(default=0)
user_name = models.CharField(max_length=30, primary_key=True)
如您所见,有很多属性。 共有25个技能等级和经验值。
我想按照模型 class 中指定的顺序在我的模板上显示它。 像这样
attack_level | attack_exp
constitutionlvl | constitution_exp
mining_level | mining_exp
在 table.
我知道我可以明确地做到这一点,但我不想那样做。
这是我目前尝试过的方法
我试过像这样执行原始查询
cursor.execute("SELECT * FROM highscores_skills WHERE user_name = %s", [user_name])
这样我就可以获取列表中的数据,然后在模板上循环它,但它按列名对数据进行排序。 攻击 -> 体质 -> 构造 -> 制作..等等。
如果我不使用星号而是使用列名,那么我得到了我想要的,但还有一个问题。
这是我的模板代码
{% for skill in skills %}
<tr>
<td class = "col1 align">
<a href="">{{ skill }}</a>
</td>
<td class = "col2">
<a href="">{{ player|lookup:forloop.counter0 }}</a>
</td>
<td class = "col3 align">
<a href="">{{ player|lookup:forloop.counter }}</a>
</td>
</tr>
{% endfor %}
循环运行了 25 次。 skills 是一组技能名称。 我制作了一个自定义过滤器,以使用循环计数器按索引获取列表数据。 如果我最后设法将循环计数器的值 +1,这个东西就会起作用。
因为现在是这样的:
一个好的解决方案是创建两个模型字段 sub类,一个用于存储技能等级,一个用于存储技能 XP。这会给出类似的东西:
from django.db import models
class XpField(models.FloatField):
'''
Django model field used to store a skill XP.
'''
def __init__(self, *args, **kwargs):
# Have a default "default" set to 0.
if kwargs.get('default') is None:
kwargs['default'] = 0
super(XpField, self).__init__(*args, **kwargs)
class LevelField(models.IntegerField):
'''
Django model field used to store a skill level.
Takes a required argument xp_field which is the XpField
associated with this field's skill.
'''
def __init__(self, *args, **kwargs):
# Have a default "default" set to 1.
if kwargs.get('default') is None:
kwargs['default'] = 1
self.xp_field = kwargs.pop('xp_field')
super(LevelField, self).__init__(*args, **kwargs)
如您所见,LevelField
存储了对 XpField
实例的引用,该实例应该是代表相同技能的 XP 的字段。
然后您可以使用这些字段 类:
来设置您的Skills
模型
class Skills(models.Model):
attack_xp = XpField()
attack = LevelField(xp_field=attack_xp)
# etc...
def get_skills(self):
'''
Returns a list of dictionnaries containing name, level and XP
for each of the model's skills.
'''
skill_values = []
# Iterate over all the model's fields.
for field in self._meta.get_fields():
if isinstance(field, LevelField):
level = getattr(self, field.name)
xp = getattr(self, field.xp_field.name)
skill_values.append({
'name': field.name,
'level': level,
'xp': xp,
})
return skill_values
get_skills
方法将遍历 Skills
模型字段,检测那些 LevelField
实例并使用它们构建技能数据列表。
Model._meta.get_fields 方法只出现在 Django 1.8 中。如果您使用的是旧版本,我认为 Model._meta.fields
可以解决问题。
然后您可以这样在模板中使用它:
{% for skill in skills.get_skills %}
<tr>
<td class = "col1 align">
<a href="">{{ skill.name }}</a>
</td>
<td class = "col2">
<a href="">{{ skill.level }}</a>
</td>
<td class = "col3 align">
<a href="">{{ skill.xp }}</a>
</td>
</tr>
{% endfor %}
P.S:我没有测试代码,因此它可能包含错误,但我希望这能让您了解如何解决您的问题。