Opened 11 months ago

Last modified 3 months ago

#22728 assigned Bug

get_or_create with field lookups cause empty values

Reported by: Xudonax Owned by: coldmind
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: get_or_create
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

First of, I'm actually using 1.7b4, but there seems to be no version for that (yet)...

When trying to be smart and using a case insensitive filter for get_or_create, it doesn't actually fill in the value, because you passed it in with a field lookup instead of just the field name. An example explains this better:

from django.db import models

class Tag(models.Model):
    name = models.CharField(unique=True)
    slug = models.SlugField(unique=True)

tags = ['django', 'python', 'web', 'Django', 'html5', 'Python'] # Just a list of tags to make this work

for tag in tags:
    obj, created = Tag.objects.get_or_create(name__iexact=tag, defaults={'slug': tag)
    print("Tag {0} created? {1}".format(obj.name, created)

This will give a IntegrityError while going through the list, complaining that there already is a tag with an empty value for name.

IntegrityError: duplicate key value violates unique constraint "blog_tag_name_key"
DETAIL:  Key (name)=() already exists.

A work-around is to also specify the name field in the defaults, but I was actually expecting the ORM to be "smart" enough to not require this. There is no documentation describing it should happen either way. Is this a documentation issue or a code issue?

Change History (8)

comment:1 Changed 11 months ago by valberg

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Don't mind me, totally misread the issue :)

Last edited 11 months ago by valberg (previous) (diff)

comment:2 Changed 11 months ago by aaugustin

Your expectations are a bit higher than what the ORM is actually able to do ;-)

This is really a feature request. Can you submit it to the django-developers mailing-list?

comment:3 Changed 11 months ago by Xudonax

I'd swear I used something like this in a previous version... But I guess you know Django better than I do :)
I'll post it to the django-developers mailing-list, thanks.

comment:4 Changed 10 months ago by bmispelon

  • Triage Stage changed from Unreviewed to Accepted

For reference, the mailing list discussion is here: https://groups.google.com/forum/#!topic/django-developers/EbLRpYB_1WI

As someone else mentionned on the mailing list, I'm not sure either if we can do something that works in the general case.

The fact that this "works" currently and that it silently drops the field that has a lookup seems quite dangerous (and not intentional).
For this reason, I'd be in favor of throwing an error if a user attempts to use lookups in a get_or_create call (similar to what happens if you try and use one in create()).

I'll mark this as accepted on this basis.

Thanks.

comment:5 Changed 4 months ago by timgraham

  • Version changed from 1.7-beta-2 to master

comment:6 Changed 4 months ago by coldmind

  • Owner changed from nobody to coldmind
  • Status changed from new to assigned

comment:8 Changed 3 months ago by berkerpeksag

  • Patch needs improvement set
Note: See TracTickets for help on using tickets.
Back to Top