Python - 将属性设置为方法的值 - 最干净的方法?

时间:2011-11-10 18:08:33

标签: python django

我想要一个很好的方便属性来执行以下操作:

from django.contrib.auth.models import User
user = User.objects.get(id=2)
user.company
<Company: Big Company L.L.C>

我目前正在使用lambda解决这个问题。在寻找答案时,似乎解决这个问题的“正确”方法可能是使用types.MethodType,但我似乎无法理解它。是的,我读过Raymond excellent guide但我显然遗漏了一些东西..这是我目前对那些感兴趣的人的解决方案..

# Defined Elsewhere
class User:
    name = models.CharField(max_length=32)
class Company(models.Model):
    users =  models.ManyToManyField(User, related_name="companies", blank=True, null=True)

# Here is the meat of this..
class UserProfile(models.Model):
    """This defines Users"""
    user = models.OneToOneField(User)

    def get_company(self):
        try:
            companies = self.user.companies.all()[0]
        except (AttributeError, IndexError):
            return None

User.company = property(lambda u: UserProfile.objects.get_or_create(user=u)[0].get_company())

现在这有效.. 但是有更好的方法 - 我对lambdas不是很疯狂吗?

2 个答案:

答案 0 :(得分:1)

我不太确定我是否正确理解你的目标是什么,但从我认为理解的情况来看,似乎没有必要在这里使用描述符做任何疯狂的事情,更不用说types.MethodType了。一个简单的属性很好,如果你不喜欢lambda,你可以使用一个用@property装饰的普通函数:

class User:
    name = models.CharField(max_length=32)
    @property
    def company(self):
        return UserProfile.objects.get_or_create(user=self)[0].get_company())

修改:如果您无法触及User类,则可以创建添加所需属性的派生类:

class MyUser(User):
    @property
    def company(self):
        return UserProfile.objects.get_or_create(user=self)[0].get_company())

答案 1 :(得分:-1)

在@SvenMarnach的答案的基础上,你仍然可以在不使用lambda的情况下完成同样的事情。虽然你还需要猴子补丁:

def _get_user_company(user):
    return UserProfile.objects.get_or_create(user=user)[0].get_company()
User.company = property(_get_user_company)