Python - Установка атрибута для значения метода - самый чистый способ? - PullRequest
3 голосов
/ 10 ноября 2011

Я хочу, чтобы удобный удобный атрибут выполнял следующие действия:

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

В настоящее время я решаю эту проблему с помощью лямбды.В поисках ответа похоже, что, возможно, «правильный» способ решить эту проблему - использовать types.MethodType, но я никак не могу разобраться с этим.Да, я прочитал Раймонд отличное руководство , но я явно что-то упускаю .. Вот мое текущее решение для тех, кто заинтересован ..

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

Прямо сейчас это работает .. Но есть ли лучший способ - я не в восторге от лямбд ?? ?? 1011 *

Ответы [ 2 ]

1 голос
/ 10 ноября 2011

Я не совсем уверен, что правильно понимаю, какова ваша цель, но из того, что я думаю, я понимаю, нет необходимости делать какие-то безумные вещи с дескрипторами, не говоря уже о 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, вы можете создать производный класс, добавив желаемое свойство:

class MyUser(User):
    @property
    def company(self):
        return UserProfile.objects.get_or_create(user=self)[0].get_company())
0 голосов
/ 10 ноября 2011

Опираясь на ответ @ SvenMarnach, вы все равно можете выполнить то же самое без использования лямбды. Хотя вам все равно придется обезьяна-патч:

def _get_user_company(user):
    return UserProfile.objects.get_or_create(user=user)[0].get_company()
User.company = property(_get_user_company)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...