2011-11-10 24 views
3

我想要一个漂亮方便的属性做到以下几点:Python - 将属性设置为方法的值 - 最干净的方式?

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()) 

现在这个工程.. 但是,有没有更好的办法 - 我米不是疯狂的lambda?

+0

是lambda导致任何问题?如果没有,你有一个你想要做的工作实施 - 为什么要让事情变得困难? – millimoose

+0

不,它的工作,但我不完全适应他们。我一直用反模式的眼睛看着它们...... – rh0dium

+0

在Python 2.x中要小心'AttributeError,IndexError:'。它只会捕获'AttributeError',并将捕获到的异常分配给'IndexError'。使用'except(AttributeError,IndexError):'代替。 –

回答

1

我不是很确定我正确理解你的目标是什么,但从我的理解来看,似乎没有必要在这里用描述符做任何疯狂的事情,更不用说types.MethodType了。一个简单的财产是好的,如果你不喜欢的拉姆达,您可以用饰有@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类,您可以创建派生类中添加所需的特性:对@ SvenMarnach的回答

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

您无法真正地将方法添加到Django库中的类中。 – millimoose

+0

@Inerdia:'用户'似乎不是Django库中的类。 (如果你不能改变某个类,只需从它派生而不是猴子修补它)。 –

+0

该OP似乎是指Django [Auth模块](https://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User)。子类化不会真的有帮助,因为模块的函数不会返回你的子类。 – millimoose

-1

大厦,你仍然可以完成同样的事情,而不使用lambda。虽然你还必须猴子补丁:

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

嗯..我以为get_or_create返回一个元组.. .. ... https://docs.djangoproject.com/en/dev/ref/models/querysets/#get-or-create – rh0dium

+0

对不起,你是对的。我通常使用'obj,created = MyModel.objects.get_or_create()',所以数组选择器让我想起了'filter'。 –

相关问题