繁体   English   中英

如何在两个 Django 类之间共享 Python 方法?

[英]How to share Python method between two Django classes?

我的 Django models.py 文件中有两个类:

class ProfileManager(models.Manager):
    def create_profile(self, user, member):
        # Set default age to 100 years old when profile is created.
        years_ago100 = datetime.datetime.now() - datetime.timedelta(days=101 * 365)
        age = calculate_age(years_ago100)       # <- Used here
        profile = self.create(user=user, person_dob=years_ago100, person_age=age)
        return

class Profile(models.Model):
    person_dob = models.DateField()
    person_age = models.IntegerField()

    objects = ProfileManager()

    def save(self, *args, **kwargs):
      # Update to real age when user edits profile for the first time.
      self.person_age = calculate_age(self.person_dob)    # <- Used here too
      super(Profile, self).save(*args, **kwargs)

每个类都使用这个calculate_age 方法:

def calculate_age(born):
    today = datetime.date.today()
    return (today.year - born.year - ((today.month, today.day) < (born.month, born.day)))

如何使两个类都可以访问此方法? 一种简单的方法是像这样使方法全局化,但这似乎是一种笨拙的方法:

def calculate_age(born):
  ...

class ProfileManager(models.Manager):
  ...

class Profile(models.Model):
  ...

此外,如果我想在此特定模型模块之外访问该方法,这将不起作用。 使用 Django 时有没有标准的方法来做到这一点?

我不知道你为什么认为它笨拙。 当它检测到一个方法不访问类成员并因此可以转换为静态方法或函数时,它经常被完成并且 PyCharm 甚至使它变得方便。

最重要的是,Python 导入非常方便。 是的,您可以从模块外部访问模块函数,语法与访问类相同:通过点引用访问成员。

模块:

# myapp/utils.py

def calculate_age(born):
    today = datetime.date.today()
    return (today.year - born.year - ((today.month, today.day) < (born.month, born.day)))
#otherapp/models.py
from myapp import utils

class UserProfile(models.Model):
    def clean(self):
        if utils.get_age(self.birthday) < 13:
            raise ValidationError("no minors below 13 allowed")

您可以将函数 calculate_age 保存到不同的文件中,然后将其导入到 models.py 文件的顶部。 这将允许访问内部的所有类/方法/函数。

可以尝试类似多重继承吗? 不太确定这会比你所做的事情的全局函数更好

class Profile(models.Model):
    person_dob = models.DateField()
    person_age = models.IntegerField()

    objects = ProfileManager()

    def save(self, *args, **kwargs):
        # Update to real age when user edits profile for the first time.
        self.person_age = self.calculate_age(self.person_dob)    # <- Used here too
        super(Profile, self).save(*args, **kwargs)

    def calculate_age(born):
        today = datetime.date.today()
        return (today.year - born.year - ((today.month, today.day) < (born.month, born.day)))


class ProfileManager(models.Manager, Profile):
    def create_profile(self, user, member):
        # Set default age to 100 years old when profile is created.
        years_ago100 = datetime.datetime.now() - datetime.timedelta(days=101 * 365)
        age = self.calculate_age(years_ago100)       # <- Used here
        profile = self.create(user=user, person_dob=years_ago100, person_age=age)
        return

如果您不喜欢从 Profile 类继承整个 models.Model,您可以创建一个它们都可以继承的共享类。

class Profile(models.Model, helpers):
    person_dob = models.DateField()
    person_age = models.IntegerField()

    objects = ProfileManager()

    def save(self, *args, **kwargs):
        # Update to real age when user edits profile for the first time.
        self.person_age = self.calculate_age(self.person_dob)    # <- Used here too
        super(Profile, self).save(*args, **kwargs)


class ProfileManager(models.Manager, helpers):
    def create_profile(self, user, member):
        # Set default age to 100 years old when profile is created.
        years_ago100 = datetime.datetime.now() - datetime.timedelta(days=101 * 365)
        age = self.calculate_age(years_ago100)       # <- Used here
        profile = self.create(user=user, person_dob=years_ago100, person_age=age)
        return


class helpers():
    def calculate_age(self, born):
        today = datetime.date.today()
        return (today.year - born.year - ((today.month, today.day) < (born.month, born.day)))

    def other_shared_method(self):
        pass

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM