#34884: Half bug/half enhancement : inconsistent behavior of get_or_create()
regarding related attributes cache
-------------------------------------+-------------------------------------
Reporter: LLyaudet | Owner: nobody
Type: | Status: new
Uncategorized |
Component: Database | Version: dev
layer (models, ORM) |
Severity: Normal | Keywords: ORM get_or_create
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Hello,
The sample script below demonstrates that get_or_create() avoid
unnecessary DB query for related object given as argument only if created
is True.
It would be nice if the case created is False could be made coherent with
it.
Setting the cache when possible would avoid having to do all over the
code:
{{{
my_object = MyModel.objects.get_or_create(related_object=related_object)
my_object.related_object = related_object
}}}
I can code a patch and provide it in a few days if my idea is accepted :)
Here is the script:
{{{
In [1]: from django.db import connection
In [2]: from django.contrib.contenttypes.models import ContentType
In [3]: from django.contrib.auth.models import Permission
In [4]: content_type = ContentType.objects.get_for_model(Permission)
In [5]: permission, created =
Permission.objects.get_or_create(name="Test", content_type=content_type,
codename="Test")
In [6]: created
Out[6]: True
In [7]: connection.queries
Out[7]:
[{'sql': "SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON
typnamespace = ns.oid WHERE typname = 'hstore'",
'time': '0.001'},
{'sql': "SELECT typarray FROM pg_type WHERE typname = 'citext'",
'time': '0.000'},
{'sql': 'SELECT "django_content_type"."id",
"django_content_type"."app_label", "django_content_type"."model" FROM
"django_content_type" WHERE ("django_content_type"."app_label" = \'auth\'
AND "django_content_type"."model" = \'permission\')',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'},
{'sql': 'INSERT INTO "auth_permission" ("name", "content_type_id",
"codename") VALUES (\'Test\', 2, \'Test\') RETURNING
"auth_permission"."id"',
'time': '0.001'}]
In [8]: permission.content_type
Out[8]: <ContentType: permission>
In [9]: connection.queries
Out[9]:
[{'sql': "SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON
typnamespace = ns.oid WHERE typname = 'hstore'",
'time': '0.001'},
{'sql': "SELECT typarray FROM pg_type WHERE typname = 'citext'",
'time': '0.000'},
{'sql': 'SELECT "django_content_type"."id",
"django_content_type"."app_label", "django_content_type"."model" FROM
"django_content_type" WHERE ("django_content_type"."app_label" = \'auth\'
AND "django_content_type"."model" = \'permission\')',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'},
{'sql': 'INSERT INTO "auth_permission" ("name", "content_type_id",
"codename") VALUES (\'Test\', 2, \'Test\') RETURNING
"auth_permission"."id"',
'time': '0.001'}]
In [10]: permission, created =
Permission.objects.get_or_create(name="Test", content_type=content_type,
codename="Test")
In [11]: created
Out[11]: False
In [12]: connection.queries
Out[12]:
[{'sql': "SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON
typnamespace = ns.oid WHERE typname = 'hstore'",
'time': '0.001'},
{'sql': "SELECT typarray FROM pg_type WHERE typname = 'citext'",
'time': '0.000'},
{'sql': 'SELECT "django_content_type"."id",
"django_content_type"."app_label", "django_content_type"."model" FROM
"django_content_type" WHERE ("django_content_type"."app_label" = \'auth\'
AND "django_content_type"."model" = \'permission\')',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'},
{'sql': 'INSERT INTO "auth_permission" ("name", "content_type_id",
"codename") VALUES (\'Test\', 2, \'Test\') RETURNING
"auth_permission"."id"',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'}]
In [13]: permission.content_type
Out[13]: <ContentType: permission>
In [14]: connection.queries
Out[14]:
[{'sql': "SELECT t.oid, typarray FROM pg_type t JOIN pg_namespace ns ON
typnamespace = ns.oid WHERE typname = 'hstore'",
'time': '0.001'},
{'sql': "SELECT typarray FROM pg_type WHERE typname = 'citext'",
'time': '0.000'},
{'sql': 'SELECT "django_content_type"."id",
"django_content_type"."app_label", "django_content_type"."model" FROM
"django_content_type" WHERE ("django_content_type"."app_label" = \'auth\'
AND "django_content_type"."model" = \'permission\')',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'},
{'sql': 'INSERT INTO "auth_permission" ("name", "content_type_id",
"codename") VALUES (\'Test\', 2, \'Test\') RETURNING
"auth_permission"."id"',
'time': '0.001'},
{'sql': 'SELECT "auth_permission"."id", "auth_permission"."name",
"auth_permission"."content_type_id", "auth_permission"."codename" FROM
"auth_permission" WHERE ("auth_permission"."codename" = \'Test\' AND
"auth_permission"."content_type_id" = 2 AND "auth_permission"."name" =
\'Test\')',
'time': '0.001'},
{'sql': 'SELECT "django_content_type"."id",
"django_content_type"."app_label", "django_content_type"."model" FROM
"django_content_type" WHERE "django_content_type"."id" = 2',
'time': '0.001'}]
}}}
Best regards,
Laurent Lyaudet
--
Ticket URL: <https://code.djangoproject.com/ticket/34884>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/0107018ae206436b-f6748db4-fd20-40b5-ac6c-a564c6d97d8f-000000%40eu-central-1.amazonses.com.