您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

utils.py 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. from __future__ import absolute_import # for logging import below
  2. import logging
  3. from django.shortcuts import redirect, resolve_url
  4. from django.utils import six
  5. from django.utils.http import is_safe_url
  6. from django.utils.timezone import get_current_timezone, is_naive, make_aware
  7. from django.conf import settings
  8. from django.template.defaultfilters import (date as date_filter,
  9. slugify as django_slugify)
  10. from unidecode import unidecode
  11. from oscar.core.loading import import_string
  12. def default_slugifier(value):
  13. """
  14. Oscar's default slugifier function.
  15. Uses Django's slugify function, but first applies unidecode() to convert
  16. non-ASCII strings to ASCII equivalents where possible.
  17. """
  18. return django_slugify(value)
  19. def slugify(value):
  20. """
  21. Slugify a string (even if it contains non-ASCII chars)
  22. """
  23. # Re-map some strings to avoid important characters being stripped. Eg
  24. # remap 'c++' to 'cpp' otherwise it will become 'c'.
  25. for k, v in settings.OSCAR_SLUG_MAP.items():
  26. value = value.replace(k, v)
  27. # Allow an alternative slugify function to be specified
  28. # Recommended way to specify a function is as a string
  29. slugifier = getattr(settings, 'OSCAR_SLUG_FUNCTION', default_slugifier)
  30. if isinstance(slugifier, six.string_types):
  31. slugifier = import_string(slugifier)
  32. # Use unidecode to convert non-ASCII strings to ASCII equivalents where
  33. # possible.
  34. value = slugifier(unidecode(six.text_type(value)))
  35. # Remove stopwords
  36. for word in settings.OSCAR_SLUG_BLACKLIST:
  37. value = value.replace(word + '-', '')
  38. value = value.replace('-' + word, '')
  39. return value
  40. def compose(*functions):
  41. """
  42. Compose functions
  43. This is useful for combining decorators.
  44. """
  45. def _composed(*args):
  46. for fn in functions:
  47. try:
  48. args = fn(*args)
  49. except TypeError:
  50. # args must be scalar so we don't try to expand it
  51. args = fn(args)
  52. return args
  53. return _composed
  54. def format_datetime(dt, format=None):
  55. """
  56. Takes an instance of datetime, converts it to the current timezone and
  57. formats it as a string. Use this instead of
  58. django.core.templatefilters.date, which expects localtime.
  59. :param format: Common will be settings.DATETIME_FORMAT or
  60. settings.DATE_FORMAT, or the resp. shorthands
  61. ('DATETIME_FORMAT', 'DATE_FORMAT')
  62. """
  63. if is_naive(dt):
  64. localtime = make_aware(dt, get_current_timezone())
  65. logging.warning(
  66. "oscar.core.utils.format_datetime received native datetime")
  67. else:
  68. localtime = dt.astimezone(get_current_timezone())
  69. return date_filter(localtime, format)
  70. def safe_referrer(meta, default):
  71. """
  72. Takes request.META and a default URL. Returns HTTP_REFERER if it's safe
  73. to use and set, and the default URL otherwise.
  74. The default URL can be a model with get_absolute_url defined, a urlname
  75. or a regular URL
  76. """
  77. referrer = meta.get('HTTP_REFERER')
  78. if referrer and is_safe_url(referrer):
  79. return referrer
  80. if default:
  81. # try to resolve
  82. return resolve_url(default)
  83. else:
  84. # Allow passing in '' and None as default
  85. return default
  86. def redirect_to_referrer(meta, default):
  87. """
  88. Takes request.META and a default URL to redirect to.
  89. Returns a HttpResponseRedirect to HTTP_REFERER if it exists and is a safe
  90. URL; to the default URL otherwise.
  91. """
  92. return redirect(safe_referrer(meta, default))