# django-pgbulk
`django-pgbulk` provides functions for doing native Postgres bulk upserts (i.e. [UPDATE ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html)), bulk updates, and [COPY FROM](https://www.postgresql.org/docs/current/sql-copy.html).
Bulk upserts can distinguish between updated/created rows and ignore unchanged updates.
Bulk updates are true bulk updates, unlike Django's [bulk_update](https://docs.djangoproject.com/en/4.2/ref/models/querysets/#bulk-update) which can still suffer from *O(N)* queries and can create poor locking scenarios.
Bulk copies can significantly speed-up bulk inserts, sometimes by an order of magnitude over Django's `bulk_create`.
## Quick Start
### Examples
#### Update or insert rows
```python
import pgbulk
pgbulk.upsert(
MyModel,
[
MyModel(int_field=1, some_attr="some_val1"),
MyModel(int_field=2, some_attr="some_val2"),
],
# These are the fields that identify the uniqueness constraint.
["int_field"],
# These are the fields that will be updated if the row already
# exists. If not provided, all fields will be updated
["some_attr"]
)
```
#### Bulk update rows
```python
import pgbulk
pgbulk.update(
MyModel,
[
MyModel(id=1, some_attr='some_val1'),
MyModel(id=2, some_attr='some_val2')
],
# These are the fields that will be updated. If not provided,
# all fields will be updated
['some_attr']
)
```
#### Copy rows into a table
```python
import pgbulk
pgbulk.copy(
MyModel,
# Insert these rows using COPY FROM
[
MyModel(id=1, some_attr='some_val1'),
MyModel(id=2, some_attr='some_val2')
],
)
```
### Advanced Features
Here are some advanced features at a glance:
- `pgbulk.upsert` can categorize which rows were inserted or updated.
- `pgbulk.upsert` and `pgbulk.update` can ignore updating unchanged fields.
- `pgbulk.upsert` and `pgbulk.update` can use expressions in updates.
## Documentation
[View the django-pgbulk docs here](https://django-pgbulk.readthedocs.io/) for more examples.
## Compatibility
`django-pgbulk` is compatible with Python 3.9 - 3.13, Django 4.2 - 5.1, Psycopg 2 - 3, and Postgres 13 - 17.
## Installation
Install `django-pgbulk` with:
pip3 install django-pgbulk
## Contributing Guide
For information on setting up django-pgbulk for development and contributing changes, view [CONTRIBUTING.md](CONTRIBUTING.md).
## Creators
- [Wes Kendall](https://github.com/wesleykendall)
## Other Contributors
- @max-muoto
- @dalberto
Raw data
{
"_id": null,
"home_page": "https://github.com/AmbitionEng/django-pgbulk",
"name": "django-pgbulk",
"maintainer": null,
"docs_url": null,
"requires_python": "<4,>=3.9.0",
"maintainer_email": null,
"keywords": null,
"author": "Wes Kendall",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/58/d8/376423d0a27a9e3bca05464bf43ab8b079b475bdcaefed8f50498beb6487/django_pgbulk-3.2.4.tar.gz",
"platform": null,
"description": "# django-pgbulk\n\n`django-pgbulk` provides functions for doing native Postgres bulk upserts (i.e. [UPDATE ON CONFLICT](https://www.postgresql.org/docs/current/sql-insert.html)), bulk updates, and [COPY FROM](https://www.postgresql.org/docs/current/sql-copy.html).\n\nBulk upserts can distinguish between updated/created rows and ignore unchanged updates.\n\nBulk updates are true bulk updates, unlike Django's [bulk_update](https://docs.djangoproject.com/en/4.2/ref/models/querysets/#bulk-update) which can still suffer from *O(N)* queries and can create poor locking scenarios.\n\nBulk copies can significantly speed-up bulk inserts, sometimes by an order of magnitude over Django's `bulk_create`.\n\n## Quick Start\n\n### Examples\n\n#### Update or insert rows\n\n```python\nimport pgbulk\n\npgbulk.upsert(\n MyModel,\n [\n MyModel(int_field=1, some_attr=\"some_val1\"),\n MyModel(int_field=2, some_attr=\"some_val2\"),\n ],\n # These are the fields that identify the uniqueness constraint.\n [\"int_field\"],\n # These are the fields that will be updated if the row already\n # exists. If not provided, all fields will be updated\n [\"some_attr\"]\n)\n```\n\n#### Bulk update rows\n\n```python\nimport pgbulk\n\npgbulk.update(\n MyModel,\n [\n MyModel(id=1, some_attr='some_val1'),\n MyModel(id=2, some_attr='some_val2')\n ],\n # These are the fields that will be updated. If not provided,\n # all fields will be updated\n ['some_attr']\n)\n```\n\n#### Copy rows into a table\n\n```python\nimport pgbulk\n\npgbulk.copy(\n MyModel,\n # Insert these rows using COPY FROM\n [\n MyModel(id=1, some_attr='some_val1'),\n MyModel(id=2, some_attr='some_val2')\n ],\n)\n```\n\n### Advanced Features\n\nHere are some advanced features at a glance:\n\n- `pgbulk.upsert` can categorize which rows were inserted or updated.\n- `pgbulk.upsert` and `pgbulk.update` can ignore updating unchanged fields.\n- `pgbulk.upsert` and `pgbulk.update` can use expressions in updates.\n\n## Documentation\n\n[View the django-pgbulk docs here](https://django-pgbulk.readthedocs.io/) for more examples.\n\n## Compatibility\n\n`django-pgbulk` is compatible with Python 3.9 - 3.13, Django 4.2 - 5.1, Psycopg 2 - 3, and Postgres 13 - 17.\n\n## Installation\n\nInstall `django-pgbulk` with:\n\n pip3 install django-pgbulk\n\n## Contributing Guide\n\nFor information on setting up django-pgbulk for development and contributing changes, view [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Creators\n\n- [Wes Kendall](https://github.com/wesleykendall)\n\n## Other Contributors\n\n- @max-muoto\n- @dalberto\n",
"bugtrack_url": null,
"license": "BSD-3-Clause",
"summary": "Native Postgres update, upsert, and copy operations.",
"version": "3.2.4",
"project_urls": {
"Documentation": "https://django-pgbulk.readthedocs.io",
"Homepage": "https://github.com/AmbitionEng/django-pgbulk",
"Repository": "https://github.com/AmbitionEng/django-pgbulk"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "dce60d0063b012172841a027276bf6eaa09f0979dc7c013494b1911a09fac506",
"md5": "89e6944dcb10759de78f6fa4005e4a33",
"sha256": "b291da67c2e03cb98d27780389cf4bd6d479e9b381be100fc5b80a1803fda6a1"
},
"downloads": -1,
"filename": "django_pgbulk-3.2.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "89e6944dcb10759de78f6fa4005e4a33",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4,>=3.9.0",
"size": 11295,
"upload_time": "2025-09-02T16:19:06",
"upload_time_iso_8601": "2025-09-02T16:19:06.591956Z",
"url": "https://files.pythonhosted.org/packages/dc/e6/0d0063b012172841a027276bf6eaa09f0979dc7c013494b1911a09fac506/django_pgbulk-3.2.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "58d8376423d0a27a9e3bca05464bf43ab8b079b475bdcaefed8f50498beb6487",
"md5": "7de29400c0e296c56b08fbb0d9c874d5",
"sha256": "4b1163c3612d679f880e9265c7674ddfb5612f07316bd8ef8de747673a836cec"
},
"downloads": -1,
"filename": "django_pgbulk-3.2.4.tar.gz",
"has_sig": false,
"md5_digest": "7de29400c0e296c56b08fbb0d9c874d5",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4,>=3.9.0",
"size": 11944,
"upload_time": "2025-09-02T16:19:07",
"upload_time_iso_8601": "2025-09-02T16:19:07.416341Z",
"url": "https://files.pythonhosted.org/packages/58/d8/376423d0a27a9e3bca05464bf43ab8b079b475bdcaefed8f50498beb6487/django_pgbulk-3.2.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-09-02 16:19:07",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "AmbitionEng",
"github_project": "django-pgbulk",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"circle": true,
"tox": true,
"lcname": "django-pgbulk"
}