Python 将类变量名传递给类方法

Python 将类变量名传递给类方法,python,django,django-models,Python,Django,Django Models,我有一个定义如下的模型: class ProblemVerificationModel(CreateUpdateDateModel): problem = models.ForeignKey(Problem, related_name="problem_survey") verifier = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="verified_problem") is_problem

我有一个定义如下的模型:

class ProblemVerificationModel(CreateUpdateDateModel):
    problem = models.ForeignKey(Problem, related_name="problem_survey")
    verifier = models.ForeignKey(settings.AUTH_USER_MODEL,    related_name="verified_problem")

    is_problem_properly_formated = ... # BooleanField
    is_this_done = ... # BooleanField
    is_that_done = ... # BooleanField
    # other BooleanFields
在我的应用程序中,上面的模型就像一个投票系统。我需要计算每个属性的投票百分比,例如
是否存在问题\u格式是否正确
是否该属性已完成
是否该属性已完成
等。我使用的classmethod定义如下:

@classmethod
def percentage_problem_properly_formated(cls, problem):
    votes = cls.objects.filter(problem=problem)
    total_votes = votes.count()
    yes_votes = votes.filter(is_problem_properly_formated=True).count()
    percentage_yes = (yes_votes / total_votes) * 100
    return percentage_yes

@classmethod
def percentage_is_this_done(cls, problem):
    votes = cls.objects.filter(problem=problem)
    total_votes = votes.count()
    yes_votes = votes.filter(is_this_done=True).count()
    percentage_yes = (yes_votes / total_votes) * 100
    return percentage_yes
现在,对于每个属性,我都使用类似的方法,不同之处在于将参数传递给filter方法。这当然不是一种枯燥的做事方式

我只需要一个方法,我可以将参数传递给filter方法


您是否可以帮助或提供提示,以实现相同的干式结果?

将筛选器参数作为dict传递,并使用
**
语法将其解压缩:

@classmethod
def percentage_is_this_done(cls, problem, filters):
    votes = cls.objects.filter(problem=problem)
    total_votes = votes.count()
    yes_votes = votes.filter(filters).count()
    percentage_yes = (yes_votes / total_votes) * 100
    return percentage_yes
要调用此方法,请执行以下操作:

MyClass.percentage_is_this_done(problem, {'is_this_done': True})

将筛选器参数作为dict传递,并使用
**
语法将其解压缩:

@classmethod
def percentage_is_this_done(cls, problem, filters):
    votes = cls.objects.filter(problem=problem)
    total_votes = votes.count()
    yes_votes = votes.filter(filters).count()
    percentage_yes = (yes_votes / total_votes) * 100
    return percentage_yes
要调用此方法,请执行以下操作:

MyClass.percentage_is_this_done(problem, {'is_this_done': True})

首先,像这样对模型进行查询的方法实际上属于管理器,而不是模型本身

其次,可以使用字典扩展动态传递要过滤的字段

class ProblemVerificationManager(models.Manager):
    def percentage(self, problem, filter_keyword):
        votes = self.filter(problem=problem)
        total_votes = votes.count()
        yes_votes = votes.filter(**{filter_keyword: True}).count()
        percentage_yes = (yes_votes / total_votes) * 100
        return percentage_yes

class ProblemVerificationModel(CreateUpdateDateModel):
    ...
    objects = ProblemVerificationManager()
现在您可以将其称为
ProblemVerificationModel.objects.percentage(问题“是否正确格式化了问题”)

在Django 2.0+中,您可以使用聚合返回在单个db查询中匹配的完整计数和百分比:

from django.db.models import Count, Q

class ProblemVerificationManager(models.Manager):
    def percentage(self, problem, filter_keyword):
        votes = self.filter(problem=problem).aggregate(
           yes_votes=Count(1, filter=Q(**{filter_keyword: True}),
           total_votes=Count(1)
        )
        percentage_yes = (votes['yes_votes'] / votes['total_votes']) * 100
        return percentage_yes

首先,像这样对模型进行查询的方法实际上属于管理器,而不是模型本身

其次,可以使用字典扩展动态传递要过滤的字段

class ProblemVerificationManager(models.Manager):
    def percentage(self, problem, filter_keyword):
        votes = self.filter(problem=problem)
        total_votes = votes.count()
        yes_votes = votes.filter(**{filter_keyword: True}).count()
        percentage_yes = (yes_votes / total_votes) * 100
        return percentage_yes

class ProblemVerificationModel(CreateUpdateDateModel):
    ...
    objects = ProblemVerificationManager()
现在您可以将其称为
ProblemVerificationModel.objects.percentage(问题“是否正确格式化了问题”)

在Django 2.0+中,您可以使用聚合返回在单个db查询中匹配的完整计数和百分比:

from django.db.models import Count, Q

class ProblemVerificationManager(models.Manager):
    def percentage(self, problem, filter_keyword):
        votes = self.filter(problem=problem).aggregate(
           yes_votes=Count(1, filter=Q(**{filter_keyword: True}),
           total_votes=Count(1)
        )
        percentage_yes = (votes['yes_votes'] / votes['total_votes']) * 100
        return percentage_yes