2

I upgraded from Django 1.11 to Django 2.0 and my tests started failing. I have 7 TestCase classes and all use the setUpTestData provided by Django. When I run them all together one of them fails to set up because of an psycopg2.IntegrityError: duplicate key value violates unique constraint "doctors_doctor_pkey".

When I run one of those TestCase classes alone it works fine. It seems like they're influencing each other in some way, but it's strange that it would fail after upgrading to Django 2.0. I've also noticed it's not at the create() it's at the save().

In the setup for the dashboards app I have some creation data:

cls.d1 = doctor_models.Doctor.objects.create(email="johndoe@example.com", name="John Doe",
                                                 specialization=cls.s1, premium=True,
                                                 premium_price=4310, consultation_price=341)

...
cls.b1 = doctor_models.DoctorBooking.objects.create(clinic=cls.c1, doctor=cls.d1,
                                                            status=2, premium_booking=True,
                                                            patient_name="example",
                                                            patient_phone_number="+9747721234",
                                                            confirmed_date=datetime.strptime(
                                                                "16 Jun 2017 14:22:26:000 +0300",
                                                                receive_format),
                                                            handled_on=datetime.strptime(
                                                                "17 Jun 2017 14:22:26:000 +0300",
                                                                receive_format))

The second line from above would call it's save() function that would call save() on cls.d1

def save(self, *args, **kwargs):
    if self.doctor.premium:
        self.premium_booking = True
    else:
        self.premium_booking = False
    super(DoctorBooking, self).save(*args, **kwargs)
    self.doctor.save()  # <- here it raises an IntegrityError

This is the simplest code I could extract, but this happens all over for different classes.

To reiterate this gives me the following.

psycopg2.IntegrityError: duplicate key value violates unique constraint "doctors_doctor_pkey"
DETAIL:  Key (id)=(7) already exists.

I'm not even sure why this is happening. When you create an object shouldn't psycopg2 take care of auto-incrementing the pk? From what I can gather the database doesn't have any issues, when I add a breakpoint before the .save() and check the Database a doctor with the same data and pk is already in the database. So I'm guessing it's assuming that these two objects are different... but I'm calling create then save NOT create twice.

EDIT: Solved in the comments :D

Ysrninja
  • 129
  • 1
  • 2
  • 9

1 Answers1

1

Most probably, the referred doctor is already saved. Check for that before trying to re-save.

Something like this:

def save(self, *args, **kwargs):
    if self.doctor.premium:
        self.premium_booking = True
    else:
        self.premium_booking = False

    super(DoctorBooking, self).save(*args, **kwargs)

    if not self.doctor.pk:
        self.doctor.save()
Umair Mohammad
  • 4,489
  • 2
  • 20
  • 34
  • Thanks for the reply! But why does this matter? I still need to save the doctor. In Django 1.11 this was working fine. Do you have any other ideas? – Ysrninja Dec 31 '18 at 14:30
  • 1
    Before you can add reference to any object (here, doctor) in another object (here, DoctorBooking) you must have that object (here, doctor) in database. So before you call save of DoctorBooking, doctor must already be in database, which you're already doing cls.d1= ... , so why are you again trying to save doctor ? – Umair Mohammad Dec 31 '18 at 14:32
  • Because the ranking of the doctor changes whenever a new booking happens, the same thing happens when I use signals. When I try to use `update_fields` it breaks because it can't find it in the database.... so I don't know – Ysrninja Dec 31 '18 at 15:04
  • 1
    So I guess you need to update the rank of doctor, where are you doing that ? – Umair Mohammad Jan 01 '19 at 18:06
  • I already figured out the problem, it's completely irrelevant to this. It was something else. Basically Django was trying to create a new object in `save` because it couldn't find an object with a similar PK. This is because Doctor has it's own manager with `get_queryset` that returns only a set of the doctors based on something, and it wasn't returning the doctors with a similar PK so it would clash. One last thing, I'll upvote you for helping me, can you please upvote me to get over the 15 rep limit. – Ysrninja Jan 02 '19 at 08:14