django-display-ids 0.5.0__tar.gz → 0.5.2__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.
Files changed (25) hide show
  1. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/PKG-INFO +1 -1
  2. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/pyproject.toml +1 -1
  3. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/managers.py +83 -2
  4. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/README.md +0 -0
  5. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/__init__.py +0 -0
  6. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/admin.py +0 -0
  7. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/apps.py +0 -0
  8. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/conf.py +0 -0
  9. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/contrib/__init__.py +0 -0
  10. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/contrib/drf_spectacular/__init__.py +0 -0
  11. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/contrib/rest_framework/__init__.py +0 -0
  12. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/contrib/rest_framework/serializers.py +0 -0
  13. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/contrib/rest_framework/views.py +0 -0
  14. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/converters.py +0 -0
  15. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/encoding.py +0 -0
  16. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/examples.py +0 -0
  17. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/exceptions.py +0 -0
  18. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/models.py +0 -0
  19. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/py.typed +0 -0
  20. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/resolver.py +0 -0
  21. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/strategies.py +0 -0
  22. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/templatetags/__init__.py +0 -0
  23. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/templatetags/display_ids.py +0 -0
  24. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/typing.py +0 -0
  25. {django_display_ids-0.5.0 → django_display_ids-0.5.2}/src/django_display_ids/views.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: django-display-ids
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Stripe-like prefixed IDs for Django. Works with existing UUIDs — no schema changes.
5
5
  Keywords: django,stripe,uuid,base62,prefixed-id,drf,shortuuid,nanoid,ulid
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "django-display-ids"
3
- version = "0.5.0"
3
+ version = "0.5.2"
4
4
  description = "Stripe-like prefixed IDs for Django. Works with existing UUIDs — no schema changes."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -187,6 +187,69 @@ class DisplayIDQuerySet(models.QuerySet[M]):
187
187
  # Execute the query
188
188
  return self.get(**lookup)
189
189
 
190
+ def resolve_identifier(
191
+ self,
192
+ value: str | uuid.UUID,
193
+ *,
194
+ strategies: tuple[StrategyName, ...] | None = None,
195
+ prefix: str | None = None,
196
+ ) -> uuid.UUID:
197
+ """Resolve an identifier to a UUID without fetching the object.
198
+
199
+ For UUID and display_id identifiers, the UUID is extracted by parsing
200
+ alone — no database query is needed. Only slug identifiers require a
201
+ database lookup.
202
+
203
+ This is useful for cursor-based pagination where you need the UUID
204
+ value to build a WHERE clause but don't need the full model instance.
205
+
206
+ Args:
207
+ value: The identifier string (display ID, UUID, or slug),
208
+ or a UUID instance (returned as-is).
209
+ strategies: Strategies to try. Defaults to settings.
210
+ prefix: Expected display ID prefix for validation.
211
+
212
+ Returns:
213
+ The resolved UUID value.
214
+
215
+ Raises:
216
+ Model.DoesNotExist: If the identifier cannot be parsed or
217
+ no matching object exists (slug lookup).
218
+ Model.MultipleObjectsReturned: If multiple objects match (slug).
219
+ """
220
+ model = self.model
221
+ uuid_field = self._get_uuid_field()
222
+
223
+ # UUID objects are returned as-is
224
+ if isinstance(value, uuid.UUID):
225
+ return value
226
+
227
+ slug_field = self._get_slug_field()
228
+ expected_prefix = prefix or self._get_model_prefix()
229
+ lookup_strategies = strategies or self._get_strategies()
230
+
231
+ # Skip slug strategy if the model has no slug field
232
+ if not self._has_slug_field(slug_field):
233
+ lookup_strategies = tuple(s for s in lookup_strategies if s != "slug")
234
+
235
+ # Parse the identifier
236
+ try:
237
+ result = parse_identifier(
238
+ value, lookup_strategies, expected_prefix=expected_prefix
239
+ )
240
+ except DisplayIDLookupError as e:
241
+ raise model.DoesNotExist( # type: ignore[attr-defined]
242
+ f"{model.__name__}: {e}"
243
+ ) from e
244
+
245
+ # UUID and display_id strategies yield a UUID directly — no DB query
246
+ if result.strategy in ("uuid", "display_id"):
247
+ return result.uuid # type: ignore[return-value]
248
+
249
+ # Slug strategy requires a DB lookup
250
+ obj = self.get(**{slug_field: result.slug})
251
+ return getattr(obj, uuid_field) # type: ignore[no-any-return]
252
+
190
253
  def get_by_identifiers(
191
254
  self,
192
255
  values: Sequence[str | uuid.UUID],
@@ -305,8 +368,11 @@ class DisplayIDManager(models.Manager[M]):
305
368
  objects = DisplayIDManager()
306
369
  """
307
370
 
308
- def get_queryset(self) -> DisplayIDQuerySet[M]:
309
- return DisplayIDQuerySet(self.model, using=self._db)
371
+ _queryset_class = DisplayIDQuerySet
372
+
373
+ if TYPE_CHECKING:
374
+
375
+ def get_queryset(self) -> DisplayIDQuerySet[M]: ...
310
376
 
311
377
  def get_by_display_id(
312
378
  self,
@@ -335,6 +401,21 @@ class DisplayIDManager(models.Manager[M]):
335
401
  value, strategies=strategies, prefix=prefix
336
402
  )
337
403
 
404
+ def resolve_identifier(
405
+ self,
406
+ value: str | uuid.UUID,
407
+ *,
408
+ strategies: tuple[StrategyName, ...] | None = None,
409
+ prefix: str | None = None,
410
+ ) -> uuid.UUID:
411
+ """Resolve an identifier to a UUID without fetching the object.
412
+
413
+ See DisplayIDQuerySet.resolve_identifier for details.
414
+ """
415
+ return self.get_queryset().resolve_identifier(
416
+ value, strategies=strategies, prefix=prefix
417
+ )
418
+
338
419
  def get_by_identifiers(
339
420
  self,
340
421
  values: Sequence[str | uuid.UUID],