tengo 3 modelos
class Person(models.Model): name = models.CharField(max_length=128) class Company(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField (Person, through = 'Membership', related_name = 'companies') class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) company = models.ForeignKey(Company, on_delete=models.CASCADE) is_admin = models.BooleanField()
Luego puedo llamar a person.companies.all()
para obtener la lista de empresas asociadas con la persona.
¿Cómo creo un administrador para tener la lista de empresas asociadas a una persona, pero cuya persona es administrador (is_admin = True)?
Puedes filtrar con:
person.companies.filter( membership__is_admin=True )
Esto filtrará la Membership
de la tabla de unión, de modo que solo recuperará las Company
para las cuales la Membership
tiene is_admin
establecido en True
.
Otra opción es recuperar esto con:
Company.objects.filter( membership__is_admin=True, members=person )
Puede adjuntar esto al modelo Person
con:
class Person(models.Model): name = models.CharField(max_length=128) @property def admin_companies(self): return self.companies.filter( membership__is_admin=True )
Puede crear un administrador como el siguiente:
managers.py
:
from django.db import models class AdminCompaniesManager(models.Manager): def get_queryset(self): return super().get_queryset().companies.filter(membership__is_admin=True)
y luego en su modelo de Person
(recuérdele al administrador de objects
):
class Person(models.Model): name = models.CharField(max_length=128) objects = models.Manager() administered_companies = AdminCompaniesManager()
Ahora puede llamar fácilmente a lo siguiente (por ejemplo, en sus vistas):
my_person.administered_companies.all()
PD: una opción muy eficiente (por ejemplo, si está en una vista y necesita la lista de identificaciones de empresas de una persona determinada) es consultar el modelo de membresía directamente, de modo que pueda optimizar la consulta para la recuperación de datos de la base de datos evitando las uniones:
Membership.objects.filter(is_admin=True, person=person).values_list('company_id')