Skip to content

Commit 160f8b0

Browse files
committed
add exclude_fields argument
1 parent fa74336 commit 160f8b0

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

bulk_sync/__init__.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
from collections import OrderedDict
22
import logging
33
from django.db import transaction
4+
from django.core.exceptions import FieldDoesNotExist
45

56
logger = logging.getLogger(__name__)
67

78

8-
def bulk_sync(new_models, key_fields, filters, batch_size=None, fields=None, skip_creates=False, skip_updates=False, skip_deletes=False):
9+
def bulk_sync(
10+
new_models, key_fields, filters,
11+
batch_size=None, fields=None, exclude_fields=None,
12+
skip_creates=False, skip_updates=False, skip_deletes=False
13+
):
914
""" Combine bulk create, update, and delete. Make the DB match a set of in-memory objects.
1015
1116
`new_models`: Django ORM objects that are the desired state. They may or may not have `id` set.
@@ -14,7 +19,9 @@ def bulk_sync(new_models, key_fields, filters, batch_size=None, fields=None, ski
1419
`filters`: Q() filters specifying the subset of the database to work in. Use `None` or `[]` if you want to sync against the entire table.
1520
`batch_size`: passes through to Django `bulk_create.batch_size` and `bulk_update.batch_size`, and controls
1621
how many objects are created/updated per SQL query.
17-
`fields`: (optional) list of fields to update. If not set, will sync all fields that are editable and not auto-created.
22+
`fields`: (optional) list of fields to update. If not set, will sync all fields that are editable and not
23+
auto-created.
24+
`exclude_fields`: (optional) list of fields to exclude from updates.
1825
`skip_creates`: If truthy, will not perform any object creations needed to fully sync. Defaults to not skip.
1926
`skip_updates`: If truthy, will not perform any object updates needed to fully sync. Defaults to not skip.
2027
`skip_deletes`: If truthy, will not perform any object deletions needed to fully sync. Defaults to not skip.
@@ -27,6 +34,19 @@ def bulk_sync(new_models, key_fields, filters, batch_size=None, fields=None, ski
2734
for field in db_class._meta.fields
2835
if not field.primary_key and not field.auto_created and field.editable]
2936

37+
if exclude_fields is not None:
38+
model_fields = set(field.name for field in db_class._meta.fields)
39+
fields_to_update = set(fields)
40+
fields_to_exclude = set(exclude_fields)
41+
42+
# Check that we're not attempting to exclude non-existant fields
43+
if not fields_to_exclude <= model_fields:
44+
raise FieldDoesNotExist(
45+
f'model "{db_class.__name__}" has no field(s) {fields_to_exclude - model_fields}'
46+
)
47+
48+
fields = list(fields_to_update - fields_to_exclude)
49+
3050
with transaction.atomic():
3151
objs = db_class.objects.all()
3252
if filters:

0 commit comments

Comments
 (0)