Al obtener miembros basados en la Unidad, solo quiero obtener los que están realmente en esa unidad a partir de ahora .

Tengo un modelo que se ve así:

class Member(models.Model):
    name = models.CharField(max_length=256)
    unit = models.ManyToManyField(Unit, through='Membership')

class Membership(models.Model):
    member = models.ForeignKey(Member)
    unit = models.ForeignKey(Unit)
    start = models.DateField(default=date.today)
    stop = models.DateField(blank=True, null=True)

class Unit(models.Model):
    name = models.CharField(max_length=256)

Como puede ver, los miembros pueden tener una membresía "falsa" en la unidad, eso es solo historia y no debe considerarse en las búsquedas y listados del administrador. Sin embargo, deberían mostrarse en la página de cambio para un solo objeto.

El administrador se ve así:

class MembershipInline(admin.TabularInline):
    model = Membership
    extra = 1

class MemberAdmin(admin.ModelAdmin):
    list_filter = ('unit',)
    inlines = [MembershipInline,]

Entonces, ¿cómo puedo (si es posible de esta manera), cuando filtre en la unidad, solo obtenga aquellas unidades cuyo membership__stop__isnull=True?

Intenté Managers, puedo hacer que funcionen en el modelo en el administrador en sí, pero no en el filtrado / búsquedas. También hay un método def queryset(self) que se puede anular, pero no puedo entender cómo usarlo para solucionar mi problema.

Editar , cómo se usa esto: un miembro solo tiene una membresía en una unidad, sin embargo, podrían ser miembros de antes, pero terminan (con stop). Por lo tanto, solo quiero filtrar (y mostrar, en la vista de lista) aquellos miembros que tienen una membresía abierta (por ejemplo, que ahora son miembros de esa unidad).

¿Alguna idea?

1
odinho - Velmont 28 sep. 2009 a las 06:03

3 respuestas

La mejor respuesta

Lo arreglé colocando un campo desnormalizado en miembro, con una clave foránea para la unidad activa. Luego, para que funcione y se actualice automáticamente en el administrador, hice la función de guardar especializada para Membresía.

class Member(models.Model):
  name = models.CharField(max_length=256)
  unit = models.ManyToManyField(Unit, through='Membership')
  unit_denorm = models.ForeignKey(Unit)

class Membership(models.Model):
  member = models.ForeignKey(Member)
  unit = models.ForeignKey(Unit)
  start = models.DateField(default=date.today)
  stop = models.DateField(blank=True, null=True)

  def save(self, *args, **kwargs):
    if not self.stop:
      self.member.unit_denorm = self.unit
      self.member.save()
    super(Membership, self).save(*args, **kwargs)

class Unit(models.Model):
  name = models.CharField(max_length=256)

Y con list_filter = ('unit_denorm',) en el administrador, hace exactamente lo que quiero.

¡Excelente! Por supuesto, solo debe haber un campo con stop__isnull=True. No he descubierto cómo hacer esa restricción. pero las personas que usan el sistema saben que no deberían hacer eso de todos modos.

0
odinho - Velmont 5 oct. 2009 a las 00:40

Una forma de lograrlo es mediante la adición de un campo desnormalizado para has_open_ended_membership.

Para hacer esto, simplemente agregue un BooleaneField como ese al Miembro y asegúrese de que sea consistente .

De la documentación de django, esta parece ser la única forma sin escribir código especializado en el objeto ModelAdmin:

Configure list_filter para activar los filtros en la barra lateral derecha de la página de lista de cambios del administrador. Debe ser una lista de nombres de campo, y cada campo especificado debe ser un BooleanField, CharField, DateField, DateTimeField, IntegerField o ForeignKey.

Tengo curiosidad sobre otros enfoques: list_filter ciertamente es limitado.

0
phoku 29 sep. 2009 a las 10:44

Entonces estás tratando de obtener los miembros de una Unidad específica, ¿verdad?

unit = Unit.objects.select_related().get(id=some_id)

Esto sacará la unidad de la base de datos para usted, junto con las Membresías y Usuarios que pertenecen a ella. Puede acceder y filtrar los usuarios por:

for member in unit.membership__set.filter(stop__isnull=True):
    print member.name

¿Espero que esto ayude? Puedo estar equivocado, no he probado esto.

0
Fragsworth 28 sep. 2009 a las 02:44