fields.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. from __future__ import unicode_literals
  2. from future.builtins import str
  3. from django.conf import settings
  4. from django.contrib.admin.widgets import AdminTextareaWidget
  5. from django.core.exceptions import ImproperlyConfigured, ValidationError
  6. from django.db import models
  7. from django.forms import MultipleChoiceField
  8. from django.utils.text import capfirst
  9. from django.utils.translation import ugettext_lazy as _
  10. from mezzanine.core.forms import OrderWidget
  11. from mezzanine.utils.importing import import_dotted_path
  12. from mezzanine.utils.html import escape
  13. class OrderField(models.IntegerField):
  14. def formfield(self, **kwargs):
  15. kwargs.update({'widget': OrderWidget,
  16. 'required': False})
  17. return super(OrderField, self).formfield(**kwargs)
  18. class RichTextField(models.TextField):
  19. """
  20. TextField that stores HTML.
  21. """
  22. def formfield(self, **kwargs):
  23. """
  24. Apply the widget class defined by the
  25. ``RICHTEXT_WIDGET_CLASS`` setting.
  26. """
  27. default = kwargs.get("widget", None) or AdminTextareaWidget
  28. if default is AdminTextareaWidget:
  29. from mezzanine.conf import settings
  30. richtext_widget_path = settings.RICHTEXT_WIDGET_CLASS
  31. try:
  32. widget_class = import_dotted_path(richtext_widget_path)
  33. except ImportError:
  34. raise ImproperlyConfigured(_("Could not import the value of "
  35. "settings.RICHTEXT_WIDGET_CLASS: "
  36. "%s" % richtext_widget_path))
  37. kwargs["widget"] = widget_class()
  38. kwargs.setdefault("required", False)
  39. formfield = super(RichTextField, self).formfield(**kwargs)
  40. return formfield
  41. def clean(self, value, model_instance):
  42. """
  43. Remove potentially dangerous HTML tags and attributes.
  44. """
  45. return escape(value)
  46. class MultiChoiceField(models.CharField):
  47. """
  48. Charfield that stores multiple choices selected as a comma
  49. separated string. Based on http://djangosnippets.org/snippets/2753/
  50. """
  51. def formfield(self, *args, **kwargs):
  52. from mezzanine.core.forms import CheckboxSelectMultiple
  53. defaults = {
  54. "required": not self.blank,
  55. "label": capfirst(self.verbose_name),
  56. "help_text": self.help_text,
  57. "choices": self.choices,
  58. "widget": CheckboxSelectMultiple,
  59. "initial": self.get_default() if self.has_default() else None,
  60. }
  61. defaults.update(kwargs)
  62. return MultipleChoiceField(**defaults)
  63. def get_db_prep_value(self, value, connection, **kwargs):
  64. if isinstance(value, (tuple, list)):
  65. value = ",".join([str(i) for i in value])
  66. return value
  67. def from_db_value(self, value, expression, connection, context):
  68. return self.to_python(value)
  69. def to_python(self, value):
  70. if isinstance(value, str):
  71. value = value.split(",")
  72. return value
  73. def validate(self, value, instance):
  74. choices = [str(choice[0]) for choice in self.choices]
  75. if set(value) - set(choices):
  76. error = self.error_messages["invalid_choice"] % {'value': value}
  77. raise ValidationError(error)
  78. def value_to_string(self, obj):
  79. value = self._get_val_from_obj(obj)
  80. return ",".join(value)
  81. # Define a ``FileField`` that maps to filebrowser's ``FileBrowseField``
  82. # if available, falling back to Django's ``FileField`` otherwise.
  83. try:
  84. FileBrowseField = import_dotted_path("%s.fields.FileBrowseField" %
  85. settings.PACKAGE_NAME_FILEBROWSER)
  86. except ImportError:
  87. class FileField(models.FileField):
  88. def __init__(self, *args, **kwargs):
  89. for fb_arg in ("format", "extensions"):
  90. kwargs.pop(fb_arg, None)
  91. super(FileField, self).__init__(*args, **kwargs)
  92. else:
  93. class FileField(FileBrowseField):
  94. def __init__(self, *args, **kwargs):
  95. kwargs.setdefault("directory", kwargs.pop("upload_to", None))
  96. kwargs.setdefault("max_length", 255)
  97. super(FileField, self).__init__(*args, **kwargs)