django-bulk-hooks 0.1.172__tar.gz → 0.1.173__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of django-bulk-hooks might be problematic. Click here for more details.
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/PKG-INFO +1 -1
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/queryset.py +129 -115
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/pyproject.toml +1 -1
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/LICENSE +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/README.md +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/__init__.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/conditions.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/constants.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/context.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/decorators.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/engine.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/enums.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/handler.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/manager.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/models.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/priority.py +0 -0
- {django_bulk_hooks-0.1.172 → django_bulk_hooks-0.1.173}/django_bulk_hooks/registry.py +0 -0
|
@@ -24,9 +24,8 @@ class HookQuerySet(models.QuerySet):
|
|
|
24
24
|
objs = list(self)
|
|
25
25
|
if not objs:
|
|
26
26
|
return 0
|
|
27
|
-
#
|
|
28
|
-
|
|
29
|
-
return len(objs)
|
|
27
|
+
# Call the base QuerySet implementation to avoid recursion
|
|
28
|
+
return super().bulk_delete(objs)
|
|
30
29
|
|
|
31
30
|
@transaction.atomic
|
|
32
31
|
def update(self, **kwargs):
|
|
@@ -34,28 +33,31 @@ class HookQuerySet(models.QuerySet):
|
|
|
34
33
|
if not instances:
|
|
35
34
|
return 0
|
|
36
35
|
|
|
36
|
+
model_cls = self.model
|
|
37
|
+
pks = [obj.pk for obj in instances]
|
|
38
|
+
|
|
39
|
+
# Load originals for hook comparison and ensure they match the order of instances
|
|
40
|
+
# Use the base manager to avoid recursion
|
|
41
|
+
original_map = {obj.pk: obj for obj in model_cls._base_manager.filter(pk__in=pks)}
|
|
42
|
+
originals = [original_map.get(obj.pk) for obj in instances]
|
|
43
|
+
|
|
37
44
|
# Apply field updates to instances
|
|
38
45
|
for obj in instances:
|
|
39
46
|
for field, value in kwargs.items():
|
|
40
47
|
setattr(obj, field, value)
|
|
41
48
|
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
# Run BEFORE_UPDATE hooks
|
|
50
|
+
ctx = HookContext(model_cls)
|
|
51
|
+
engine.run(model_cls, BEFORE_UPDATE, instances, originals, ctx=ctx)
|
|
45
52
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
)
|
|
55
|
-
else:
|
|
56
|
-
# Use bulk_create for new objects
|
|
57
|
-
self.bulk_create([obj])
|
|
58
|
-
return obj
|
|
53
|
+
# Use Django's built-in update logic directly
|
|
54
|
+
# Call the base QuerySet implementation to avoid recursion
|
|
55
|
+
update_count = super().update(**kwargs)
|
|
56
|
+
|
|
57
|
+
# Run AFTER_UPDATE hooks
|
|
58
|
+
engine.run(model_cls, AFTER_UPDATE, instances, originals, ctx=ctx)
|
|
59
|
+
|
|
60
|
+
return update_count
|
|
59
61
|
|
|
60
62
|
@transaction.atomic
|
|
61
63
|
def bulk_create(
|
|
@@ -112,60 +114,86 @@ class HookQuerySet(models.QuerySet):
|
|
|
112
114
|
|
|
113
115
|
# Fire hooks before DB ops
|
|
114
116
|
if not bypass_hooks:
|
|
117
|
+
print(f"DEBUG: Firing BEFORE_CREATE hooks for {model_cls}")
|
|
118
|
+
print(f"DEBUG: Number of objects: {len(objs)}")
|
|
119
|
+
print(f"DEBUG: Object types: {[type(obj) for obj in objs]}")
|
|
120
|
+
print(f"DEBUG: QuerySet type: {type(self)}")
|
|
121
|
+
print(f"DEBUG: Is this HookQuerySet? {isinstance(self, HookQuerySet)}")
|
|
115
122
|
ctx = HookContext(model_cls)
|
|
116
123
|
if not bypass_validation:
|
|
124
|
+
print(f"DEBUG: Running VALIDATE_CREATE hooks")
|
|
117
125
|
engine.run(model_cls, VALIDATE_CREATE, objs, ctx=ctx)
|
|
126
|
+
print(f"DEBUG: Running BEFORE_CREATE hooks")
|
|
118
127
|
engine.run(model_cls, BEFORE_CREATE, objs, ctx=ctx)
|
|
128
|
+
else:
|
|
129
|
+
print(f"DEBUG: Skipping hooks due to bypass_hooks=True for {model_cls}")
|
|
119
130
|
|
|
120
131
|
# For MTI models, we need to handle them specially
|
|
121
132
|
if is_mti:
|
|
122
133
|
# Use our MTI-specific logic
|
|
123
134
|
# Filter out custom parameters that Django's bulk_create doesn't accept
|
|
124
135
|
mti_kwargs = {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
136
|
+
'batch_size': batch_size,
|
|
137
|
+
'ignore_conflicts': ignore_conflicts,
|
|
138
|
+
'update_conflicts': update_conflicts,
|
|
139
|
+
'update_fields': update_fields,
|
|
140
|
+
'unique_fields': unique_fields,
|
|
130
141
|
}
|
|
131
142
|
# Remove custom hook kwargs if present in self.bulk_create signature
|
|
132
143
|
result = self._mti_bulk_create(
|
|
133
144
|
objs,
|
|
134
|
-
**{
|
|
135
|
-
k: v
|
|
136
|
-
for k, v in mti_kwargs.items()
|
|
137
|
-
if k not in ["bypass_hooks", "bypass_validation"]
|
|
138
|
-
},
|
|
145
|
+
**{k: v for k, v in mti_kwargs.items() if k not in ['bypass_hooks', 'bypass_validation']}
|
|
139
146
|
)
|
|
140
147
|
else:
|
|
141
148
|
# For single-table models, use Django's built-in bulk_create
|
|
149
|
+
# but we need to call it on the base manager to avoid recursion
|
|
142
150
|
# Filter out custom parameters that Django's bulk_create doesn't accept
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
151
|
+
|
|
152
|
+
# Use Django's original QuerySet to avoid recursive calls
|
|
153
|
+
from django.db.models import QuerySet
|
|
154
|
+
original_qs = QuerySet(model_cls, using=self.db)
|
|
155
|
+
result = original_qs.bulk_create(
|
|
156
|
+
objs,
|
|
157
|
+
batch_size=batch_size,
|
|
158
|
+
ignore_conflicts=ignore_conflicts,
|
|
159
|
+
update_conflicts=update_conflicts,
|
|
160
|
+
update_fields=update_fields,
|
|
161
|
+
unique_fields=unique_fields,
|
|
162
|
+
)
|
|
153
163
|
|
|
154
164
|
# Fire AFTER_CREATE hooks
|
|
155
165
|
if not bypass_hooks:
|
|
166
|
+
print(f"DEBUG: Firing AFTER_CREATE hooks for {model_cls}")
|
|
167
|
+
print(f"DEBUG: Number of objects: {len(objs)}")
|
|
168
|
+
print(f"DEBUG: QuerySet type: {type(self)}")
|
|
169
|
+
print(f"DEBUG: Is this HookQuerySet? {isinstance(self, HookQuerySet)}")
|
|
156
170
|
engine.run(model_cls, AFTER_CREATE, objs, ctx=ctx)
|
|
171
|
+
else:
|
|
172
|
+
print(f"DEBUG: Skipping AFTER_CREATE hooks due to bypass_hooks=True for {model_cls}")
|
|
157
173
|
|
|
158
174
|
return result
|
|
159
175
|
|
|
160
176
|
@transaction.atomic
|
|
161
|
-
def bulk_update(
|
|
162
|
-
self, objs, fields, bypass_hooks=False, bypass_validation=False, **kwargs
|
|
163
|
-
):
|
|
177
|
+
def bulk_update(self, objs, fields, bypass_hooks=False, bypass_validation=False, **kwargs):
|
|
164
178
|
"""
|
|
165
179
|
Bulk update objects in the database.
|
|
166
180
|
"""
|
|
181
|
+
import inspect
|
|
182
|
+
print(f"DEBUG: QuerySet.bulk_update called with:")
|
|
183
|
+
print(f" - self: {type(self)}")
|
|
184
|
+
print(f" - objs: {type(objs)}")
|
|
185
|
+
print(f" - fields: {fields}")
|
|
186
|
+
print(f" - bypass_hooks: {bypass_hooks}")
|
|
187
|
+
print(f" - bypass_validation: {bypass_validation}")
|
|
188
|
+
print(f" - kwargs: {kwargs}")
|
|
189
|
+
print(f"DEBUG: Method signature: {inspect.signature(self.bulk_update)}")
|
|
190
|
+
|
|
167
191
|
model_cls = self.model
|
|
168
|
-
|
|
192
|
+
print(f"DEBUG: Model class: {model_cls}")
|
|
193
|
+
print(f"DEBUG: bypass_hooks value: {bypass_hooks}")
|
|
194
|
+
print(f"DEBUG: QuerySet type: {type(self)}")
|
|
195
|
+
print(f"DEBUG: Is this HookQuerySet? {isinstance(self, HookQuerySet)}")
|
|
196
|
+
|
|
169
197
|
if not objs:
|
|
170
198
|
return []
|
|
171
199
|
|
|
@@ -179,9 +207,7 @@ class HookQuerySet(models.QuerySet):
|
|
|
179
207
|
# Use the base manager to avoid recursion
|
|
180
208
|
original_map = {
|
|
181
209
|
obj.pk: obj
|
|
182
|
-
for obj in model_cls._base_manager.filter(
|
|
183
|
-
pk__in=[obj.pk for obj in objs]
|
|
184
|
-
)
|
|
210
|
+
for obj in model_cls._base_manager.filter(pk__in=[obj.pk for obj in objs])
|
|
185
211
|
}
|
|
186
212
|
originals = [original_map.get(obj.pk) for obj in objs]
|
|
187
213
|
|
|
@@ -193,7 +219,12 @@ class HookQuerySet(models.QuerySet):
|
|
|
193
219
|
|
|
194
220
|
# Then run business logic hooks
|
|
195
221
|
if not bypass_hooks:
|
|
222
|
+
print(f"DEBUG: Firing BEFORE_UPDATE hooks for {model_cls}")
|
|
223
|
+
print(f"DEBUG: Number of objects: {len(objs)}")
|
|
224
|
+
print(f"DEBUG: Object types: {[type(obj) for obj in objs]}")
|
|
196
225
|
engine.run(model_cls, BEFORE_UPDATE, objs, originals, ctx=ctx)
|
|
226
|
+
else:
|
|
227
|
+
print(f"DEBUG: Skipping hooks due to bypass_hooks=True for {model_cls}")
|
|
197
228
|
|
|
198
229
|
# Automatically detect fields that were modified during BEFORE_UPDATE hooks
|
|
199
230
|
modified_fields = self._detect_modified_fields(objs, originals)
|
|
@@ -208,15 +239,15 @@ class HookQuerySet(models.QuerySet):
|
|
|
208
239
|
|
|
209
240
|
# Call the base implementation to avoid re-triggering this method
|
|
210
241
|
# Filter out custom parameters that Django's bulk_update doesn't accept
|
|
211
|
-
django_kwargs = {
|
|
212
|
-
k: v
|
|
213
|
-
for k, v in kwargs.items()
|
|
214
|
-
if k not in ["bypass_hooks", "bypass_validation"]
|
|
215
|
-
}
|
|
242
|
+
django_kwargs = {k: v for k, v in kwargs.items() if k not in ['bypass_hooks', 'bypass_validation']}
|
|
216
243
|
super().bulk_update(chunk, fields, **django_kwargs)
|
|
217
244
|
|
|
218
245
|
if not bypass_hooks:
|
|
246
|
+
print(f"DEBUG: Firing AFTER_UPDATE hooks for {model_cls}")
|
|
247
|
+
print(f"DEBUG: Number of objects: {len(objs)}")
|
|
219
248
|
engine.run(model_cls, AFTER_UPDATE, objs, originals, ctx=ctx)
|
|
249
|
+
else:
|
|
250
|
+
print(f"DEBUG: Skipping AFTER_UPDATE hooks due to bypass_hooks=True for {model_cls}")
|
|
220
251
|
|
|
221
252
|
return objs
|
|
222
253
|
|
|
@@ -319,11 +350,7 @@ class HookQuerySet(models.QuerySet):
|
|
|
319
350
|
Sets auto_now_add/auto_now fields for each model in the chain.
|
|
320
351
|
"""
|
|
321
352
|
# Remove custom hook kwargs before passing to Django internals
|
|
322
|
-
django_kwargs = {
|
|
323
|
-
k: v
|
|
324
|
-
for k, v in kwargs.items()
|
|
325
|
-
if k not in ["bypass_hooks", "bypass_validation"]
|
|
326
|
-
}
|
|
353
|
+
django_kwargs = {k: v for k, v in kwargs.items() if k not in ['bypass_hooks', 'bypass_validation']}
|
|
327
354
|
if inheritance_chain is None:
|
|
328
355
|
inheritance_chain = self._get_inheritance_chain()
|
|
329
356
|
|
|
@@ -356,9 +383,9 @@ class HookQuerySet(models.QuerySet):
|
|
|
356
383
|
|
|
357
384
|
# Step 1: Do O(n) normal inserts into parent tables to get primary keys back
|
|
358
385
|
# Get bypass_hooks from kwargs
|
|
359
|
-
bypass_hooks = kwargs.get(
|
|
360
|
-
bypass_validation = kwargs.get(
|
|
361
|
-
|
|
386
|
+
bypass_hooks = kwargs.get('bypass_hooks', False)
|
|
387
|
+
bypass_validation = kwargs.get('bypass_validation', False)
|
|
388
|
+
|
|
362
389
|
for obj in batch:
|
|
363
390
|
parent_instances = {}
|
|
364
391
|
current_parent = None
|
|
@@ -366,35 +393,32 @@ class HookQuerySet(models.QuerySet):
|
|
|
366
393
|
parent_obj = self._create_parent_instance(
|
|
367
394
|
obj, model_class, current_parent
|
|
368
395
|
)
|
|
369
|
-
|
|
396
|
+
|
|
370
397
|
# Fire parent hooks if not bypassed
|
|
371
398
|
if not bypass_hooks:
|
|
372
399
|
ctx = HookContext(model_class)
|
|
373
400
|
if not bypass_validation:
|
|
374
401
|
engine.run(model_class, VALIDATE_CREATE, [parent_obj], ctx=ctx)
|
|
375
402
|
engine.run(model_class, BEFORE_CREATE, [parent_obj], ctx=ctx)
|
|
376
|
-
|
|
403
|
+
|
|
377
404
|
# Use Django's base manager to create the object and get PKs back
|
|
378
405
|
# This bypasses hooks and the MTI exception
|
|
379
406
|
field_values = {
|
|
380
407
|
field.name: getattr(parent_obj, field.name)
|
|
381
408
|
for field in model_class._meta.local_fields
|
|
382
|
-
if hasattr(parent_obj, field.name)
|
|
383
|
-
and getattr(parent_obj, field.name) is not None
|
|
409
|
+
if hasattr(parent_obj, field.name) and getattr(parent_obj, field.name) is not None
|
|
384
410
|
}
|
|
385
|
-
created_obj = model_class._base_manager.using(self.db).create(
|
|
386
|
-
|
|
387
|
-
)
|
|
388
|
-
|
|
411
|
+
created_obj = model_class._base_manager.using(self.db).create(**field_values)
|
|
412
|
+
|
|
389
413
|
# Update the parent_obj with the created object's PK
|
|
390
414
|
parent_obj.pk = created_obj.pk
|
|
391
415
|
parent_obj._state.adding = False
|
|
392
416
|
parent_obj._state.db = self.db
|
|
393
|
-
|
|
417
|
+
|
|
394
418
|
# Fire AFTER_CREATE hooks for parent
|
|
395
419
|
if not bypass_hooks:
|
|
396
420
|
engine.run(model_class, AFTER_CREATE, [parent_obj], ctx=ctx)
|
|
397
|
-
|
|
421
|
+
|
|
398
422
|
parent_instances[model_class] = parent_obj
|
|
399
423
|
current_parent = parent_obj
|
|
400
424
|
parent_objects_map[id(obj)] = parent_instances
|
|
@@ -412,10 +436,10 @@ class HookQuerySet(models.QuerySet):
|
|
|
412
436
|
if all_child_objects:
|
|
413
437
|
# Get the base manager's queryset
|
|
414
438
|
base_qs = child_model._base_manager.using(self.db)
|
|
415
|
-
|
|
439
|
+
|
|
416
440
|
# Use Django's exact approach: call _prepare_for_bulk_create then partition
|
|
417
441
|
base_qs._prepare_for_bulk_create(all_child_objects)
|
|
418
|
-
|
|
442
|
+
|
|
419
443
|
# Implement our own partition since itertools.partition might not be available
|
|
420
444
|
objs_without_pk, objs_with_pk = [], []
|
|
421
445
|
for obj in all_child_objects:
|
|
@@ -423,50 +447,44 @@ class HookQuerySet(models.QuerySet):
|
|
|
423
447
|
objs_with_pk.append(obj)
|
|
424
448
|
else:
|
|
425
449
|
objs_without_pk.append(obj)
|
|
426
|
-
|
|
450
|
+
|
|
427
451
|
# Use Django's internal _batched_insert method
|
|
428
452
|
opts = child_model._meta
|
|
429
453
|
# For child models in MTI, we need to include the foreign key to the parent
|
|
430
454
|
# but exclude the primary key since it's inherited
|
|
431
|
-
|
|
455
|
+
|
|
432
456
|
# Include all local fields except generated ones
|
|
433
457
|
# We need to include the foreign key to the parent (business_ptr)
|
|
434
458
|
fields = [f for f in opts.local_fields if not f.generated]
|
|
435
|
-
|
|
459
|
+
|
|
436
460
|
with transaction.atomic(using=self.db, savepoint=False):
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
objs_without_pk, returned_columns
|
|
465
|
-
):
|
|
466
|
-
for result, field in zip(results, opts.db_returning_fields):
|
|
467
|
-
setattr(obj_without_pk, field.attname, result)
|
|
468
|
-
obj_without_pk._state.adding = False
|
|
469
|
-
obj_without_pk._state.db = self.db
|
|
461
|
+
if objs_with_pk:
|
|
462
|
+
returned_columns = base_qs._batched_insert(
|
|
463
|
+
objs_with_pk,
|
|
464
|
+
fields,
|
|
465
|
+
batch_size=len(objs_with_pk), # Use actual batch size
|
|
466
|
+
)
|
|
467
|
+
for obj_with_pk, results in zip(objs_with_pk, returned_columns):
|
|
468
|
+
for result, field in zip(results, opts.db_returning_fields):
|
|
469
|
+
if field != opts.pk:
|
|
470
|
+
setattr(obj_with_pk, field.attname, result)
|
|
471
|
+
for obj_with_pk in objs_with_pk:
|
|
472
|
+
obj_with_pk._state.adding = False
|
|
473
|
+
obj_with_pk._state.db = self.db
|
|
474
|
+
|
|
475
|
+
if objs_without_pk:
|
|
476
|
+
# For objects without PK, we still need to exclude primary key fields
|
|
477
|
+
fields = [f for f in fields if not isinstance(f, AutoField) and not f.primary_key]
|
|
478
|
+
returned_columns = base_qs._batched_insert(
|
|
479
|
+
objs_without_pk,
|
|
480
|
+
fields,
|
|
481
|
+
batch_size=len(objs_without_pk), # Use actual batch size
|
|
482
|
+
)
|
|
483
|
+
for obj_without_pk, results in zip(objs_without_pk, returned_columns):
|
|
484
|
+
for result, field in zip(results, opts.db_returning_fields):
|
|
485
|
+
setattr(obj_without_pk, field.attname, result)
|
|
486
|
+
obj_without_pk._state.adding = False
|
|
487
|
+
obj_without_pk._state.db = self.db
|
|
470
488
|
|
|
471
489
|
# Step 3: Update original objects with generated PKs and state
|
|
472
490
|
pk_field_name = child_model._meta.pk.name
|
|
@@ -519,19 +537,15 @@ class HookQuerySet(models.QuerySet):
|
|
|
519
537
|
value = getattr(source_obj, field.name, None)
|
|
520
538
|
if value is not None:
|
|
521
539
|
setattr(child_obj, field.name, value)
|
|
522
|
-
|
|
540
|
+
|
|
523
541
|
# Set parent links for MTI
|
|
524
542
|
for parent_model, parent_instance in parent_instances.items():
|
|
525
543
|
parent_link = child_model._meta.get_ancestor_link(parent_model)
|
|
526
544
|
if parent_link:
|
|
527
545
|
# Set both the foreign key value (the ID) and the object reference
|
|
528
546
|
# This follows Django's pattern in _set_pk_val
|
|
529
|
-
setattr(
|
|
530
|
-
|
|
531
|
-
) # Set the foreign key value
|
|
532
|
-
setattr(
|
|
533
|
-
child_obj, parent_link.name, parent_instance
|
|
534
|
-
) # Set the object reference
|
|
547
|
+
setattr(child_obj, parent_link.attname, parent_instance.pk) # Set the foreign key value
|
|
548
|
+
setattr(child_obj, parent_link.name, parent_instance) # Set the object reference
|
|
535
549
|
|
|
536
550
|
# Handle auto_now_add and auto_now fields like Django does
|
|
537
551
|
for field in child_model._meta.local_fields:
|
|
@@ -544,4 +558,4 @@ class HookQuerySet(models.QuerySet):
|
|
|
544
558
|
elif hasattr(field, "auto_now") and field.auto_now:
|
|
545
559
|
field.pre_save(child_obj, add=True)
|
|
546
560
|
|
|
547
|
-
return child_obj
|
|
561
|
+
return child_obj
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "django-bulk-hooks"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.173"
|
|
4
4
|
description = "Hook-style hooks for Django bulk operations like bulk_create and bulk_update."
|
|
5
5
|
authors = ["Konrad Beck <konrad.beck@merchantcapital.co.za>"]
|
|
6
6
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|