converters.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import functools
  2. import uuid
  3. import warnings
  4. from django.utils.deprecation import RemovedInDjango60Warning
  5. class IntConverter:
  6. regex = "[0-9]+"
  7. def to_python(self, value):
  8. return int(value)
  9. def to_url(self, value):
  10. return str(value)
  11. class StringConverter:
  12. regex = "[^/]+"
  13. def to_python(self, value):
  14. return value
  15. def to_url(self, value):
  16. return value
  17. class UUIDConverter:
  18. regex = "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
  19. def to_python(self, value):
  20. return uuid.UUID(value)
  21. def to_url(self, value):
  22. return str(value)
  23. class SlugConverter(StringConverter):
  24. regex = "[-a-zA-Z0-9_]+"
  25. class PathConverter(StringConverter):
  26. regex = ".+"
  27. DEFAULT_CONVERTERS = {
  28. "int": IntConverter(),
  29. "path": PathConverter(),
  30. "slug": SlugConverter(),
  31. "str": StringConverter(),
  32. "uuid": UUIDConverter(),
  33. }
  34. REGISTERED_CONVERTERS = {}
  35. def register_converter(converter, type_name):
  36. if type_name in REGISTERED_CONVERTERS or type_name in DEFAULT_CONVERTERS:
  37. # RemovedInDjango60Warning: when the deprecation ends, replace with
  38. # raise ValueError(f"Converter {type_name} is already registered.")
  39. warnings.warn(
  40. f"Converter {type_name!r} is already registered. Support for overriding "
  41. "registered converters is deprecated and will be removed in Django 6.0.",
  42. RemovedInDjango60Warning,
  43. stacklevel=2,
  44. )
  45. REGISTERED_CONVERTERS[type_name] = converter()
  46. get_converters.cache_clear()
  47. from django.urls.resolvers import _route_to_regex
  48. _route_to_regex.cache_clear()
  49. @functools.cache
  50. def get_converters():
  51. return {**DEFAULT_CONVERTERS, **REGISTERED_CONVERTERS}