【问题标题】:How to show relationship in Django Admin如何在 Django Admin 中显示关系
【发布时间】:2019-09-16 01:17:30
【问题描述】:

我正在使用 Django 2.1,我很难弄清楚如何在 Admin 上显示关系。 我有两个示范医院和单位,第三个是考试。他们是这样设置的,医院可以有多个单元,一个单元属于一个医院。并且考试模型具有考试名称和医院名称等考试属性。

class Hospital(models.Model):

    name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

class Unit(models.Model):

    unit_name = models.CharField(max_length=200)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    parent_company = models.ForeignKey(
        Hospital, related_name='unit_parent', on_delete=models.CASCADE, verbose_name="Hospital")


class Exam(models.Model):

    unit_name = models.ForeignKey(
        Hospital, related_name='hospital_pk', on_delete=models.CASCADE)
    exam_name = models.CharField(max_length=255, blank=True,
                                 null=True, verbose_name="Exam's name")
    date = models.DateField()
    time = models.TimeField()

    def __str__(self):
        return self.exam_name


class CustomExamAdmin(admin.ModelAdmin):

    model = Exam
    list_display = ('exam_name', 'time', 'alert',
                    'document', 'notes', 'report', 'patients_name', 'unit_name')
    list_filter = ('exam_name', 'time')
    list_select_related = ('unit_name',)
    fieldsets = (
        ("Hospital's Name:", {
            'fields': ('unit_name',)}),
        ('Types of Exams:', {
            'fields': ('exam_name', 'modality', 'model_used')}),
        ("Patient's name:", {
            'fields': ('patients_name',)}),
     )

因此,在管理员的考试页面中,我可以选择医院名称,但我无法选择属于医院的单位。我需要选择医院以及所属的单位。 我是否应该在考试中添加另一个外键,如下所示: unit_selected = models.ForeignKey( 单位,related_name='unit_pk', on_delete=models.CASCADE)

例如:医院:布鲁克代尔大学医院 单位:市区单位

我得到了什么: enter image description here

【问题讨论】:

  • 你看到了什么?可以打印屏幕吗?我猜你可以做类似unit_name__name 的事情,但如果没有看到就很难说
  • 感谢您与我们联系,我刚刚添加了屏幕截图。我想要的是选择医院和单位白色试图创建一个考试。

标签: django django-models django-admin django-admin-filters


【解决方案1】:

要在Admin 中选择Unit,您需要先将其添加到Exam 模型中。您有一个名为unit_name 的字段,但您已将其定义为Hospital 模型的外键,而不是Unit 模型。如果你有一个unit_name 字段,你真的不需要一个单独的hospital 字段,因为你可以很容易地从unit_name.parent_company 得到它。所以你可以这样做:

class Exam(models.Model):

    unit_name = models.ForeignKey(
        Unit, related_name='exams', on_delete=models.CASCADE)
    exam_name = models.CharField(max_length=255, blank=True,
                                 null=True, verbose_name="Exam's name")
    date = models.DateField()
    time = models.TimeField()

    def __str__(self):
        return self.exam_name

对于管理员,我认为最简单的方法是在管理员中选择医院名称时将医院名称作为单元名称的一部分,而不是单独选择医院和单位,例如Brookdale University Hospital|Downtown Unit。这样你只需要一个下拉字段。你可以这样做:

from django import forms


class UnitChoiceField(forms.ModelChoiceField):
     def label_from_instance(self, obj):
         return "{}|{}".format(obj.parent_company.name, obj.unit_name)


class CustomExamAdmin(admin.ModelAdmin):

    model = Exam
    list_display = ('exam_name', 'time', 'alert',
                    'document', 'notes', 'report', 'patients_name', 'get_hospital', 'unit_name')
    list_filter = ('exam_name', 'time')
    list_select_related = ('unit_name__parent_company',)
    fieldsets = (
        ("Hospital's Name:", {
            'fields': ('unit_name',)}),
        ('Types of Exams:', {
            'fields': ('exam_name', 'modality', 'model_used')}),
        ("Patient's name:", {
            'fields': ('patients_name',)}),
     )

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'unit_name':
            return UnitChoiceField(
                queryset=Unit.objects.all().select_related('parent_company').order_by(
                'parent_company.name', 'unit_name'))
        return super().formfield_for_foreignkey(db_field, request, **kwargs)

    def get_hospital(self, obj):
    #  required to add hospital name to list_display
        return obj.unit_name.parent_company.name           
    get_hospital.short_description = 'Hospital'

另一个注意事项:ForeignKeyField 中的 related_name 是从外部模型返回到您正在定义的模型的关系。所以在Unit 模型中

parent_company = models.ForeignKey(
    Hospital, related_name='unit_parent', on_delete=models.CASCADE, verbose_name="Hospital")

应该是

 parent_company = models.ForeignKey(
    Hospital, related_name='units', on_delete=models.CASCADE, verbose_name="Hospital")

然后在Hospital 模型中,您可以将单元列表称为units

【讨论】:

  • 感谢您与我们联系,嗯,我有两个应用程序,第一个名为 Hospitals,其中包含医院和单元模型,第二个名为 Exam。因此,当我在 Exams Admin.py 中测试您的代码时,我收到错误消息:“'Exam' 对象没有属性 'parent_company'。我应该创建一个包含医院、单位和考试的大型 models.py 吗?
  • 我已经编辑了UnitChoiceField 类。立即尝试。
  • 很抱歉现在才回复您。我有一段时间无法上网。这很奇怪,现在我得到“'str' object has no attribute 'parent_company'”。这真的很令人沮丧,我现在一直在安静地练习 Django,但我发现自己陷入了困境。谢谢常青!!
  • 抱歉,所有错误,乔安妮。在进行上一次编辑之前,我应该更仔细地查看。不幸的是,我无法在发布之前测试代码,因为我没有整个项目。我已经编辑了UnitChoiceField 类(一开始是正确的)和get_hospital 方法(这是原始错误所在的位置)。请再试一次...
  • 天啊!太感谢了!你已经提供了更多帮助。直到现在我才知道如何正确使用 formfield_for_foreignkey 方法。再次感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-18
  • 2019-01-21
  • 1970-01-01
  • 2017-07-10
相关资源
最近更新 更多