forms.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. from django import forms
  2. from django.utils.html import conditional_escape, mark_safe
  3. from django.utils.translation import gettext, gettext_lazy as _
  4. from mptt.forms import TreeNodeChoiceField
  5. from ...themes.models import Theme
  6. from ..forms import YesNoSwitch
  7. from .assets import create_css, create_image
  8. class ThemeChoiceField(TreeNodeChoiceField):
  9. level_indicator = "- - "
  10. def __init__(self, *args, **kwargs):
  11. kwargs.setdefault("queryset", Theme.objects.all())
  12. kwargs.setdefault("empty_label", _("No parent"))
  13. super().__init__(*args, **kwargs)
  14. class ThemeForm(forms.ModelForm):
  15. name = forms.CharField(label=_("Name"))
  16. parent = ThemeChoiceField(label=_("Parent"), required=False)
  17. version = forms.CharField(label=_("Version"), required=False)
  18. author = forms.CharField(label=_("Author(s)"), required=False)
  19. url = forms.URLField(label=_("Url"), required=False)
  20. class Meta:
  21. model = Theme
  22. fields = ["name", "parent", "version", "author", "url"]
  23. def __init__(self, *args, **kwargs):
  24. super().__init__(*args, **kwargs)
  25. self.limit_parent_choices()
  26. def limit_parent_choices(self):
  27. if not self.instance or not self.instance.pk:
  28. return
  29. self.fields["parent"].queryset = Theme.objects.exclude(
  30. tree_id=self.instance.tree_id,
  31. lft__gte=self.instance.lft,
  32. rght__lte=self.instance.rght,
  33. )
  34. class UploadAssetsForm(forms.Form):
  35. allowed_content_types = []
  36. allowed_extensions = []
  37. assets = forms.FileField(
  38. widget=forms.ClearableFileInput(attrs={"multiple": True}),
  39. error_messages={"required": _("No files have been uploaded.")},
  40. )
  41. def __init__(self, *args, instance=None):
  42. self.instance = instance
  43. super().__init__(*args)
  44. def clean_assets(self):
  45. assets = []
  46. for asset in self.files.getlist("assets"):
  47. try:
  48. if self.allowed_content_types:
  49. self.validate_asset_content_type(asset)
  50. if self.allowed_extensions:
  51. self.validate_asset_extension(asset)
  52. except forms.ValidationError as e:
  53. self.add_error("assets", e)
  54. else:
  55. assets.append(asset)
  56. return assets
  57. def validate_asset_content_type(self, asset):
  58. if asset.content_type in self.allowed_content_types:
  59. return
  60. message = gettext(
  61. 'File "%(file)s" content type "%(content_type)s" is not allowed.'
  62. )
  63. details = {"file": asset.name, "content_type": asset.content_type}
  64. raise forms.ValidationError(message % details)
  65. def validate_asset_extension(self, asset):
  66. filename = asset.name.lower()
  67. for extension in self.allowed_extensions:
  68. if filename.endswith(".%s" % extension):
  69. return
  70. message = gettext('File "%(file)s" extension is invalid.')
  71. details = {"file": asset.name}
  72. raise forms.ValidationError(message % details)
  73. def save(self):
  74. for asset in self.cleaned_data["assets"]:
  75. self.save_asset(asset)
  76. class UploadCssForm(UploadAssetsForm):
  77. allowed_content_types = ["text/css"]
  78. allowed_extensions = ["css"]
  79. def save_asset(self, asset):
  80. create_css(self.instance, asset)
  81. class UploadImagesForm(UploadAssetsForm):
  82. assets = forms.ImageField(widget=forms.ClearableFileInput(attrs={"multiple": True}))
  83. def save_asset(self, asset):
  84. create_image(self.instance, asset)