我有3个模型来自三个不同的表:
class Profile(models.Model):
player_name = models.CharField(max_length=150)
player_surname=models.CharField(max_length=200)
class Meta:
db_table='profiles'
class Results_2019(models.Model):
player_name = models.CharField(max_length=150)
first_score=models.DecimalField(decimal_places=2,max_digits=1000)
second_score=models.DecimalField(decimal_places=2,max_digits=1000)
class Meta:
db_table='results_2019'
class Results_2018(models.Model):
player_name = models.CharField(max_length=150)
first_score=models.DecimalField(decimal_places=2,max_digits=1000)
second_score=models.DecimalField(decimal_places=2,max_digits=1000)
class Meta:
db_table='results_2018'
数据库是静态的。所有三个模型中的播放器都有相同的名称=[Alex','handler','Zach'],并且它们都有属于它们的所有列的数据(first_score,second_score
(
配置文件数据库看起来像:
id player_name player_surname
1 Alex Chapman
2 Chandler Wellington
3 Zach Berg
结果_2019数据库看起来像:
id profile_id player_name first_score second_score
1 1 Alex 70 68
2 2 Chandler 60 62
3 3 Zach 90 85
结果_2018数据库看起来像:
id profile_id player_name first_score second_score
1 1 Alex 78 81
2 2 Chandler 56 66
3 3 Zach 97 95
我想根据Results_2019和Results_2018的值进行计算,得到:
-2019年和2018年在firstrongcore和second_score中增长超过20%的玩家,然后获得符合这些标准的姓名并打印在模板中
下面的标准公式虽然不起作用,但我将其作为我想要实现的目标的指导。
first_score_growth=((Results_2019.first_score/Results_2018.first_score)*100)
和
second_score_growth=((Results_2019.second_score/Results_2018.second_score)*100)
到目前为止我能做什么:
为此,我为数据库分配了外键,我在mysqlprodile_id
中有一个单独的列。然而,它甚至不进行迁移。
我可以从1 DB表(Results_2019
(中计算和过滤结果:
total=Results_2019.objects.annotate(
total_score=(F('first_score') + F('second_score'))/2).filter(total_score__gt=80,)
但这计算的是2019年的总分,而不是增长。
此外,当我将外键添加到Results_2019时,它会给我这样的OperationalError(1054,"字段列表中的未知列'Results_2019.profile_id'"(
如果你能帮我解决这个问题,我将不胜感激。
首先,我建议重组您的模型,以便结果链接到概要文件,并且您有一个带有年度字段的单个结果模型。我看到你的结果类中有播放器名称,但这可以通过与播放器模型(如result.player.firstname
(的关系来访问。顺便说一句,模型通常用单数表示,即Profile,而不是Profiles。
class Player(models.Model):
firstname = models.CharField(max_length=150)
surname = models.CharField(max_length=200)
class Result(models.Model):
player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='results')
year = models.IntegerField() # this is where you would store 2018 or 2019
score = models.DecimalField(decimal_places=2, max_digits=1000)
我还删除了firstrongcore和second_score,这样每个结果只有一个分数字段。因此,每个分数和年份都有一个Result对象,这样可以更容易地使用注释、聚合和筛选。
使用注释来创建所需的增长价值当然是正确的,但这受到了模型布局的阻碍。一旦你重组了你的模型,你就可以得到这样的增长:
score1 = Avg('results__score', filter=Q(results__year=2018))
score2 = Avg('results__score', filter=Q(results__year=2019))
player_growth = Player.objects.values().annotate(growth=(score2/score1)*100)
请注意,使用"results_score"使用玩家字段中设置的相关名称,并从链接到该玩家的每个结果中获取分数。
上面应该返回类似的内容(使用伪数据(:
{'id': 1, 'firstname': 'John', 'surname': 'Smith', 'growth': Decimal('110.0')}
编辑:如果您无法更改模型结构,则可以使用其他方法,将方法添加到Player模型中。注意,您应该将Result关系更改为OneToOneField。
def get_first_score_growth(self):
return self.results_2019.first_score / self.results_2018.first_score * 100
你可以在这样的模板中调用它:
{% for player in players %}
{{ player.get_first_score_growth }}
{% endfor %}
您的模型结构似乎非常复杂。为什么每年都要创建不同的表格?只需在Result表中添加一个year
字段,就可以完成您的工作。
型号
class Result(models.Model):
player=models.ForeignKeyField(Profiles)
first_score=models.DecimalField(decimal_places=2,max_digits=1000)
second_score=models.DecimalField(decimal_places=2,max_digits=1000)
year=models.CharField(max_length=4)
class Meta:
db_table='result'
现在,您可以编写查询以获得所需的数据。
根据您是否需要进行一次或多次计算,我可能会创建一个新列。现在创建一个新列将使以后的计算更容易。如果你不想创建一个新的专栏,你可以找到每年增长的人,并列出一个列表。
如果它们同时出现在这两个列表中,那么你就知道它们在2018年和2019年都有所增长。
def myPageView(request):
GrowthNames = []
# loop through both tables
for MyResults in [Results_2018, Results_2019]:
# Get all objects and calculate growth
results_list = MyResults.objects.all()
for result in results_list:
score1 = result.first_score
score2 = result.second_score
growth = (score2 - score1) / score1
# if growth is > 20%, add it to our list
if growth > .02:
GrowthNames.append(results.player_name)
# Now, we must find which items appear in our list twice (once for 2018, once for 2019)
DoubleGrowthNames = list(set([x for x in GrowthNames if GrowthNames.count(x) == 2])
# With our list our names, we can now get their surnames via querying
FinalNames = []
for name in DoubleGrowthNames:
MyProfile = Profile.objects.filter(player_name=name)[0]
FinalNames.append(f'{MyProfile.player_name} {MyProfile.player_surname}')
# Finally, let's return this to the template
return render(request, 'page.html', {'FinalNames': FinalNames})
在page.html中:
{% for name in FinalNames %}
<div>{{name}}</div>
{% endif %}