Permalink
Browse files

Turns out that image uploads were not working at all. Now they do, an…

…d I've cleaned up the delete/edit flow a little bit
  • Loading branch information...
1 parent ea6ad6f commit 777649ded27cab8d175709e86e0e90c5749df54a @rossbruniges rossbruniges committed Dec 5, 2012
@@ -29,6 +29,9 @@ textarea {
border-radius: 8px;
padding: 0.2em 4px;
}
+input[type=file] {
+ display: block;
+}
textarea {
height: 100px;
}
@@ -108,6 +111,17 @@ fieldset.js_enabled .field {
.category_select ul {
margin-bottom: 0;
}
+.thumbnail_row .frame {
+ display: inline-block;
+ width: 100px;
+ margin-right: 20px;
+}
+.thumbnail_row div p {
+ margin-top: 0;
+}
+.thumbnail_row br {
+ clear: left;
+}
.submit_row {
background: #000;
text-align: left;
@@ -1,7 +1,7 @@
from django import forms
from django.forms.models import ModelChoiceField
-from gameon.submissions.widgets import CategorySelectWidget
+from gameon.submissions.widgets import CategorySelectWidget, AdvancedFileInput
from gameon.submissions.models import Entry, Category
@@ -16,7 +16,8 @@
'url': forms.TextInput(attrs={'aria-describedby': 'info_url'}),
'description': forms.Textarea(attrs={'aria-describedby': 'info_description',
'data-maxlength': '1000'}),
- 'video_url': forms.TextInput(attrs={'aria-describedby': 'info_video_url'}),
+ 'thumbnail': AdvancedFileInput(attrs={'aria-describedby': 'info_description'}),
+ 'video_url': forms.TextInput(attrs={'aria-describedby': 'info_description'}),
'team_members': forms.Textarea(attrs={'aria-describedby': 'info_team_members',
'data-maxlength': '250'}),
'team_description': forms.Textarea(attrs={'aria-describedby': 'info_team_description',
@@ -31,6 +32,15 @@ class EntryForm(forms.ModelForm):
empty_label=None,
widget=CategorySelectWidget())
+ def clean_thumbnail(self):
+ # ensure that people can't upload a HUGE file
+ # hopefully we can top and tail this with a LimitRequestBody setting in
+ # apache (http://stackoverflow.com/a/6195637/1308104)
+ thumb = self.cleaned_data.get('thumbnail', False)
+ if thumb and thumb._size > 2 * 1024 * 1024:
+ raise forms.ValidationError("That file is a bit big - please use one under 2mb")
+ return thumb
+
class Meta:
model = Entry
fields = entry_fields
@@ -1,5 +1,4 @@
from datetime import datetime
-import string
import re
from django.db import models
@@ -34,6 +33,7 @@
}
}
+
def url2embed(url):
if not url:
return
@@ -46,6 +46,7 @@ def url2embed(url):
args.update(result.groupdict())
return service['embed'] % args
+
class Challenge(models.Model):
objects = ChallengeManager()
@@ -148,9 +149,7 @@ def get_entry_feature(self):
If there is a video_url we want to include that as a feature, otherwise
we fall through to the thumbnail
"""
-
video_embed = url2embed(self.video_url)
-
if video_embed:
return video_embed
if self.thumbnail:
@@ -14,7 +14,7 @@
<h1 class="busta shout">{% block view_title %}Submit Your Game{% endblock %}</h1>
</header>
<div class="busta">
- <form action="" method="post">
+ <form action="" method="post" enctype="multipart/form-data">
{{ csrf() }}
<div class="form_wrapper">
<fieldset>
@@ -24,7 +24,6 @@ <h1 class="busta shout">{% block view_title %}Submit Your Game{% endblock %}</h1
Game name
{% for error in form.title.errors %}<em>{{ error }}</em>{% endfor %}
</label>
-
{{ form.title }}
</div>
<div class="field">
@@ -43,12 +42,17 @@ <h1 class="busta shout">{% block view_title %}Submit Your Game{% endblock %}</h1
</label>
{{ form.description }}
</div>
- <div class="field">
- <label for="id_thumbnail" class="announce">
- Upload Thumbnail Image <span class="opt">(optional)</span>
- {% for error in form.thumbnail.errors %}<em>{{ error }}</em>{% endfor %}
- </label>
- {{ form.thumbnail }}
+ <div class="field thumbnail_row">
+ <div>
+ <label for="id_thumbnail" class="announce">
+ Upload Thumbnail Image <span class="opt">(optional)</span>
+ {% for error in form.thumbnail.errors %}<em>{{ error }}</em>{% endfor %}
+ <span class="extra meta" id="info_thumbnail">(maximum 2mb file size)</span>
+ </label>
+ </div>
+ <div>
+ {{ form.thumbnail }}
+ </div>
</div>
<div class="field category_select">
<p class="announce">Category <span class="opt">(optional)</span></p>
@@ -19,7 +19,7 @@ def create(request, template='submissions/create.html'):
if not request.challenge.is_open():
return action_unavailable_response(request, case='challenge_closed')
if request.method == 'POST':
- form = NewEntryForm(request.POST)
+ form = NewEntryForm(request.POST, request.FILES)
if form.is_valid():
entry = form.save(commit=False)
entry.created_by = request.user.get_profile()
@@ -51,7 +51,7 @@ def edit_entry(request, slug, template='submissions/edit.html'):
if not request.challenge.is_open():
return action_unavailable_response(request, case='challenge_closed')
if request.method == 'POST':
- form = EntryForm(request.POST, instance=entry)
+ form = EntryForm(request.POST, request.FILES, instance=entry)
if form.is_valid():
entry = form.save(commit=False)
new_slug = slugify(entry.title)
@@ -4,7 +4,55 @@
from gameon.submissions.models import Category
+from django.utils.html import escape, conditional_escape
+from django.forms.widgets import ClearableFileInput, CheckboxInput
+
+# The ClearableFieldWidget is pretty horrible - trying to make it a bit nicer
+class AdvancedFileInput(ClearableFileInput):
+
+ def __init__(self, *args, **kwargs):
+
+ self.url_length = kwargs.pop('url_length', 30)
+ self.preview = kwargs.pop('preview', True)
+ self.image_width = kwargs.pop('image_width', 100)
+ super(AdvancedFileInput, self).__init__(*args, **kwargs)
+
+ def render(self, name, value, attrs=None,):
+
+ substitutions = {
+ 'initial_text': "<p class='meta'>Right now you have</p>",
+ 'input_text': '<span class="meta">Change this</span>',
+ 'clear_template': '',
+ 'clear_checkbox_label': '<span class="meta">Delete this</span>',
+ }
+ template = u'%(input)s'
+
+ substitutions['input'] = super(ClearableFileInput, self).render(name, value, attrs)
+
+ if value and hasattr(value, "url"):
+
+ template = self.template_with_initial
+ if self.preview:
+ substitutions['initial'] = (u'<span class="frame">\
+ <img src="{0}" width="{2}"></span>'.format
+ (escape(value.url), '...' + escape(force_unicode(value))[-self.url_length:],
+ self.image_width))
+ else:
+ substitutions['initial'] = (u'<a href="{0}">{1}</a>'.format
+ (escape(value.url), '...' + escape(force_unicode(value))[-self.url_length:]))
+ if not self.is_required:
+ checkbox_name = self.clear_checkbox_name(name)
+ checkbox_id = self.clear_checkbox_id(checkbox_name)
+ substitutions['clear_checkbox_name'] = conditional_escape(checkbox_name)
+ substitutions['clear_checkbox_id'] = conditional_escape(checkbox_id)
+ substitutions['clear'] = CheckboxInput().render(checkbox_name, False, attrs={'id': checkbox_id})
+ substitutions['clear_template'] = self.template_with_clear % substitutions
+
+ return mark_safe(template % substitutions)
+
+
+# Used to display the category description with each category in a RadioSelect widget
class CategorySelectRenderer(RadioFieldRenderer):
"""Mainly duplicated from django.forms.widgets
A custom widget that allows us to render the standard list of radios with

0 comments on commit 777649d

Please sign in to comment.