winidjango 1.0.4__py3-none-any.whl → 2.0.55__py3-none-any.whl

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.
winidjango/src/db/bulk.py CHANGED
@@ -1,8 +1,10 @@
1
- """Bulk utilities for Django models.
1
+ """Utilities for performing bulk operations on Django models.
2
2
 
3
- This module provides utility functions for working with Django models,
4
- including bulk operations and validation. These utilities help with
5
- efficiently managing large amounts of data in Django applications.
3
+ This module centralizes helpers used by importers and maintenance
4
+ commands to create, update and delete large collections of model
5
+ instances efficiently. It provides batching, optional concurrent
6
+ execution, dependency-aware ordering and simulation helpers for
7
+ previewing cascade deletions.
6
8
  """
7
9
 
8
10
  from collections import defaultdict
@@ -48,20 +50,19 @@ def bulk_create_in_steps[TModel: Model](
48
50
  bulk: Iterable[TModel],
49
51
  step: int = STANDARD_BULK_SIZE,
50
52
  ) -> list[TModel]:
51
- """Create model instances from bulk and saves them to the database in steps.
53
+ """Create objects in batches and return created instances.
52
54
 
53
- Takes a list of model instances and creates them in the database in steps.
54
- This is useful when you want to create a large number of objects
55
- in the database. It also uses multithreading to speed up the process.
55
+ Breaks ``bulk`` into chunks of size ``step`` and calls the project's
56
+ batched bulk-create helper for each chunk. Execution is performed
57
+ using the concurrent utility where configured for throughput.
56
58
 
57
59
  Args:
58
- model (type[Model]): The Django model class to create.
59
- bulk (Iterable[Model]): a list of model instances to create.
60
- step (int, optional): The step size of the bulk creation.
61
- Defaults to STANDARD_BULK_SIZE.
60
+ model: Django model class to create instances for.
61
+ bulk: Iterable of unsaved model instances.
62
+ step: Number of instances to create per chunk.
62
63
 
63
64
  Returns:
64
- list[Model]: a list of created objects.
65
+ List of created model instances (flattened across chunks).
65
66
  """
66
67
  return cast(
67
68
  "list[TModel]",
@@ -75,21 +76,17 @@ def bulk_update_in_steps[TModel: Model](
75
76
  update_fields: list[str],
76
77
  step: int = STANDARD_BULK_SIZE,
77
78
  ) -> int:
78
- """Update model instances in the database in steps using multithreading.
79
-
80
- Takes a list of model instances and updates them in the database in chunks.
81
- This is useful when you want to update a large number of objects efficiently.
82
- Uses multithreading to speed up the process by processing chunks in parallel.
79
+ """Update objects in batches and return total updated count.
83
80
 
84
81
  Args:
85
- model (type[Model]): The Django model class to update.
86
- bulk (Iterable[Model]): A list of model instances to update.
87
- update_fields (list[str]): List of field names to update on the models.
88
- step (int, optional): The step size for bulk updates.
89
- Defaults to STANDARD_BULK_SIZE.
82
+ model: Django model class.
83
+ bulk: Iterable of model instances to update (must have PKs set).
84
+ update_fields: Fields to update on each instance when calling
85
+ ``bulk_update``.
86
+ step: Chunk size for batched updates.
90
87
 
91
88
  Returns:
92
- int: Total number of objects updated across all chunks.
89
+ Total number of rows updated across all chunks.
93
90
  """
94
91
  return cast(
95
92
  "int",
@@ -102,23 +99,21 @@ def bulk_update_in_steps[TModel: Model](
102
99
  def bulk_delete_in_steps[TModel: Model](
103
100
  model: type[TModel], bulk: Iterable[TModel], step: int = STANDARD_BULK_SIZE
104
101
  ) -> tuple[int, dict[str, int]]:
105
- """Delete model instances from the database in steps using multithreading.
102
+ """Delete objects in batches and return deletion statistics.
106
103
 
107
- Takes a list of model instances and deletes them from the database in chunks.
108
- This is useful when you want to delete a large number of objects efficiently.
109
- Uses multithreading to speed up the process by processing chunks in parallel.
110
- Also handles cascade deletions according to model relationships.
104
+ Each chunk is deleted using Django's QuerySet ``delete`` which
105
+ returns a (count, per-model-counts) tuple. Results are aggregated
106
+ across chunks and returned as a consolidated tuple.
111
107
 
112
108
  Args:
113
- model (type[Model]): The Django model class to update.
114
- bulk (Iterable[Model]): A list of model instances to delete.
115
- step (int, optional): The step size for bulk deletions.
116
- Defaults to STANDARD_BULK_SIZE.
109
+ model: Django model class.
110
+ bulk: Iterable of model instances to delete.
111
+ step: Chunk size for deletions.
117
112
 
118
113
  Returns:
119
- tuple[int, dict[str, int]]: A tuple containing the
120
- total count of deleted objects
121
- and a dictionary mapping model names to their deletion counts.
114
+ A tuple containing the total number of deleted objects and a
115
+ mapping from model label to deleted count (including cascaded
116
+ deletions).
122
117
  """
123
118
  return cast(
124
119
  "tuple[int, dict[str, int]]",
@@ -168,26 +163,25 @@ def bulk_method_in_steps[TModel: Model](
168
163
  mode: MODE_TYPES,
169
164
  **kwargs: Any,
170
165
  ) -> int | tuple[int, dict[str, int]] | list[TModel]:
171
- """Execute bulk operations on model instances in steps with transaction handling.
166
+ """Run a batched bulk operation (create/update/delete) on ``bulk``.
172
167
 
173
- This is the core function that handles bulk create, update, or delete operations
174
- by dividing the work into manageable chunks and processing them with multithreading.
175
- It includes transaction safety checks and delegates to the atomic version.
168
+ This wrapper warns if called from within an existing transaction and
169
+ delegates actual work to :func:`bulk_method_in_steps_atomic` which is
170
+ executed inside an atomic transaction. The return type depends on
171
+ ``mode`` (see :mod:`winidjango.src.db.bulk` constants).
176
172
 
177
173
  Args:
178
- model (type[Model]): The Django model class to perform operations on.
179
- bulk (Iterable[Model]): A list of model instances to process.
180
- step (int): The step size for chunking the bulk operations.
181
- mode (MODE_TYPES): The operation mode - 'create', 'update', or 'delete'.
182
- **kwargs: Additional keyword arguments passed to the bulk operation methods.
174
+ model: Django model class to operate on.
175
+ bulk: Iterable of model instances.
176
+ step: Chunk size for processing.
177
+ mode: One of ``'create'``, ``'update'`` or ``'delete'``.
178
+ **kwargs: Additional keyword arguments forwarded to the underlying
179
+ bulk methods (for example ``update_fields`` for updates).
183
180
 
184
181
  Returns:
185
- None | int | tuple[int, dict[str, int]] | list[Model]:
186
- The result depends on mode:
187
- - create: list of created model instances
188
- - update: integer count of updated objects
189
- - delete: tuple of (total_count, count_by_model_dict)
190
- - None if bulk is empty
182
+ For ``create``: list of created instances.
183
+ For ``update``: integer number of updated rows.
184
+ For ``delete``: tuple(total_deleted, per_model_counts).
191
185
  """
192
186
  # check if we are inside a transaction.atomic block
193
187
  _in_atomic_block = transaction.get_connection().in_atomic_block
@@ -244,29 +238,24 @@ def bulk_method_in_steps_atomic[TModel: Model](
244
238
  mode: MODE_TYPES,
245
239
  **kwargs: Any,
246
240
  ) -> int | tuple[int, dict[str, int]] | list[TModel]:
247
- """Bulk create, update or delete the given list of objects in steps.
241
+ """Atomic implementation of the batched bulk operation.
248
242
 
249
- WHEN BULK CREATING OR UPDATING A BULK
250
- AND THEN A SECOND BULK THAT DEPENDS ON THE FIRST BULK,
251
- YOU WILL RUN INTO A INTEGRITY ERROR IF YOU DO THE
252
- ENTIRE THING IN AN @transaction.atomic DECORATOR.
253
- REMOVE THE DECORATORS THAT ARE HIGHER UP THAN THE ONE OF THIS FUNCTION
254
- TO AVOID THIS ERROR.
243
+ This function is decorated with ``transaction.atomic`` so each call
244
+ to this function runs in a database transaction. Note that nesting
245
+ additional, outer atomic blocks that also include dependent bulk
246
+ operations can cause integrity issues for operations that depend on
247
+ each other's side-effects; callers should be careful about atomic
248
+ decorator placement in higher-level code.
255
249
 
256
250
  Args:
257
- model (type[Model]): The Django model class to perform operations on.
258
- bulk (Iterable[Model]): A list of model instances to process.
259
- step (int): number of objects to process in one chunk
260
- mode (MODE_TYPES): The operation mode - 'create', 'update', or 'delete'.
261
- **kwargs: Additional keyword arguments passed to the bulk operation methods.
251
+ model: Django model class.
252
+ bulk: Iterable of model instances.
253
+ step: Chunk size for processing.
254
+ mode: One of ``'create'``, ``'update'`` or ``'delete'``.
255
+ **kwargs: Forwarded to the underlying bulk method.
262
256
 
263
257
  Returns:
264
- None | int | tuple[int, dict[str, int]] | list[Model]:
265
- The result depends on mode:
266
- - create: list of created model instances
267
- - update: integer count of updated objects
268
- - delete: tuple of (total_count, count_by_model_dict)
269
- - None if bulk is empty
258
+ See :func:`bulk_method_in_steps` for return value semantics.
270
259
  """
271
260
  bulk_method = get_bulk_method(model=model, mode=mode, **kwargs)
272
261
 
@@ -284,14 +273,18 @@ def bulk_method_in_steps_atomic[TModel: Model](
284
273
  def get_step_chunks(
285
274
  bulk: Iterable[Model], step: int
286
275
  ) -> Generator[tuple[list[Model]], None, None]:
287
- """Yield chunks of the given size from the bulk.
276
+ """Yield consecutive chunks of at most ``step`` items from ``bulk``.
277
+
278
+ The function yields a single-tuple containing the chunk (a list of
279
+ model instances) because the concurrent execution helper expects a
280
+ tuple of positional arguments for the target function.
288
281
 
289
282
  Args:
290
- bulk (Iterable[Model]): The bulk to chunk.
291
- step (int): The size of each chunk.
283
+ bulk: Iterable of model instances.
284
+ step: Maximum number of instances per yielded chunk.
292
285
 
293
286
  Yields:
294
- Generator[list[Model], None, None]: Chunks of the bulk.
287
+ Tuples where the first element is a list of model instances.
295
288
  """
296
289
  bulk = iter(bulk)
297
290
  while True:
@@ -323,23 +316,22 @@ def get_bulk_method(
323
316
  def get_bulk_method(
324
317
  model: type[Model], mode: MODE_TYPES, **kwargs: Any
325
318
  ) -> Callable[[list[Model]], list[Model] | int | tuple[int, dict[str, int]]]:
326
- """Get the appropriate bulk method function based on the operation mode.
319
+ """Return a callable that performs the requested bulk operation on a chunk.
327
320
 
328
- Creates and returns a function that performs the specified bulk operation
329
- (create, update, or delete) on a chunk of model instances. The returned
330
- function is configured with the provided kwargs.
321
+ The returned function accepts a single argument (a list of model
322
+ instances) and returns the per-chunk result for the chosen mode.
331
323
 
332
324
  Args:
333
- model (type[Model]): The Django model class to perform operations on.
334
- mode (MODE_TYPES): The operation mode - 'create', 'update', or 'delete'.
335
- **kwargs: Additional keyword arguments to pass to the bulk operation method.
325
+ model: Django model class.
326
+ mode: One of ``'create'``, ``'update'`` or ``'delete'``.
327
+ **kwargs: Forwarded to the underlying ORM bulk methods.
336
328
 
337
329
  Raises:
338
- ValueError: If the mode is not one of the valid MODE_TYPES.
330
+ ValueError: If ``mode`` is invalid.
339
331
 
340
332
  Returns:
341
- Callable[[list[Model]], Any]: A function that performs the bulk operation
342
- on a chunk of model instances.
333
+ Callable that accepts a list of model instances and returns the
334
+ result for that chunk.
343
335
  """
344
336
  bulk_method: Callable[[list[Model]], list[Model] | int | tuple[int, dict[str, int]]]
345
337
  if mode == MODE_CREATE:
@@ -389,24 +381,22 @@ def flatten_bulk_in_steps_result[TModel: Model](
389
381
  def flatten_bulk_in_steps_result[TModel: Model](
390
382
  result: list[int] | list[tuple[int, dict[str, int]]] | list[list[TModel]], mode: str
391
383
  ) -> int | tuple[int, dict[str, int]] | list[TModel]:
392
- """Flatten and aggregate results from multithreaded bulk operations.
384
+ """Aggregate per-chunk results returned by concurrent bulk execution.
393
385
 
394
- Processes the results returned from parallel bulk operations and aggregates
395
- them into the appropriate format based on the operation mode. Handles
396
- different return types for create, update, and delete operations.
386
+ Depending on ``mode`` the function reduces a list of per-chunk
387
+ results into a single consolidated return value:
397
388
 
398
- Args:
399
- result (list[Any]): List of results from each chunk operation.
400
- mode (str): The operation mode - 'create', 'update', or 'delete'.
389
+ - ``create``: flattens a list of lists into a single list of objects
390
+ - ``update``: sums integer counts returned per chunk
391
+ - ``delete``: aggregates (count, per-model-dict) tuples into a single
392
+ total and combined per-model counts
401
393
 
402
- Raises:
403
- ValueError: If the mode is not one of the valid operation modes.
394
+ Args:
395
+ result: List of per-chunk results returned by the chunk function.
396
+ mode: One of the supported modes.
404
397
 
405
398
  Returns:
406
- None | int | tuple[int, dict[str, int]] | list[Model]: Aggregated result:
407
- - update: sum of updated object counts
408
- - delete: tuple of (total_count, count_by_model_dict)
409
- - create: flattened list of all created objects
399
+ Aggregated result corresponding to ``mode``.
410
400
  """
411
401
  if mode == MODE_UPDATE:
412
402
  # formated as [1000, 1000, ...]
@@ -436,26 +426,24 @@ def flatten_bulk_in_steps_result[TModel: Model](
436
426
  def bulk_delete(
437
427
  model: type[Model], objs: Iterable[Model], **_: Any
438
428
  ) -> tuple[int, dict[str, int]]:
439
- """Delete model instances using Django's QuerySet delete method.
429
+ """Delete the provided objects and return Django's delete summary.
440
430
 
441
- Deletes the provided model instances from the database using Django's
442
- built-in delete functionality. Handles both individual model instances
443
- and QuerySets, and returns deletion statistics including cascade counts.
431
+ Accepts either a QuerySet or an iterable of model instances. When an
432
+ iterable of instances is provided it is converted to a QuerySet by
433
+ filtering on primary keys before calling ``QuerySet.delete()``.
444
434
 
445
435
  Args:
446
- model (type[Model]): The Django model class to delete from.
447
- objs (list[Model]): A list of model instances to delete.
436
+ model: Django model class.
437
+ objs: Iterable of model instances or a QuerySet.
448
438
 
449
439
  Returns:
450
- tuple[int, dict[str, int]]: A tuple containing the total count of deleted
451
- objects and a dictionary mapping model names to their deletion counts.
440
+ Tuple(total_deleted, per_model_counts) as returned by ``delete()``.
452
441
  """
453
- if not isinstance(objs, QuerySet):
454
- objs = list(objs)
455
- pks = [obj.pk for obj in objs]
442
+ query_set = objs
443
+ if not isinstance(query_set, QuerySet):
444
+ query_set = list(query_set)
445
+ pks = [obj.pk for obj in query_set]
456
446
  query_set = model.objects.filter(pk__in=pks)
457
- else:
458
- query_set = objs
459
447
 
460
448
  return query_set.delete()
461
449
 
@@ -464,22 +452,19 @@ def bulk_create_bulks_in_steps[TModel: Model](
464
452
  bulk_by_class: dict[type[TModel], Iterable[TModel]],
465
453
  step: int = STANDARD_BULK_SIZE,
466
454
  ) -> dict[type[TModel], list[TModel]]:
467
- """Create multiple bulks of different model types in dependency order.
455
+ """Create multiple model-type bulks in dependency order.
468
456
 
469
- Takes a dictionary mapping model classes to lists of instances and creates
470
- them in the database in the correct order based on model dependencies.
471
- Uses topological sorting to ensure foreign key constraints are satisfied.
457
+ The function topologically sorts the provided model classes so that
458
+ models referenced by foreign keys are created before models that
459
+ reference them. Each class' instances are created in batches using
460
+ :func:`bulk_create_in_steps`.
472
461
 
473
462
  Args:
474
- bulk_by_class (dict[type[Model], list[Model]]): Dictionary mapping model classes
475
- to lists of instances to create.
476
- step (int, optional): The step size for bulk creation. Defaults to 1000.
477
- validate (bool, optional): Whether to validate instances before creation.
478
- Defaults to True.
463
+ bulk_by_class: Mapping from model class to iterable of instances to create.
464
+ step: Chunk size for each model's batched creation.
479
465
 
480
466
  Returns:
481
- dict[type[Model], list[Model]]: Dictionary mapping model classes to lists
482
- of created instances.
467
+ Mapping from model class to list of created instances.
483
468
  """
484
469
  # order the bulks in order of creation depending how they depend on each other
485
470
  models_ = list(bulk_by_class.keys())
@@ -499,29 +484,24 @@ def get_differences_between_bulks(
499
484
  bulk2: list[Model],
500
485
  fields: "list[Field[Any, Any] | ForeignObjectRel | GenericForeignKey]",
501
486
  ) -> tuple[list[Model], list[Model], list[Model], list[Model]]:
502
- """Compare two bulks and return their differences and intersections.
487
+ """Return differences and intersections between two bulks of the same model.
503
488
 
504
- Compares two lists of model instances by computing hashes of their field values
505
- and returns the differences and intersections between them. Optionally allows
506
- specifying which fields to compare and the depth of comparison for related objects.
489
+ Instances are compared using :func:`hash_model_instance` over the
490
+ provided ``fields``. The function maintains the original ordering
491
+ for returned lists so that callers can preserve deterministic
492
+ ordering when applying diffs.
507
493
 
508
494
  Args:
509
- bulk1 (list[Model]): First list of model instances to compare.
510
- bulk2 (list[Model]): Second list of model instances to compare.
511
- fields (list[Field] | None, optional): List of fields to compare.
512
- Defaults to None, which compares all fields.
513
- max_depth (int | None, optional): Maximum depth for comparing related objects.
514
- Defaults to None.
495
+ bulk1: First list of model instances.
496
+ bulk2: Second list of model instances.
497
+ fields: Fields to include when hashing instances.
515
498
 
516
499
  Raises:
517
- ValueError: If the two bulks contain different model types.
500
+ ValueError: If bulks are empty or contain different model types.
518
501
 
519
502
  Returns:
520
- tuple[list[Model], list[Model], list[Model], list[Model]]: A tuple containing:
521
- - Objects in bulk1 but not in bulk2
522
- - Objects in bulk2 but not in bulk1
523
- - Objects in both bulk1 and bulk2 (from bulk1)
524
- - Objects in both bulk1 and bulk2 (from bulk2)
503
+ Four lists in the order:
504
+ (in_1_not_2, in_2_not_1, in_both_from_1, in_both_from_2).
525
505
  """
526
506
  if not bulk1 or not bulk2:
527
507
  return bulk1, bulk2, [], []
@@ -577,19 +557,18 @@ def get_differences_between_bulks(
577
557
  def simulate_bulk_deletion(
578
558
  model_class: type[Model], entries: list[Model]
579
559
  ) -> dict[type[Model], set[Model]]:
580
- """Simulate bulk deletion to preview what objects would be deleted.
560
+ """Simulate Django's delete cascade and return affected objects.
581
561
 
582
- Uses Django's Collector to simulate the deletion process and determine
583
- which objects would be deleted due to cascade relationships, without
584
- actually performing the deletion. Useful for previewing deletion effects.
562
+ Uses :class:`django.db.models.deletion.Collector` to determine which
563
+ objects (including cascaded related objects) would be removed if the
564
+ provided entries were deleted. No database writes are performed.
585
565
 
586
566
  Args:
587
- model_class (type[Model]): The Django model class of the entries to delete.
588
- entries (list[Model]): List of model instances to simulate deletion for.
567
+ model_class: Model class of the provided entries.
568
+ entries: Instances to simulate deletion for.
589
569
 
590
570
  Returns:
591
- dict[type[Model], set[Model]]: Dictionary mapping model classes to sets
592
- of objects that would be deleted, including cascade deletions.
571
+ Mapping from model class to set of instances that would be deleted.
593
572
  """
594
573
  if not entries:
595
574
  return {}
@@ -599,7 +578,7 @@ def simulate_bulk_deletion(
599
578
  collector = Collector(using)
600
579
 
601
580
  # Collect deletion cascade for all entries
602
- collector.collect(entries)
581
+ collector.collect(entries) # ty:ignore[invalid-argument-type]
603
582
 
604
583
  # Prepare the result dictionary
605
584
  deletion_summary: defaultdict[type[Model], set[Model]] = defaultdict(set)
@@ -618,25 +597,22 @@ def simulate_bulk_deletion(
618
597
  def multi_simulate_bulk_deletion(
619
598
  entries: dict[type[Model], list[Model]],
620
599
  ) -> dict[type[Model], set[Model]]:
621
- """Simulate bulk deletion for multiple model types and aggregate results.
600
+ """Simulate deletions for multiple model classes and merge results.
622
601
 
623
- Performs deletion simulation for multiple model types and combines the results
624
- into a single summary. This is useful when you want to preview the deletion
625
- effects across multiple related model types.
602
+ Runs :func:`simulate_bulk_deletion` for each provided model and
603
+ returns a unified mapping of all models that would be deleted.
626
604
 
627
605
  Args:
628
- entries (dict[type[Model], list[Model]]): Dictionary mapping model classes
629
- to lists of instances to simulate deletion for.
606
+ entries: Mapping from model class to list of instances to simulate.
630
607
 
631
608
  Returns:
632
- dict[type[Model], set[Model]]: Dictionary mapping model classes to sets
633
- of all objects that would be deleted across all simulations.
609
+ Mapping from model class to set of instances that would be deleted.
634
610
  """
635
611
  deletion_summaries = [
636
612
  simulate_bulk_deletion(model, entry) for model, entry in entries.items()
637
613
  ]
638
614
  # join the dicts to get the total count of deleted objects
639
- joined_deletion_summary = defaultdict(set)
615
+ joined_deletion_summary: defaultdict[type[Model], set[Model]] = defaultdict(set)
640
616
  for deletion_summary in deletion_summaries:
641
617
  for model, objects in deletion_summary.items():
642
618
  joined_deletion_summary[model].update(objects)
@@ -1,6 +1,9 @@
1
- """Fields module.
1
+ """Utilities for inspecting Django model fields.
2
2
 
3
- Utils for working with Django model fields.
3
+ This module provides small helpers that make it easier to introspect
4
+ Django model fields and metadata in a type-friendly way. The helpers are
5
+ used across the project's database utilities to implement operations like
6
+ topological sorting and deterministic hashing of model instances.
4
7
  """
5
8
 
6
9
  from typing import TYPE_CHECKING, Any
@@ -16,54 +19,29 @@ if TYPE_CHECKING:
16
19
  def get_field_names(
17
20
  fields: "list[Field[Any, Any] | ForeignObjectRel | GenericForeignKey]",
18
21
  ) -> list[str]:
19
- """Get the names of all fields from a Django model including relationships.
20
-
21
- Retrieves the names of all field objects from a Django model, including
22
- regular fields, foreign key relationships, reverse foreign key relationships,
23
- and generic foreign keys. This provides a comprehensive view of all model
24
- attributes that can be used for introspection, validation, or bulk operations.
22
+ """Return the ``name`` attribute for a list of Django field objects.
25
23
 
26
24
  Args:
27
25
  fields (list[Field | ForeignObjectRel | GenericForeignKey]):
28
- The list of field objects to get names from.
26
+ Field objects obtained from a model's ``_meta.get_fields()``.
29
27
 
30
28
  Returns:
31
- list[str]: A list containing the names of all fields.
32
-
33
- Example:
34
- >>> from django.contrib.auth.models import User
35
- >>> fields = get_fields(User)
36
- >>> field_names = get_field_names(fields)
37
- >>> 'username' in field_names
38
- True
39
- >>> 'email' in field_names
40
- True
29
+ list[str]: List of field names in the same order as ``fields``.
41
30
  """
42
31
  return [field.name for field in fields]
43
32
 
44
33
 
45
34
  def get_model_meta(model: type[Model]) -> "Options[Model]":
46
- """Get the Django model metadata options object.
35
+ """Return a model class' ``_meta`` options object.
47
36
 
48
- Retrieves the _meta attribute from a Django model class, which contains
49
- metadata about the model including field definitions, table name, and
50
- other model configuration options. This is a convenience wrapper around
51
- accessing the private _meta attribute directly.
37
+ This small wrapper exists to make typing clearer at call sites where
38
+ the code needs the model Options object.
52
39
 
53
40
  Args:
54
- model (type[Model]): The Django model class to get metadata from.
41
+ model (type[Model]): Django model class.
55
42
 
56
43
  Returns:
57
- Options[Model]: The model's metadata options object containing
58
- field definitions, table information, and other model configuration.
59
-
60
- Example:
61
- >>> from django.contrib.auth.models import User
62
- >>> meta = get_model_meta(User)
63
- >>> meta.db_table
64
- 'auth_user'
65
- >>> len(meta.get_fields())
66
- 11
44
+ Options: The model's ``_meta`` options object.
67
45
  """
68
46
  return model._meta # noqa: SLF001
69
47
 
@@ -71,31 +49,17 @@ def get_model_meta(model: type[Model]) -> "Options[Model]":
71
49
  def get_fields[TModel: Model](
72
50
  model: type[TModel],
73
51
  ) -> "list[Field[Any, Any] | ForeignObjectRel | GenericForeignKey]":
74
- """Get all fields from a Django model including relationships.
52
+ """Return all field objects for a Django model.
75
53
 
76
- Retrieves all field objects from a Django model, including regular fields,
77
- foreign key relationships, reverse foreign key relationships, and generic
78
- foreign keys. This provides a comprehensive view of all model attributes
79
- that can be used for introspection, validation, or bulk operations.
54
+ This wraps ``model._meta.get_fields()`` and is typed to include
55
+ relationship fields so callers can handle both regular and related
56
+ fields uniformly.
80
57
 
81
58
  Args:
82
- model (type[Model]): The Django model class to get fields from.
59
+ model (type[Model]): Django model class.
83
60
 
84
61
  Returns:
85
- list[Field | ForeignObjectRel | GenericForeignKey]: A list
86
- containing all field objects associated with the model, including:
87
- - Regular model fields (CharField, IntegerField, etc.)
88
- - Foreign key fields (ForeignKey, OneToOneField, etc.)
89
- - Reverse relationship fields (ForeignObjectRel)
90
- - Generic foreign key fields (GenericForeignKey)
91
-
92
- Example:
93
- >>> from django.contrib.auth.models import User
94
- >>> fields = get_fields(User)
95
- >>> field_names = [f.name for f in fields if hasattr(f, 'name')]
96
- >>> 'username' in field_names
97
- True
98
- >>> 'email' in field_names
99
- True
62
+ list[Field | ForeignObjectRel | GenericForeignKey]: All field
63
+ objects associated with the model.
100
64
  """
101
65
  return get_model_meta(model).get_fields()