Home > other >  Many to Many relationship between different types of users - Django
Many to Many relationship between different types of users - Django

Time:04-24

I am building a toy project consisting in a healthcare information system. I want to have two types of users: patients and doctors. A patient could have multiple doctors and a doctor could have multiple patients. What is the best way to represent this relationship?

Currently I have something similar to this:

class User(AbstractUser):
    def serialize(self):
        return {
            "id": self.id,
            "username": self.username,
        }

class Doctor(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
    patients = models.ManyToManyField(Patient)

class Patient(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))
    doctors = models.ManyToManyField(Doctor)

However I'm pretty sure this doesn't work. What is the right way to represent this type of relationship using django models? Thanks!

CodePudding user response:

Problem Statement

Using ManyToManyRelationship (M2M) will lead to many problems in the long run, starting with serializing patients for a doctor, and doctors for a patient effectively.

A separate database table is created for every M2M relation in a model with the foreign keys of the two related models. This table is also inaccessible in Django for further operations.

So there would have been two databases defining a particular doctor's relation with that of a particular patient. Maintaining the two relations could lead to discrepancies in the long run. Also, fetching the nformation would't be a uniform task.

This will also create a problem if you try to create/update information, as handling the nested data will be complex.

The Solution

The best solution is to follow the RESTful API paradigm.

We will drop all the M2M relations in class Doctor and Patient, and then create a new model in models.py to define the doctor-patient relationship:

class Doctor(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))

class Patient(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET(get_sentinel_user))

class DoctorPatient(models.Model):
    doctor = models.ForeignKey(Doctor)
    patient = models.ForeignKey(Patient)

Now, whenever

  • a new patient is assigned to a doctor, or
  • a new doctor is assigned to a patient

Then, a new patient-doctor relationship can be established by creating an instance of the class DoctorPatient.

what did we achieve

The DoctorPatient model establishes an accessible model for the database tables which were being created by M2M relation. It also handles this relation in one place.

Now, two separate Django ViewSets can be created if you wish to create two separate APIs to lookup via IDs for the given relations:

  • One, for a doctor having all the patients
  • Other, for a patient having all the doctors.

Assuming there is a django serializer for the model DoctorPatient as DoctorPatientSerializer, the viewsets can be defined in api.py as:

from rest_framework import viewsets

class DoctorWithPatientsViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.DoctorPatientSerializer
    filter_backends = (DjangoFilterBackend,)
    filterset_fields = "__all__"
    lookup_field = 'doctor'

    def get_queryset(self):
        queryset = models.DoctorPatient.objects.all()
        return DoctorPatient.objects.filter(id__in=queryset.values_list('doctor_id',flat=True))

class PatientWithDoctorsViewSet(viewsets.ModelViewSet):
    serializer_class = serializers.DoctorPatientSerializer
    filter_backends = (DjangoFilterBackend,)
    filterset_fields = "__all__"
    lookup_field = 'patient'

    def get_queryset(self):
        queryset = models.DoctorPatient.objects.all()
        return DoctorPatient.objects.filter(id__in=queryset.values_list('patient_id',flat=True))

CodePudding user response:

skip the many2many at the doctors. You can get the doctor of a patient through the patient. Via .add you can set a doctor for a patient

  • Related