3

I'm getting an unexpected result using icontains in my get_or_create call.

Take the following example:

>>>team_name = "Bears"
>>>Team.objects.get(name__icontains=team_name) # returns DoesNotExist as expected
>>>team, created = Team.objects.get_or_create(name__icontains=team_name)
>>>print(created) # Prints True as expected
>>>print(team.name) # Prints an empty string!

Why does this create a team with a blank name rather than "Bears"? The reason I'm using get_or_create here is that if a subsequent user posts something like "BearS" I want to get the correct team, not create a duplicate team with incorrect capitalization.

3 Answers 3

7

Another option besides wencakisa's answer is to include the defaults parameter in get_or_create, because Django strips lookups containing the __ separator. See answers to this question.

The code would be:

Team.objects.get_or_create(
    name__icontains=team_name,
    defaults = {
        "name": team_name
    }
)
Sign up to request clarification or add additional context in comments.

Comments

5

I think here you should split the get() and create() functionalities instead of using get_or_create(), because the __icontains lookup works for get() only.

Try doing something like this:

>>> team_name = 'Bears'

>>> teams = Team.objects.filter(name__icontains=team_name)
# This will filter the teams with this name

>>> team = teams.first() if teams.exists() else Team.objects.create(name=team_name)
# Now your team is the first element of your previous query (it returns a QuerySet with single element) if it exists
# Otherwise, you create a new Team.

1 Comment

good point...didn't realize that get_or_create didn't allow icontains. I also ended up using iexact instead of icontains to avoid mistakes in the case that there's a different team called the "Golden Bears", for instance.
0

The right way to do it is using Django's function get_or_create(). But instead of "icontains", you should use "iexact" (), unless you want an exact match, in wich case you should use just "exact":

Team.objects.get_or_create(
    name__iexact=team_name,
    defaults = {
        "name": team_name
    }
)

Outside "defaults" you should put your search terms. If the objects doesn't exist, you should write your creation terms inside 'defaults'

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.