Skip to content

Instantly share code, notes, and snippets.

@jangeador
Last active December 6, 2023 04:57
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jangeador/e7221fc3b5ebeeac9a08 to your computer and use it in GitHub Desktop.
Save jangeador/e7221fc3b5ebeeac9a08 to your computer and use it in GitHub Desktop.
A function that creates unique objects based on models
def get_or_create(session, model, **kwargs):
'''
Creates an object or returns the object if exists
credit to Kevin @ StackOverflow
from: http://stackoverflow.com/questions/2546207/does-sqlalchemy-have-an-equivalent-of-djangos-get-or-create
'''
instance = session.query(model).filter_by(**kwargs).first()
if instance:
return instance
else:
instance = model(**kwargs)
session.add(instance)
return instance
# Usage:
# Suppose my model object is :
class Country(Base):
__tablename__ = 'countries'
id = Column(Integer, primary_key=True)
name = Column(String, unique=True)
# To get or create my object I write :
myCountry = get_or_create(session, Country, name=countryName)
@jmberros
Copy link

jmberros commented Dec 1, 2016

I'm wondering if this gist could be slightly simplified to avoid the two return statements:

def get_or_create(session, model, **kwargs):
    '''
    Creates an object or returns the object if exists
    credit to Kevin @ StackOverflow
    from: http://stackoverflow.com/questions/2546207/does-sqlalchemy-have-an-equivalent-of-djangos-get-or-create
    '''
    instance = session.query(model).filter_by(**kwargs).first()

    if not instance:
        instance = model(**kwargs)
        session.add(instance)

    return instance

@kyle-go
Copy link

kyle-go commented Nov 1, 2017

It's not threading safe.

@DwainTR
Copy link

DwainTR commented May 11, 2018

Hello,

I'm having issues with this function when I try to add a dict type to JSON field in database.

I have file called 5.txt. In this file I have a data as:

{
"MESA": {
    "district": 6,
    "town": 161,
    "street": 19,
    "building": 26,
    "section": 0
    }
}

I use the following code to assign it to a variable.

file = open('5.txt', 'r', encoding='utf8')
data = json.loads(file.read())

And the type of "data" is <class ‘dict’>. The output is:

{'MESA': {'district': 6, 'town': 161, 'street': 19, 'building': 26, 'section': 0}}

So I'm trying to write the data variable to my table. This is how I created my table with SQL Alchemy.

class Forms(Base):
        __tablename__ = 'payload'
        id = Column(Integer, primary_key=True)
        city_payload = Column(JSON)

And the code that I try to write it is:

city1 = get_or_create(session, Forms, city_payload=data)

But I get the following error:

psycopg2.ProgrammingError: operator does not exist: json = unknown
LINE 3: WHERE payload.city_payload = '{"MESA": {"district": 6, "to...
                                   ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
.
.
.
sqlalchemy.exc.ProgrammingError: (psycopg2.ProgrammingError) operator does not exist: json = unknown
LINE 3: WHERE payload.city_payload = '{"MESA": {"district": 6, "to...
                                   ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.

But when I try to do it as following everything is ok:

c = Forms()
c.city_payload = data
session.add(c)
session.commit()

By the way my function is almost the same as you did:

def get_or_create(session, model, **kwargs):
    instance = session.query(model).filter_by(**kwargs).first()
    if instance:
        return instance
    else:
        instance = model(**kwargs)
        session.add(instance)
        session.flush()
        return instance

Why do you think I'm having this problem?

Thanks.

@jakubblaha-ids
Copy link

Change

if ...:
    ...
    return ...
else:
    ...
    return ...

to

if ...:
    ...
    return ...

return ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment