1

Intro: I have 2 Django Rest Framework models Patient and Embryo There is only 1 user who is the superuser. All the patients belong to the superuser. A patient can have many ebryo's but each embryo can have only 1 patient.

What I want to do: I am trying to send the patient an email when either the patient model or embryo model is created or updated. Below is my code what am I doing wrong

Below is my views.py

 def send_email_confirmation(instance):
    patient = Patient.objects.get(id=instance)
    embryo = Embryo.objects.filter(patient=patient)
    try:
        '''Sending the Order to the patient'''
        subject = "Gemonic Prediction Create or Update record"
        to = ['{}'.format(patient.email)]
        from_email = "no_reply@genomicprediction.com/"
        order_information = {
            'patient': patient,
            'embryo': embryo
        }
        message = get_template('email/email.html').render(order_information)
        msg = EmailMessage(subject, message, to=to, from_email=from_email)
        msg.content_subtype = 'html'
        msg.send()
    except IOError as e:
        return e


class PatientsApiView(viewsets.ModelViewSet):
    """Handles Creating, reading and updating Patients"""

    serializer_class = serializers.PatientsSerializer
    queryset = Patient.objects.all()
    authentication_classes = (TokenAuthentication,)
    filter_backends = (filters.SearchFilter,)
    permission_classes = (IsAuthenticated,)
    search_fields = ("first_name", "last_name", "phone", "email",)

    def perform_create(self, serializer):
        serializer.save(user=self.request.user)
        instance = serializer.save()
        try:
            send_email_confirmation(created=instance)
            print('An email has been sent to the customer.')
        except IOError as e:
            return e

    def perform_update(self, serializer):
        instance = serializer.save()
        try:
            send_email_confirmation(modified=instance)
            print('An email has been sent to the customer.')
        except IOError as e:
            return e


class EmbroApiView(viewsets.ModelViewSet):
    """Handles Creating, reading and updating Patients"""

    serializer_class = serializers.EmbryoSerializer
    queryset = Embryo.objects.all()
    authentication_classes = (TokenAuthentication,)
    filter_backends = (filters.SearchFilter,)
    permission_classes = (IsAuthenticated,)
    search_fields = ("code_name", "karyotype", "sex", "down_syndrome",)

    def perform_create(self, serializer):
        serializer.save(pk=self.kwargs.get("pk"))
        instance = serializer.save()
        try:
            send_email_confirmation(created=instance)
            print('An email has been sent to the customer.')
        except IOError as e:
            return e

    def perform_update(self, serializer):
        instance = serializer.save()
        try:
            send_email_confirmation(modified=instance)
            print('An email has been sent to the customer.')
        except IOError as e:
            return e

My models are below just in case

class Patient(models.Model):
    """Patients model which has all the patients information"""
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    first_name = models.CharField(max_length=25)
    last_name = models.CharField(max_length=35)
    phone = models.CharField(max_length=18)
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    @property
    def full_name(self):
        return "%s %s" % (self.first_name, self.last_name)

    def __str__(self):
        return "%s %s" % (self.full_name, self.email)


class Embryo(models.Model):
    """A ForeignKey model to the patient"""
    patient = models.ForeignKey(Patient, related_name="embryos", on_delete=models.CASCADE)
    code_name = models.CharField(max_length=100)
    karyotype = models.CharField(max_length=100)
    down_syndrome = models.BooleanField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    GENDER_CHOICES = (
        ("M", "Male"),
        ("F", "Female"),

    )
    sex = models.CharField(blank=True, null=True, max_length=1, choices=GENDER_CHOICES)
Samir Tendulkar
  • 1,151
  • 3
  • 19
  • 47

2 Answers2

1

You may use django's signal.

Signal are emitted upon model changes. Here is the official documentation https://docs.djangoproject.com/en/2.1/topics/signals/

binarym
  • 357
  • 2
  • 10
  • Can you tell me what I am doing wrong in the code above – Samir Tendulkar Nov 05 '18 at 16:40
  • 1
    There's a good example on the documentation: 1/ Hook on your model pre-save or post-save signal https://docs.djangoproject.com/en/2.1/topics/signals/#connecting-to-signals-sent-by-specific-senders and 2/ Send an email (https://docs.djangoproject.com/en/2.1/topics/email/). – binarym Nov 05 '18 at 16:42
0

In the class EmbroApiView the methods perform_update and perform_create are calling send_email_confirmation with an instance of Patient (the result of calling save on the serializer). And inside the function send_email_confirmation the first line is

patient = Patient.objects.get(id=instance)

So you are using an instance of Patient as the id, this is the first error I see.

The second is similar but with the class EmbroApiView in this case, you are calling the method send_email_confirmation with an instance of Embryo.

grouchoboy
  • 1,016
  • 8
  • 12
  • do you think it should be `instance_id` – Samir Tendulkar Nov 05 '18 at 16:54
  • Think that you are passing to the method an instance of `Patient` so you do not need to do any queryset to get the `Patient`. In the second case you can call the method with `send_email_confirmation(created=instance.patient)` – grouchoboy Nov 05 '18 at 16:59