【问题标题】:Django Many to Many Inline - how to show fields referenced by through model?Django 多对多内联 - 如何显示通过模型引用的字段?
【发布时间】:2014-03-01 00:31:37
【问题描述】:

我正在尝试在 django Admin 中自定义和多对多内联,但我无法显示底层模型的字段。

这是一个简化的示例。也许你能告诉我如何引用它们?

这是我的模型:

class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...

class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)

class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)

和我的管理员:

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['clown__name','clown__edit_link']


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)

但是我得到了这个错误:

Unknown field(s) (clown__name) specified for WorkedAt

(我在 Django 1.6 上)

更新: 为什么这也行不通。 (通过模型添加了计算字段。)

class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...

class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)

class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)
    @property
    def edit_link(self):
        return self.clown.edit_link()

和我的管理员:

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['edit_link']


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)

【问题讨论】:

  • fields 必须是来自 WorkedAt 模型的数据库字段。它不能是底层模型的字段。在这种情况下,您可以在 Circus 模型上将内联为 Clown,并完全取消 WorkedAd
  • 好的,看看我的更新。如果我在直通模型中添加了一个方法,为什么它甚至不会出现?
  • 你能发布一个堆栈跟踪吗?
  • 同时定义 fieldsreadonly_fields 应该可以完成这项工作。

标签: django django-forms django-admin django-1.6


【解决方案1】:

试试这个。希望能解决你的问题

class ClownInline(admin.TabularInline):
    model = WorkedAt
    fields = ['clown_name', 'clown_edit_link']
    readonly_fields = ['clown_name', 'clown_edit_link']

    def clown_name(self, instance):
        return instance.clown.name
    clown_name.short_description = 'clow name'

    def clown_edit_link(self, instance):
        url = reverse("admin:%s_%s_change" % (instance.clown._meta.app_label, instance.clown._meta.module_name), args=(instance.clown.pk,))
        return '<a href="%s">%s</a>' % (url, instance.clown.name)
    clown_edit_link.allow_tags = True


class CircusAdmin(admin.ModelAdmin):
    inlines = [
        ClownInline,
    ]
    exclude = ('clowns',)

【讨论】:

  • 非常感谢您的尝试!由于某种原因,它仍然无法正常工作。我什至让你的方法 ClownInline.clown_name 返回一个简单的字符串 'test' 以排除任何问题,但它仍然找不到字段 clown_name。
【解决方案2】:

我不知道是否还有人需要这个,因为这个问题已经有 4 年了,但这解决了我在Django 2.0.3 中的问题:

# models.py
class Clown(models.Model):
    name = models.CharField(max_length=255)
    def edit_link(self):
        return ...


class Circus(models.Model):
    clowns = models.ManyToManyField(Clown, blank=True, through='WorkedAt')
    name = models.CharField(max_length=255)


class WorkedAt(models.Model):
    clown = models.ForeignKey(Clown)
    circus = models.ForeignKey(Circus)


# admin.py
class WorkedAtInline(admin.TabularInline):
    model = WorkedAt
    extra = 1


class WorkedAtAdmin(admin.ModelAdmin):
    inlines = (WorkedAtInline,)


admin.site.register(Clown, WorkedAtAdmin)

希望这可以帮助任何偶然发现此问题并调查此答案的人。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    • 2012-11-15
    • 1970-01-01
    • 2019-08-13
    • 1970-01-01
    • 2023-03-22
    相关资源
    最近更新 更多