Django ManyToMany创建和级联删除

8aqjt8rx  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(252)

Django ManyToMany创建和级联删除
Django新手在这里。我已经看了几个线程,我没有找到任何相关的,所以我希望你能帮助我在这方面。
我正在研究一个涉及医生和患者的ManyToMany模型,也就是说,两者之间可以有多个关系。我有以下模型定义:

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连接表中创建关系。我已经阅读了有关Related objects参考的文档(https://docs.djangoproject.com/en/4.2/ref/models/relations/#django.db.models.fields.related.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_patients表中的所有相关记录外,我还需要删除所有相关的Patients(仅当该患者只剩下一个关系时)(当前医生被删除)。我正在阅读关于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()


这些在哪里定义?我错过了什么?
你的帮助将不胜感激。
再加上我最初的问题,我目前使用的是基于类的视图(使用rest_framework.views中的API View),上面的代码是初步的。也就是说,我还没有将它包含在我的工作代码中。我现在要显示和保存新患者的代码如下:

class PatientList(APIView):
    def get(self, request):
        doctor_id = 25  # currently hardcoded, eventually to be taken from singed-on user
        doctor = Doctor.objects.get(pk=doctor_id)
        patients = doctor.patients.all()
        serializer = PatientDisplaySerializer(patients, many=True)
        return Response(serializer.data)

    def post(self, request):
        doctor_id = 25  # currently hardcoded, eventually to be taken from singed-on user
        serializer = PatientSaveSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        print(serializer.validated_data)
        return Response(serializer.data)


关于serializer.save()命令,我应该覆盖serializers.py文件中的save()函数,还是应该在哪里包含add_new_patient()函数和代码来构建与医生的关系?
应该在哪里调用remove()函数?我有我想要的功能的大致想法,但我不知道在哪里包括它。再次感谢。

yvfmudvl

yvfmudvl1#

为添加一个新的病人到一个医生你可以使用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


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

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


该函数应该接受某些参数:sender,这是发送信号instance的模型类,在本例中,是Doctor模型,这是将要删除的模型的示例。
我希望这对你有帮助。

相关问题