Django: добавление свойства в модель пользователя после создания модели на основе абстрактного класса
У меня есть нормальная модель и абстрактная модель, например, так:
class TaggedSubject(models.Model):
user = models.ForeignKey(User, null=True, blank=True)
category = models.CharField(max_length=200)
foo = models.CharField(max_length=50)
bar = models.CharField(max_length=50)
# etc
content_type = models.ForeignKey(ContentType)
content_object_pk = models.CharField(max_length=255)
content_object = generic.GenericForeignKey("content_type", "content_object_pk")
def __unicode__(self):
if self.user:
return "%s" % (self.user.get_full_name() or self.user.username)
else:
return self.label
class Taggable(models.Model):
tagged_subjects = generic.GenericRelation(TaggedSubject, content_type_field='content_type', object_id_field='content_object_pk')
@property
def tagged_users(self):
return User.objects.filter(pk__in=self.tagged_subjects.filter(user__isnull=False).values("user"))
class Meta:
abstract = True
Taggable
Класс абстрактной модели затем используется так:
class Photo(Taggable):
image = models.ImageField(upload_to="foo")
# ... etc
Итак, если у нас есть фото-объект:
photo = Photo.objects.all()[0]
Я могу всех пользователей отмеченных на фото с помощью photo.tagged_users.all()
Я хочу добавить обратное отношение к объекту пользователя, чтобы при наличии пользователя:
user = User.objects.filter(pk__in=TaggedSubject.objects.exclude(user__isnull=True).values("user"))[0]
Я могу назвать что-то вроде user.tagged_photo_set.all()
и пусть он вернет все фото объекты.
Я подозреваю, что поскольку TaggedSubject подключается к модели Taggable по общему признаку, его нельзя будет использовать как through
модель с ManyToMany
поле.
Предполагая, что это правда, я полагаю, что эту функцию мне нужно (как-то) добавить в модель User:
def tagged_photo_set(self):
Photo.objects.filter(pk__in=TaggedSubject.objects.filter(user=self, content_type=ContentType.objects.get_for_model(Photo))
Мне интересно, возможно ли настроить его так, чтобы каждый раз, когда новый класс модели создавался на основе Taggable, он создавал версию функции выше и добавлял ее (в идеале как функцию, которая ведет себя как свойство!) Для пользователя,
В качестве альтернативы, если можно каким-либо образом выполнить полевые соединения ManyToMany с родовым отношением (в чем я очень сомневаюсь), это тоже сработает.
Наконец, если есть третий, даже более прохладный вариант, который я не вижу, я, безусловно, открыт для него.
1 ответ
Вы могли бы использовать add_to_class
и class_prepared
сигнал для некоторой постобработки, когда настроены модели, подклассифицирующие ваш базовый класс:
def add_to_user(sender, **kwargs):
def tagged_FOO_set(self):
return sender.objects.filter(pk__in=TaggedSubject.objects.filter(
user=self,
content_type=ContentType.objects.get_for_model(sender)))
if issubclass(sender, MyAbstractClass):
method_name = 'tagged_{model}_set'.format(model=sender.__name__.lower())
User.add_to_class(method_name, property(tagged_FOO_set))
class_prepared.connect(add_to_user)