Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在django admin中获取列表显示以显示';许多';多对一关系的结束_Python_Django_Python 3.x_Django Admin - Fatal编程技术网

Python 在django admin中获取列表显示以显示';许多';多对一关系的结束

Python 在django admin中获取列表显示以显示';许多';多对一关系的结束,python,django,python-3.x,django-admin,Python,Django,Python 3.x,Django Admin,我想使用列表显示所有宠物主人(客户),并为每个主人显示一个逗号分隔的所有宠物(患者)列表 外键位于患者表中,因此主人可以有许多宠物,但宠物只能有一个主人 我有以下工作要做,但想知道这是否是一个可接受的方法 from .models import Client, Patient class ClientAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'mobile', 'patients')

我想使用列表显示所有宠物主人(客户),并为每个主人显示一个逗号分隔的所有宠物(患者)列表

外键位于患者表中,因此主人可以有许多宠物,但宠物只能有一个主人

我有以下工作要做,但想知道这是否是一个可接受的方法

from .models import Client, Patient

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'patients')

    def patients(self,obj):
        p = Patient.objects.filter(client_id=obj.pk)
        return list(p)
这就是它看起来的样子:

谢谢你的指导

更新: 到目前为止,我的情况如下:

以下是我迄今为止所做的工作

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'getpatients')
    def getpatients(self, request):
        c = Client.objects.get(pk=1)
        p = c.patient_fk.all()
        return p
这是以下文档:

当然,上面的示例将客户机对象的数量“修复”为一个(pk=1),因此我不确定如何获得所有客户机的结果

@请不要归属-我已经尝试了你的代码,非常感谢。我几乎可以肯定我做错了什么,因为我得到了一个错误。但是你知道FK现在有

 related_name = 'patient_fk'
这就解释了为什么我不使用patient_set(因为FOO_set被覆盖)

这就是我所拥有的:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'getpatients')

    def get_queryset(self, request):
        qs = super(ClientAdmin, self).get_queryset(request)
        return qs.prefetch_related('patient_fk') 

    def getpatients(self, obj):
        return self.patient_fk.all()
我得到的错误是“'ClientAdmin'对象没有属性'patient_fk'”,并且与上面代码的最后一行相关

有什么想法吗

谢谢

编辑

我试过Brian的代码:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'getpatients')

    def getpatients(self, obj):
        p = obj.patient_pk.all()
        return list(p)
…并且我收到错误
“Client”对象没有属性“patient\u fk”

如果我运行我的原始代码,它仍然可以正常工作:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'getpatients')

    def getpatients(self, obj):
        p = Patient.objects.filter(client_id=obj.pk)
        return list(p)
以下是我的课程供参考:

class Client(TimeStampedModel):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    ....

class Patient(TimeStampedModel):
    client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='patient_fk')
    name = models.CharField(max_length=30)
    ....
如果有效:+1:

但是,很少注意:它将为每个客户机执行一个查询,因此如果您在admin上显示100个客户机,django将执行100个查询

您可以通过在admin上更改主queryset()并使用

应该是这样的:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'patients')

    def get_queryset(self, request):
        qs = super(ClientAdmin, self).get_queryset(request)
        return qs.prefetch_related('patients')  # do read the doc, maybe 'patients' is not the correct lookup for you

    def patients(self,obj):
        return self.patients_set.all()  # since you have prefetched the patients I think it wont hit the database, to be tested
# get one client
client = Client.objects.last()
# get all the client's patient
patients = client.patient_set.all()
希望这有帮助

注: 您可以使用获取与客户相关的所有患者,例如:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'patients')

    def get_queryset(self, request):
        qs = super(ClientAdmin, self).get_queryset(request)
        return qs.prefetch_related('patients')  # do read the doc, maybe 'patients' is not the correct lookup for you

    def patients(self,obj):
        return self.patients_set.all()  # since you have prefetched the patients I think it wont hit the database, to be tested
# get one client
client = Client.objects.last()
# get all the client's patient
patients = client.patient_set.all()
最后一行类似于:

patients = Patient.objects.get(client=client)
最后,您可以覆盖
患者集
名称并使其更漂亮,请阅读

