简体   繁体   English

如何在Django Admin中显示关系

[英]How to show relationship in Django Admin

I am using Django 2.1 and I am getting a hard time trying to figure out how to show relationships on Admin. 我正在使用Django 2.1,我正在努力弄清楚如何在Admin上显示关系。 I have two Models Hospital and Units and the third one is Exams. 我有两个医院和单位模型,第三个是考试。 They are setting up like this, Hospital can have many Units and one Units belongs to one Hospital. 他们这样设置,医院可以有多个单位,一个单位属于一个医院。 And the Exam model has the exams attributes like exams name and hospital`s name. 考试模型有考试名称和医院名称等考试属性。

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',)}),
     )

So, in Exams page on Admin I am able to select the Hospital name, however I am not able to select the Unit the belongs to the hospital. 因此,在管理员的考试页面中,我可以选择医院名称,但是我无法选择属于医院的单位。 I need to select the hospital as well as the unit that belongs to it. 我需要选择医院以及属于它的单位。 Should I add another foreignkey to Exams, like this: unit_selected = models.ForeignKey( Unit, related_name='unit_pk', on_delete=models.CASCADE) 我应该向Exams添加另一个外键,如下所示:unit_selected = models.ForeignKey(Unit,related_name ='unit_pk',on_delete = models.CASCADE)

For instance: Hospital: Brookdale University Hospital Unit: Downtown Unit 例如:医院:布鲁克戴尔大学医院单位:市中心单位

What I get: enter image description here 我得到的: 在这里输入图像描述

In order to select the Unit in the Admin , you need to first add it to the Exam model. 要在Admin选择Unit ,您需要先将其添加到Exam模型中。 You have a field called unit_name , but you have defined it as a foreign key to the Hospital model, not the Unit model. 您有一个名为unit_name的字段,但您已将其定义为Hospital模型的外键,而不是Unit模型。 If you have a unit_name field, you don't really need a separate hospital field, since you can easily get it from unit_name.parent_company . 如果您有unit_name字段,则实际上并不需要单独的hospital字段,因为您可以从unit_name.parent_company轻松获取它。 So you can do this: 所以你可以这样做:

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

For the admin, rather than selecting the hospital and unit separately, the simplest approach, in my opinion, is to include the hospital name as part of the unit name when you select it in the admin, like Brookdale University Hospital|Downtown Unit . 对于管理员而言,不是单独选择医院和单位,我认为最简单的方法是在管理员中选择医院名称作为单位名称的一部分,如Brookdale University Hospital|Downtown Unit That way you only need one dropdown field. 这样你只需要一个下拉字段。 You can do that like this: 你可以这样做:

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'

One other note: the related_name in a ForeignKeyField is the relation from the foreign model back to the model you are defining. 另一个注意:在related_nameForeignKeyField是国外模型回您所定义的模型之间的关系。 So in the Unit model 所以在Unit模型中

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

should be 应该

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

Then from the Hospital model you can refer to the list of units as units . 然后从Hospital模型中,您可以将单位列表称为units

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM