Opened 3 months ago

Closed 3 months ago

#35694 closed Cleanup/optimization (invalid)

FK inconsistency beween `get_or_create` and any other orm function

Reported by: KIC Owned by:
Component: Database layer (models, ORM) Version: 5.1
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by KIC)

While any orm filter, get, ... accepts a pk or instance get_or_create does not. For consistency get_or_create should also be able to handle instances and pk's interchangeably.

models.py:

from django.db import models


class A(models.Model):
    foo = models.CharField(max_length=100)


class B(models.Model):
    a = models.ForeignKey(A, on_delete=models.CASCADE)
    bar = models.CharField(max_length=100)

tests.py

from testing.utils import TestCase
from zfoo import models


class TestSomething(TestCase):
    def test_lala(self):
        a = models.A.objects.create(foo="foo")
        models.B.objects.create(a=a, bar="bar")

        self.assertEqual(models.B.objects.get(a=a), models.B.objects.get(a=a.pk))
        self.assertEqual(
            models.B.objects.filter(a=a).first(),
            models.B.objects.filter(a=a.pk).first(),
        )

        models.B.objects.get_or_create(dict(bar="does not exist"), bar="baz", a=a)
        models.B.objects.get_or_create(dict(bar="does not exist"), bar="baz", a=a.pk)  # FAILS

Change History (2)

comment:1 by KIC, 3 months ago

Description: modified (diff)

comment:2 by Sarah Boyce, 3 months ago

Resolution: invalid
Status: newclosed

This is consistent with create - models.B.objects.create(dict(bar="does not exist"), bar="baz", a=a.pk) would also raise a ValueError
You can use the _id suffix models.B.objects.get_or_create(dict(bar="does not exist"), bar="baz", a_id=a.pk) (same for create)

Note: See TracTickets for help on using tickets.
Back to Top