Вернуть прокси-класс в отношении многие ко многим, Django 2.0

Из другого установленного приложения у меня есть такие модели

class Organization(model.Model):
    name = models.CharField(max_length=255, blank=True)

class Person(model.Model):
    name = models.CharField(max_length=255, blank=True)

class Membership(model.Model):

    organization = models.ForeignKey(
        Organization,
        related_name='memberships',
        # memberships will go away if the org does
        on_delete=models.CASCADE,
        help_text="A link to the Organization in which the Person is a member.")

    person = models.ForeignKey(
        Person,
        related_name='memberships',
        null=True,
        # Membership will just unlink if the person goes away
        on_delete=models.SET_NULL,
        help_text="A link to the Person that is a member of the Organization.")

В моем приложении мне нужно добавить некоторый метод к некоторым моделям. Итак, у меня есть модель, как

class ProxiedOrganization(other_app.models.Organization):
    class Meta:
        proxy = True

    special_attribute = 'foo'


class ProxiedPerson(other_app.models.Person):
    class Meta:
        proxy = True

    def special_method(self):
         print('I do something special')

Когда я получаю членство от организации, они имеют тип other_app.models.Person.

> type(proxied_org_instance.memberships[0].person)
<class 'other_app.models.Person'>

но я бы хотел, чтобы они были моими экземплярами моего прокси-класса

> type(proxied_org_instance.memberships[0].person)
<class 'my_app.models.ProxiedPerson'>

Есть ли хороший способ сделать это? Это то, что я могу сделать с помощью диспетчера запросов? Решение должно работать для Django 2.0.


person fgregg    schedule 25.11.2018    source источник
comment
Это похоже на stackoverflow.com/questions/3891880/, но ни одно из предложенных решений не помогло мне с Django 2.0.   -  person fgregg    schedule 26.11.2018


Ответы (2)


Вам нужно либо поместить ForeignKey в Organization до ProxiedPerson. Например:

class MemberShip(models.Model):
    person = models.ForeignKey(
        ProxyPerson,
        related_name='memberships',
        null=True,
        # Membership will just unlink if the person goes away
        on_delete=models.SET_NULL,
        help_text="A link to the Person that is a member of the Organization.")

или вы можете получить экземпляр доверенного лица:

proxy_person = ProxyPerson.objects.get(pk=proxied_org_instance.memberships[0].person.pk)

Or

proxy_persons = ProxyPerson.objects.filter(
                    pk__in = proxied_org_instance.memberships.all().values_list('person_id')
                )

Согласно документации.

Класс MyPerson работает с той же таблицей базы данных, что и его родительский класс Person. В частности, любые новые экземпляры Person также будут доступны через MyPerson и наоборот.

Означает, что вы можете получить доступ к экземпляру Person через экземпляр ProxyPerson или наоборот.

person ruddra    schedule 25.11.2018
comment
Это полезно, но я бы хотел изменить поведение proxied_org_instance.memberships, чтобы по умолчанию ProxiedPersons не приходилось преобразовывать их в ProxiedPerson после выполнения запроса. - person fgregg; 25.11.2018
comment
Хм... но я хочу использовать данные из таблицы other_app Membership. Возможно, я смогу сделать это, создав неуправляемую модель Membership в my_app. - person fgregg; 25.11.2018

Я адаптировал работу Мэтта Шинкеля по переопределению отношений прокси-модели, для решения, которое будет работать с Django 2.0 и 2.1. Код доступен в виде библиотеки на pypi.

person fgregg    schedule 30.11.2018