Skip to content
Browse files

Whitespace-only validation of snipppet fields

The fields "title", "description" and "code" of a the snippet model
are required, yet allow the user to enter whitespace-only content.
This leads to some issues esp. with the title field, which is used
as link text in snippet listings.

This change first adds additional validation to these fields by
checking for content that contains only whitespaces. For snippets
affected by this already in the database the listing now checks
for empty strings and renders them as "Untitled".

Additionally the snippet listing in the admin now includes the
snippet's ID as link-element.
  • Loading branch information...
1 parent 329663c commit 59150a5f671f9e529716d38d1801cda29e3be753 @zerok zerok committed
Showing with 39 additions and 8 deletions.
  1. +1 −1 cab/admin.py
  2. +21 −0 cab/forms.py
  3. +4 −4 cab/templates/cab/snippet_list.html
  4. +3 −3 cab/templates/cab/user_detail.html
  5. +10 −0 cab/templatetags/core_tags.py
View
2 cab/admin.py
@@ -8,7 +8,7 @@ class LanguageAdmin(admin.ModelAdmin):
class SnippetAdmin(admin.ModelAdmin):
- list_display = ('title', 'author', 'rating_score', 'pub_date')
+ list_display = ('id', 'title', 'author', 'rating_score', 'pub_date')
list_filter = ('language',)
date_hierarchy = 'pub_date'
search_fields = ('author__username', 'title', 'description', 'code',)
View
21 cab/forms.py
@@ -8,11 +8,32 @@
from registration.forms import RegistrationFormUniqueEmail
+def validate_non_whitespace_only_string(value):
+ """
+ Additionally to requiring a non-empty string, this validator also strips
+ the string to treat strings with only whitespaces in them as empty.
+ """
+ if not value or not value.strip():
+ raise forms.ValidationError(u'This field is required', code='required')
+
+
class SnippetForm(forms.ModelForm):
+ title = forms.CharField(
+ validators=[validate_non_whitespace_only_string])
+ description = forms.CharField(
+ validators=[validate_non_whitespace_only_string],
+ widget=forms.Textarea)
+ code = forms.CharField(
+ validators=[validate_non_whitespace_only_string],
+ widget=forms.Textarea)
+
class Meta:
model = Snippet
exclude = ('author', 'bookmark_count', 'rating_score',)
+ def __init__(self, *args, **kwargs):
+ super(SnippetForm, self).__init__(*args, **kwargs)
+
class SnippetFlagForm(forms.ModelForm):
class Meta:
View
8 cab/templates/cab/snippet_list.html
@@ -1,5 +1,5 @@
{% extends "base.html" %}
-
+{% load core_tags %}
{% block title %}All snippets{% if months %} last {{ months }} months{% endif %}{% endblock %}
{% block content_header %}All snippets{% if months %} last {{ months }} months{% endif %}{% endblock %}
@@ -15,18 +15,18 @@
<ul class="snippet_list">
{% for snippet in object_list %}
<li>
- <a href="{{ snippet.get_absolute_url }}">{{ snippet.title }}</a> by <a href="/users/{{ snippet.author.username }}/">{{ snippet.author.username }}</a>
+ <a href="{{ snippet.get_absolute_url }}">{% if not snippet.title|strip %}Untitled{% else %}{{ snippet.title }}{% endif %}</a> by <a href="/users/{{ snippet.author.username }}/">{{ snippet.author.username }}</a>
<p class="details">{{ snippet.pub_date|timesince }} ago, <span class="rating-{% if snippet.rating_score >= 0 %}positive{% else %}negative{% endif %}">{% if snippet.rating_score >= 0 %}+{% endif %}{{ snippet.rating_score }}</span></p>
</li>
{% endfor %}
</ul>
<p class="pagination">
{% if has_previous %}
- <a href="?page={{ previous }}{% if months %}&months={{ months }}{% endif %}">&lt; Previous {{ results_per_page }}</a>
+ <a href="?page={{ previous }}{% if months %}&amp;months={{ months }}{% endif %}">&lt; Previous {{ results_per_page }}</a>
{% endif %}
&nbsp;&nbsp;
{% if has_next %}
- <a href="?page={{ next }}{% if months %}&months={{ months }}{% endif %}">Next {{ results_per_page }} &gt;</a>
+ <a href="?page={{ next }}{% if months %}&amp;months={{ months }}{% endif %}">Next {{ results_per_page }} &gt;</a>
{% endif %}
</p>
{% else %}
View
6 cab/templates/cab/user_detail.html
@@ -19,18 +19,18 @@
<ul class="snippet_list">
{% for snippet in object_list %}
<li>
- <a href="{{ snippet.get_absolute_url }}">{{ snippet.title }}</a> by <a href="/users/{{ snippet.author.username }}/">{{ snippet.author.username }}</a>
+ <a href="{{ snippet.get_absolute_url }}">{% if not snippet.title|strip %}Untitled{% else %}{{ snippet.title }}{% endif %}</a> by <a href="/users/{{ snippet.author.username }}/">{{ snippet.author.username }}</a>
<p class="details">{{ snippet.pub_date|timesince }} ago, <span class="rating-{% if snippet.rating_score >= 0 %}positive{% else %}negative{% endif %}">{% if snippet.rating_score >= 0 %}+{% endif %}{{ snippet.rating_score }}</span></p>
</li>
{% endfor %}
</ul>
<p class="pagination">
{% if has_previous %}
- <a href="?page={{ previous }}{% if months %}&months={{ months }}{% endif %}">&lt; Previous {{ results_per_page }}</a>
+ <a href="?page={{ previous }}{% if months %}&amp;months={{ months }}{% endif %}">&lt; Previous {{ results_per_page }}</a>
{% endif %}
&nbsp;&nbsp;
{% if has_next %}
- <a href="?page={{ next }}{% if months %}&months={{ months }}{% endif %}">Next {{ results_per_page }} &gt;</a>
+ <a href="?page={{ next }}{% if months %}&amp;months={{ months }}{% endif %}">Next {{ results_per_page }} &gt;</a>
{% endif %}
</p>
{% else %}
View
10 cab/templatetags/core_tags.py
@@ -40,3 +40,13 @@ def call_manager(model_or_obj, method):
manager = model_or_obj._default_manager
return getattr(manager, method)()
+
+
+@register.filter
+def strip(value):
+ """
+ Strips a string.
+ """
+ if value:
+ return value.strip()
+ return value

0 comments on commit 59150a5

Please sign in to comment.
Something went wrong with that request. Please try again.