管理员列表上的manytomany字段

时间:2014-10-01 16:44:06

标签: django many-to-many

根据https://docs.djangoproject.com/en/1.4/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_ordering

不支持ManyToManyField字段,因为这需要为表中的每一行执行单独的SQL语句。如果您想要这样做,请为您的模型提供自定义方法,并将该方法的名称添加到list_display。 (有关list_display中自定义方法的更多信息,请参见下文。)

所以我仍然想要它; D

我有模特:

class Person(models.Model):
  names = models.ManyToManyField('Name')
  birth_date = models.DateField(null=True, blank=True)
  def __unicode__(self):
    return "something"

class Name(models.Model):

  first_name = models.CharField(max_length=50,blank=True)
  last_name = models.CharField(max_length=50, blank=True)
  def __unicode__(self):
    return "%s%s%s" % (self.first_name, " %s " % self.middle_name if self.middle_name else ' ', self.last_name)

我希望列出所有可能性

  • Carlos Ray Norris(10.03.1940)
  • Chuck Norris(10.03.1940)
  • 查克诺里斯(17.01.1978)
  • Michael Sylvester Enzio Stallone(06.07.1946)
  • 西尔维斯特史泰龙(06.07.1946)

如你所见,我们有三个基地。其中两个有不止一个名字,其他两个名字具有相同的名字和姓氏

有两个问题 - 一个是字段名称和订购。

字段名称可以使用Models或ModelAdmin中的方法制作,但我不会显示它,因为主要问题是排序,所以当我们可以进行排序时 - 名称将是附加结果< / p>

这将是最好的,但当然不起作用:

class PersonAdmin(admin.ModelAdmin):
  ordering = ['names__last_name', 'names__last_name', 'birth_date']
  list_display = ('names__first_name', 'names__last_name', 'birth_date')

有什么想法吗?

更新

现在我正在检查查询 - &gt;排序ordering = ['names__last_name', 'names__last_name', 'birth_date']给出了完美的结果,但收到的字段仅限于人模型......

SQL现在:

SELECT "aaa_person"."id", "aaa_person"."birth_date" FROM "aaa_person" LEFT OUTER JOIN "aaa_person_names" ON ("aaa_person"."id" = "aaa_person_names"."person_id") LEFT OUTER JOIN "aaa_name" ON ("aaa_person_names"."name_id" = "aaa_name"."id") ORDER BY "aaa_name"."last_name" ASC, "aaa_name"."first_name" ASC, "aaa_person"."birth_date" ASC

如果我将其更改为:

SELECT * FROM "aaa_person" LEFT OUTER JOIN "aaa_person_names" ON ("aaa_person"."id" = "aaa_person_names"."person_id") LEFT OUTER JOIN "aaa_name" ON ("aaa_person_names"."name_id" = "aaa_name"."id") ORDER BY "aaa_name"."last_name" ASC, "aaa_name"."first_name" ASC, "aaa_person"."birth_date" ASC

我获得了包含名称的完美列表..但是如何设置管理员从aaa_name添加字段?

重要更新

寻找我添加的解决方案:

 def queryset(self, request):
    qs = super(PersonAdmin, self).queryset(request)
    qs = qs.distinct()
    return qs

之前的结果是5行,但没有名字和姓氏。我想只有3行(过滤欺骗)。正如我提到的唯一字段是id和出生日期,SELECT DISTINCT应该给我结果。但结果让我非常惊讶:现在qs.query看起来:

SELECT DISTINCT "backoffice_person"."id", "backoffice_person"."birth_date", "backoffice_name"."last_name", "backoffice_name"."first_name" FROM "backoffice_person" LEFT OUTER JOIN "backoffice_person_names" ON ("backoffice_person"."id" = "backoffice_person_names"."person_id") LEFT OUTER JOIN "backoffice_name" ON ("backoffice_person_names"."name_id" = "backoffice_name"."id") ORDER BY "backoffice_name"."last_name" ASC, "backoffice_name"."first_name" ASC,  "backoffice_person"."birth_date" ASC

这是理想的(DISTINCT对此查询没有影响)。所以现在订购已经完成,现在我需要对象名称。

现在我有:

class PersonAdmin(admin.ModelAdmin):
  def queryset(self, request):
    qs = super(PersonAdmin, self).queryset(request)
    qs = qs.distinct()

    return qs
  def get_all_names(self, instance):
    return instance.names.all()

  ordering = ['names__last_name', 'names__first_name', 'names__middle_name','birth_date']
  list_display = ('get_all_names', 'birth_date')

所以我可以看到所有人的名字,但这不是我想要的......

我需要

def get_first_name(self, *ROW*):
  return *ROW*.first_name

但应该是什么而不是ROW?

1 个答案:

答案 0 :(得分:0)

好吧,经过20个小时的思考和尝试,我终于得到了解决方案。它并不完美,因为我使用extra(),但是就像预期的那样工作。

首先,您必须手动添加列。根据{{​​3}},并知道qs.query我将此行添加到queryset:

def queryset(self, request):
    qs = super(PersonAdmin, self).queryset(request)
    qs = qs.extra(select={'first_name':'aaa_name.first_name', 'last_name':'aaa_name.last_name'})
    return qs

现在一切都按预期进行了。

我必须添加方法get_name:

def get_name(self, instance):
    return "%s %s" % (instance.first_name, instance.last_name)

并更改list_display:

list_display = ('get_name', 'birth_date')

和VOILA !!!

很遗憾,我必须明确使用数据库变量而不是django,但是 - 问题已经解决了。