我还没有测试过它,如果能有一个反馈,看看这是否能防止

这是假设您在ForeignKey中设置了
related\u name='patients'

编辑:修正错误 EDIT2:将反向名称更改为相关名称,并添加了“.all()”

现在可以使用:

class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'get_patients')

    def get_queryset(self, obj):
        qs = super(ClientAdmin, self).get_queryset(obj)
        return qs.prefetch_related('patient_fk')

    def get_patients(self, obj):
        return list(obj.patient_fk.all())
此页面只需要6个查询即可显示

…与我的原始代码(如下)相比,我的原始代码运行一个单独的查询来检索每个客户端的患者(每页100个客户端)

以下是我对其工作方式和原因的理解(请随意指出任何错误):

每个模型都有一个管理器,其默认名称为对象,允许我们访问数据库记录。为了从一个模型中提取所有记录,我们使用了
SomeModel.objects.all()
,它在引擎盖下只是Manager类的get\u QuerySet方法返回的QuerySet

因此,如果我们需要调整从模型返回的内容,即QuerySet,那么我们需要覆盖获取它的方法,即get\u QuerySet。我们的新方法与要重写的方法同名:

 def get_queryset(self, obj):
现在,上述方法不知道如何访问模式数据。它不包含任何代码。为了访问数据,我们需要调用“real”get_queryset方法(我们正在覆盖的方法),以便我们能够实际获取数据,调整它(添加一些额外的患者信息),然后返回它

要访问“原始”get_queryset方法并获取queryset对象(包含所有模型数据,没有患者),我们使用
super()

super()
允许我们访问父类上的方法

例如:

在本例中,它允许我们获取ClientAdmin的
get\u queryset()
方法

def get_queryset(self, obj):
    qs = super(ClientAdmin, self).get_queryset(obj)
qs
将模型中的所有数据保存在QuerySet对象中

要“添加”位于一对多关系末尾的所有患者对象(一个客户端可以有多个患者),我们使用
prefetch\u related()

这将对每个客户端执行查找,并通过遵循“Patient_fk”外键返回任何Patient对象。这是由Python(而不是SQL)在后台执行的,因此最终结果是一个新的查询集——由单个数据库查找生成——包含我们需要的所有数据,这些数据不仅列出主模型中的所有对象,还包括来自其他模型的相关对象

那么,如果我们不重写
Manager.get\u queryset()
方法,会发生什么呢?那么,我们只得到特定表(客户)中的数据,没有关于患者的信息(…和100个额外的数据库点击):


我希望这能帮助其他人。我解释中的任何错误都会让我知道,我会更正。

谢谢,不过我还是有点困惑,请耐心听我说:)你能描述一下我将如何使用queryset和prefetch_related()吗?我的理解是,从客户端对象中,我能够对一对多关系进行“反向”查找,即每个给定客户端对象的所有相关患者字段。就目前情况而言,我已经尝试了几十种组合,但仍然没有完全理解,所以如果能朝着正确的方向轻推,我将不胜感激。谢谢。我猜你的意思是我确实设置的相关名称。我仍在努力理解客户端类如何能够“查看”各种Patient
name
值,而无需实例化Patient对象。我想这就是为什么我需要
related\u name
prefetch\u related
的原因,但就我的一生而言,我并没有让反向查找工作。是的,我是指related\u name,修复了我的答案,而且,我忘了添加对all()方法的调用,我现在已经添加了这个方法。我已经用我的结果编辑了我的帖子,仍然在客户端对象上缺少“patient_pk”属性。。。任何我
return qs.prefetch_related('patient_fk')'
class ClientAdmin(admin.ModelAdmin):
    list_display = ('first_name', 'last_name', 'mobile', 'get_patients')
    #do not override Manager.get_queryset()
    #def get_queryset(self, obj):
    #    qs = super(ClientAdmin, self).get_queryset(obj)
    #    return qs.prefetch_related('patient_fk')

def get_patients(self, obj):
    return list(obj.patient_fk.all())
    #forces extra per-client query by following patient_fk