Django ManyToMany 创建和级联删除

问题描述 投票:0回答:1

Django ManyToMany 创建和级联删除

这里是 Django 新手。我查看了几个线程,但没有找到任何相关内容,所以我希望你能帮助我解决这个问题。

我正在研究涉及医生和患者的多对多模型,也就是说,两者之间可以有多种关系。我有以下模型定义:

class Patient(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    email = models.EmailField(unique=True)
    (other fields definitions)

class Doctor(models.Model):
    first_name = models.CharField(max_length=255)
    last_name = models.CharField(max_length=255)
    email = models.EmailField(unique=True)
    (other fields definitions)
…
    patients = models.ManyToManyField(Patient)

医生是主要用户,应该能够可视化所有相关患者(没问题)。不过,当添加新患者时,我想知道如何在 app_doctor_ Patients 连接表中创建关系。我已阅读有关相关对象参考的文档(https://docs.djangoproject.com/en/4.2/ref/models/relations/#django.db.models.fields.lated.RelatedManager),但我确实不知道应用这些功能的最佳方式是什么。首先,我设想了以下内容:

def add_new_patient(request, doctor_id=None, curp=None):
    doctor = Doctor.objects.get(id=doctor_id)
    try:
        patient = Patient.objects.get(curp=curp)
        # Associates Patient 'patient' with Doctor 'doctor'.
        doctor.patients.add(patient)
    except Patient.DoesNotExist:
        # Creates a new patient object, saves it and puts it in the related object set. Returns the newly created object
        patient = d.patients.create(
            first_name="John", first_last_name="McCain")

  • 我明白
    create()
    是我应该调用的函数,而不是
    save()
    函数。这是正确的吗?
  • 这是否应该包含在我的代码中的views.py下,或者这是对
    save
    函数的覆盖?

关于删除,我希望在删除相关患者的同时保留医生。仅应删除关系。为此,我想到使用以下内容:

p = Patient.objects.get(id=345)
d = Doctor.objects.get(id=1)
p.doctors_set.remove(d)  # Disassociates Doctor d from Patient p.
  • 我应该使用
    clear()
    而不是
    remove()
    吗?有什么区别?

对于相反的操作,当删除医生时,除了删除app_doctor_患者表中的所有相关记录之外,仅当该患者只剩下一个关系时(当前医生被删除),我还需要删除所有相关的患者。我正在阅读有关 m2m_changed 信号的信息(https://docs.djangoproject.com/en/4.2/ref/signals/#django.db.models.signals.m2m_changed),但我不明白如何应用它。我有以下部分代码

@receiver(pre_delete, sender=Doctor)
def pre_delete_story(sender, instance, **kwargs):
    for patient in instance.patients.all():
        if patient.doctors.count() == 1:
            # instance is the only Doctor attending this Patient, so delete it
            patient.delete()

这些在哪里定义?我错过了什么?

我们将非常感谢您的帮助。

django many-to-many cascading-deletes
1个回答
0
投票

要向医生添加新患者,您可以使用

add
方法,正如您已正确完成的那样。
create
方法用于创建一个新的相关对象(在本例中为新患者),并将其与医生关联。

在创建新患者后在代码中将其添加到医生的患者中:

def add_new_patient(request, doctor_id=None, curp=None):
    doctor = Doctor.objects.get(id=doctor_id)
    try:
        patient = Patient.objects.get(curp=curp)
        # Associates Patient 'patient' with Doctor 'doctor'.
        doctor.patients.add(patient)
    except Patient.DoesNotExist:
        # Creates a new patient object, saves it and puts it in the related object set. Returns the newly created object
        patient = d.patients.create(
            first_name="John", first_last_name="McCain")
        doctor.patients.add(patient)

关于删除,如果您想删除医生和患者之间的关系而不删除患者本身,您应该使用

remove
方法,该方法仅删除两个实体之间的关系,另一方面,如果您使用
 clear
方法将消除医生和所有患者之间的所有关系,这可能不是您想要的行为。

对于删除医生,您可以使用

pre_delete
信号来检查该患者是否只有一名与其相关的医生。如果是这样,那么您可以像在代码中所做的那样删除患者,在 django 信号中,当发生某些操作时,信号允许某些发送者通知一组接收者。它们为解耦应用程序提供了一种在应用程序中其他地方发生某些事件时收到通知的方法。

在调用模型的

pre_delete
方法之前发送
delete()
信号。它允许您在删除对象之前执行某些操作或检查。当您需要在从数据库中删除对象之前执行一些操作或清理时,这非常有用。

在您的用例中,您正在使用

pre_delete
信号,您想要检查与该医生关联的任何患者在删除
Doctor
实例之前其关系中是否只有一名医生(如果您想要删除这些患者)好吧。

为此,您需要导入必要的模块:

from django.db.models.signals import pre_delete
from django.dispatch import receiver

使用

pre_delete
装饰器定义
@receiver
信号,该装饰器将函数与信号连接起来:

@receiver(pre_delete, sender=Doctor)
def pre_delete_story(sender, instance, **kwargs):
    # yor logic for pre_deletaion actions goes here

该函数应该接受某些参数:

sender
,这是发送信号
instance
的模型类,在本例中,是
Doctor
模型,这是即将删除的模型的实例。

希望这对您有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.