Skip to content

Instantly share code, notes, and snippets.

@jamesturk
Created December 5, 2018 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesturk/a50f3952f2acd004f32ab7e0e523af17 to your computer and use it in GitHub Desktop.
Save jamesturk/a50f3952f2acd004f32ab7e0e523af17 to your computer and use it in GitHub Desktop.
bulk loading from postgres
import csv
from io import StringIO
from django.db import connection
def postgres_bulk_copy(objects, ModelCls=None,
table_name=None,
fields=None, not_null=None, null=None,
include_id=False,
):
_fields = []
_not_null = []
_null = []
# if a model was passed in, use it to get defaults
if ModelCls:
for f in ModelCls._meta.get_fields():
if (not f.auto_created and
not (f.is_relation and f.many_to_many) and
f.column):
_fields.append(f.column)
if f.null:
_null.append(f.column)
else:
_not_null.append(f.column)
# prefer passed in overrides if they exist
table_name = table_name or ModelCls._meta.db_table
fields = fields or _fields
not_null = not_null or _not_null
null = null or _null
if include_id:
fields.append('id')
objects = [
{k: getattr(o, k) for k in fields} for o in objects
]
tmp = StringIO()
w = csv.DictWriter(tmp, fieldnames=fields)
w.writeheader()
w.writerows(objects)
# flush and seek to start
tmp.flush()
tmp.seek(0)
cursor = connection.cursor()
sql = "COPY {}({}) FROM STDIN WITH CSV HEADER".format(table_name,
', '.join(fields)
)
if null:
sql += " FORCE NULL {}".format(', '.join(null))
if not_null:
sql += " FORCE NOT NULL {}".format(', '.join(not_null))
cursor.copy_expert(sql, tmp)
# need this commit here so lookups immediately after will work
cursor.connection.commit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment