diff options
author | Matthew Lemon <y@yulqen.org> | 2024-05-14 13:59:52 +0100 |
---|---|---|
committer | Matthew Lemon <y@yulqen.org> | 2024-05-14 13:59:52 +0100 |
commit | ced16ee9dc3bf1790c0345e874dc7861e27c99ca (patch) | |
tree | 17cc73c5232b1043d241736c4728904b0fb8f9ed | |
parent | 46f11648d902b22a177b878e35d6049a7a127ce7 (diff) |
Adds crispy forms helper
-rw-r--r-- | pyblackbird_cc/resources/forms.py | 47 | ||||
-rw-r--r-- | pyblackbird_cc/templates/resources/resource_create.html | 21 | ||||
-rw-r--r-- | pyblackbird_cc/templates/resources/resource_detail.html | 40 | ||||
-rw-r--r-- | pyproject.toml | 127 |
4 files changed, 137 insertions, 98 deletions
diff --git a/pyblackbird_cc/resources/forms.py b/pyblackbird_cc/resources/forms.py index c3b938d..9645a82 100644 --- a/pyblackbird_cc/resources/forms.py +++ b/pyblackbird_cc/resources/forms.py @@ -1,6 +1,8 @@ import logging import magic +from crispy_forms.helper import FormHelper +from crispy_forms.layout import Submit from django import forms from .models import ResourceCategory @@ -8,19 +10,43 @@ from .models import ResourceType logger = logging.getLogger(__name__) +ALLOWED_THUMBNAILS = 5 +ALLOWED_PDFS = 20 + class ResourceCreateForm(forms.Form): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.helper = FormHelper(self) + self.helper.add_input(Submit("submit", "Submit")) + error_css_class = "error" required_css_class = "required" name = forms.CharField( max_length=255, - help_text="Concisely describe what the resource is, aiming for 35-45 characters. eg: ‘Fractions KS2 Worksheet and Answers.'", + help_text="Concisely describe what the resource is, aiming for" + "35-45 characters. " + "eg: 'Fractions KS2 Worksheet and Answers.'", ) description = forms.CharField( max_length=1000, widget=forms.Textarea, - help_text="This is your opportunity to clearly explain what your resource is all about! It’s worth remembering that you are using the space to communicate to two different audiences. Firstly, think about what fellow teachers would like to know, such as exactly what the resource contains and how it could be used in the classroom. Secondly, the words you include on this page are also talking to internal and external search engines. External search engines, like Google, show the first 155 characters of the resource description, so make sure you take advantage of these characters by using lots of relevant keywords as part of an enticing pitch.", + help_text="This is your opportunity to clearly explain what your resource " + "is all " + "about! It’s worth remembering that you are using the space to " + "communicate to two " + "different audiences. Firstly, think about what fellow teachers " + "would like " + "to know, such as exactly what the resource contains and how it " + "could be used in the classroom. Secondly, the words you include " + "on this page are also talking to internal and external search " + "engines." + " External search engines, like Google, show the first 155 characters " + "of the resource description, so make sure you take advantage " + "of these " + "characters by using lots of relevant keywords as part of an " + "enticing pitch.", ) resource_type = forms.ModelChoiceField(queryset=ResourceType.objects.all()) age_range = forms.ChoiceField( @@ -33,7 +59,8 @@ class ResourceCreateForm(forms.Form): ("16+", "16+"), ("Age not applicable", "Age not applicable"), ], - help_text="Try to be accurate in your choice of age range so that your resource shows up in the correct searches. (Although we don't have searches yet!)", + help_text="Try to be accurate in your choice of age range so that your resource " + "shows up in the correct searches. (Although we don't have searches yet!)", ) curriculum = forms.ChoiceField( choices=[ @@ -44,7 +71,9 @@ class ResourceCreateForm(forms.Form): ) main_resource_category = forms.ModelChoiceField( queryset=ResourceCategory.objects.all(), - help_text="Categorise your resource by subject so it shows up in the correct searches. It's a good idea to limit the number of subjects you select to one or two to make your resource easier to find.", + help_text="Categorise your resource by subject so it shows up in the correct " + "searches. It's a good idea to limit the number of subjects you select " + "to one or two to make your resource easier to find.", ) additional_resource_category = forms.ModelChoiceField( queryset=ResourceCategory.objects.all(), @@ -72,7 +101,11 @@ class ResourceCreateForm(forms.Form): ), required=False, label="Cover images", - help_text="Your cover image will be displayed in the search results and as the first image on your resource page in the preview function. It is important to add an eye catching cover image that gives other teachers an idea about what your resource contains. You can multi-select up to 5 .png or .jpg files here.", + help_text="Your cover image will be displayed in the search results and as " + "the first image on your resource page in the preview function. " + "It is important to add an eye catching cover image that gives " + "other teachers an idea about what your resource contains. " + "You can multi-select up to 5 .png or .jpg files here.", ) pdf_files.widget.attrs.update({"class": "file_upload", "accept": ".pdf"}) thumbnail_files.widget.attrs.update({"class": "file_upload", "accept": ".png,.jpg"}) @@ -87,7 +120,7 @@ class ResourceCreateForm(forms.Form): f.file.seek(0) if content_type not in acceptable: raise forms.ValidationError("Please select only PNG or JPG files.") - if len(thumbnail_files) > 5: + if len(thumbnail_files) > ALLOWED_THUMBNAILS: raise forms.ValidationError("Please select up to 5 files.") return thumbnail_files @@ -101,6 +134,6 @@ class ResourceCreateForm(forms.Form): f.file.seek(0) if content_type not in acceptable: raise forms.ValidationError("Please select only PDF files.") - if len(pdf_files) > 20: + if len(pdf_files) > ALLOWED_PDFS: raise forms.ValidationError("Please select up to 20 PDF files.") return pdf_files diff --git a/pyblackbird_cc/templates/resources/resource_create.html b/pyblackbird_cc/templates/resources/resource_create.html index 03a192a..c10e7b8 100644 --- a/pyblackbird_cc/templates/resources/resource_create.html +++ b/pyblackbird_cc/templates/resources/resource_create.html @@ -8,14 +8,17 @@ {# {% endblock %}#} {% block content %} <div class="container"> - <h2>Upload a new resource</h2> - <p>{% lorem %}</p> - <form action="{% url 'resources:create_resource' %}" - method="post" - enctype="multipart/form-data"> - {% csrf_token %} - {{ form|crispy }} - <input type="submit" class="btn btn-primary" value="Upload" /> - </form> + <div class="row d-flex justify-content-center"> + <div class="col-md-10 bg-light mt-lg-4"> + <h2>Upload a new resource</h2> + <p>{% lorem %}</p> + <form action="{% url 'resources:create_resource' %}" + method="post" + enctype="multipart/form-data"> + {% csrf_token %} + {% crispy form form.helper %} + </form> + </div> + </div> </div> {% endblock content %} diff --git a/pyblackbird_cc/templates/resources/resource_detail.html b/pyblackbird_cc/templates/resources/resource_detail.html index 61d9265..a52c2c6 100644 --- a/pyblackbird_cc/templates/resources/resource_detail.html +++ b/pyblackbird_cc/templates/resources/resource_detail.html @@ -23,28 +23,28 @@ <h4>{{ snapshot_filename }}</h4> </div> <div> - {% for snapshot_url in snapshot_urls %}<img src="{{ snapshot_url }}" alt="{{ snapshot_filename }}"{% endfor %} </div /> - {% endfor %} - </div> - <div class="resource-description-panel"> - <h3>What's included?</h3> - <div>{{ resource.description }}</div> - <h3>What's it for?</h3> - <div>{% lorem %}</div> - <h3>Resource Details</h3> - <div>{% lorem %}</div> - </div> - <div class="resource-download-panel"> - <h4>Download the resource</h4> - <div> - Click - <button hx-get="/hx-download-btn?rn={{ resource.pdf_filename }}" - hx-target="next #download-reveal">here</button> - to download the resource + {% for snapshot_url in snapshot_urls %}<img src="{{ snapshot_url }}" alt="{{ snapshot_filename }}" />{% endfor %} + <div class="resource-description-panel"> + <h3>What's included?</h3> + <div>{{ resource.description }}</div> + <h3>What's it for?</h3> + <div>{% lorem %}</div> + <h3>Resource Details</h3> + <div>{% lorem %}</div> + </div> + <div class="resource-download-panel"> + <h4>Download the resource</h4> + <div> + Click + <button hx-get="/hx-download-btn?rn={{ resource.pdf_filename }}" + hx-target="next #download-reveal">here</button> + to download the resource + </div> + <div id="download-reveal"></div> </div> - <div id="download-reveal"></div> </div> </div> - </div> + {% endfor %} <div>Logged in as {{ request.user.username }}</div> {% endblock content %} +</div> diff --git a/pyproject.toml b/pyproject.toml index eba190f..258cdbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -80,75 +80,78 @@ exclude = [ "staticfiles/*" ] # Same as Django: https://github.com/cookiecutter/cookiecutter-django/issues/4792. -line-length = 88 +line-length = 98 indent-width = 4 target-version = "py312" [tool.ruff.lint] select = [ - "F", - "E", - "W", - "C90", - "I", - "N", - "UP", - "YTT", - # "ANN", # flake8-annotations: we should support this in the future but 100+ errors atm - "ASYNC", - "S", - "BLE", - "FBT", - "B", - "A", - "COM", - "C4", - "DTZ", - "T10", - "DJ", - "EM", - "EXE", - "FA", - 'ISC', - "ICN", - "G", - 'INP', - 'PIE', - "T20", - 'PYI', - 'PT', - "Q", - "RSE", - "RET", - "SLF", - "SLOT", - "SIM", - "TID", - "TCH", - "INT", - # "ARG", # Unused function argument - "PTH", - "ERA", - "PD", - "PGH", - "PL", - "TRY", - "FLY", - # "NPY", - # "AIR", - "PERF", - # "FURB", - # "LOG", - "RUF" + "F", + "E", + "W", + "C90", + "I", + "N", + "UP", + "YTT", + # "ANN", # flake8-annotations: we should support this in the future but 100+ errors atm + "ASYNC", + "S", + "BLE", + "FBT", + "B", + "A", + "COM", + "C4", + "DTZ", + "T10", + "DJ", + "EM", + "EXE", + "FA", + 'ISC', + "ICN", + "G", + 'INP', + 'PIE', + "T20", + 'PYI', + 'PT', + "Q", + "RSE", + "RET", + "SLF", + "SLOT", + "SIM", + "TID", + "TCH", + "INT", + # "ARG", # Unused function argument + "PTH", + "ERA", + "PD", + "PGH", + "PL", + "TRY", + "FLY", + # "NPY", + # "AIR", + "PERF", + # "FURB", + # "LOG", + "RUF" ] ignore = [ - "S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/ - "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` - "SIM102", # sometimes it's better to nest - "UP038" # Checks for uses of isinstance/issubclass that take a tuple - # of types for comparison. - # Deactivated because it can make the code slow: - # https://github.com/astral-sh/ruff/issues/7871 + "TRY003", + "RUF001", + "EM101", + "S101", # Use of assert detected https://docs.astral.sh/ruff/rules/assert/ + "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "SIM102", # sometimes it's better to nest + "UP038" # Checks for uses of isinstance/issubclass that take a tuple + # of types for comparison. + # Deactivated because it can make the code slow: + # https://github.com/astral-sh/ruff/issues/7871 ] # Allow fix for all enabled rules (when `--fix`) is provided. fixable = ["ALL"] |