implemented general file upload
This commit is contained in:
parent
7ca60e0353
commit
89fb12f72f
7 changed files with 231 additions and 11 deletions
|
@ -14,3 +14,8 @@ class PageForm(forms.ModelForm):
|
|||
"body": MarkItUpWidget(),
|
||||
"path": forms.HiddenInput(),
|
||||
}
|
||||
|
||||
|
||||
class FileUploadForm(forms.Form):
|
||||
|
||||
file = forms.FileField()
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import datetime
|
||||
import os
|
||||
import re
|
||||
from datetime import datetime
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import models
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
@ -26,9 +28,9 @@ class Page(models.Model):
|
|||
path = models.CharField(max_length=100, unique=True)
|
||||
body = MarkupField()
|
||||
status = models.IntegerField(choices=STATUS_CHOICES, default=2)
|
||||
publish_date = models.DateTimeField(default=datetime.now)
|
||||
created = models.DateTimeField(editable=False, default=datetime.now)
|
||||
updated = models.DateTimeField(editable=False, default=datetime.now)
|
||||
publish_date = models.DateTimeField(default=datetime.datetime.now)
|
||||
created = models.DateTimeField(editable=False, default=datetime.datetime.now)
|
||||
updated = models.DateTimeField(editable=False, default=datetime.datetime.now)
|
||||
tags = TaggableManager(blank=True)
|
||||
|
||||
published = PublishedPageManager()
|
||||
|
@ -41,13 +43,26 @@ class Page(models.Model):
|
|||
return ("cms_page", [self.path])
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
self.updated = datetime.now()
|
||||
self.updated = datetime.datetime.now()
|
||||
super(Page, self).save(*args, **kwargs)
|
||||
|
||||
def clean_fields(self, exclude=None):
|
||||
super(Page, self).clean_fields(exclude)
|
||||
if not re.match(settings.SYMPOSION_PAGE_REGEX, self.path):
|
||||
raise ValidationError({"path": [_("Path can only contain letters, numbers and hyphens and end with /"),]})
|
||||
raise ValidationError({"path": [_("Path can only contain letters, numbers and hyphens and end with /")]})
|
||||
|
||||
|
||||
reversion.register(Page)
|
||||
|
||||
|
||||
def generate_filename(instance, filename):
|
||||
return filename
|
||||
|
||||
|
||||
class File(models.Model):
|
||||
|
||||
file = models.FileField(upload_to=generate_filename)
|
||||
created = models.DateTimeField(default=datetime.datetime.now)
|
||||
|
||||
def download_url(self):
|
||||
return reverse("file_download", args=[self.pk, os.path.basename(self.file.name).lower()])
|
||||
|
|
|
@ -3,6 +3,10 @@ from django.conf.urls.defaults import url, patterns
|
|||
PAGE_RE = r"(([\w-]{1,})(/[\w-]{1,})*)/"
|
||||
|
||||
urlpatterns = patterns("symposion.cms.views",
|
||||
url(r"^files/$", "file_index", name="file_index"),
|
||||
url(r"^files/create/$", "file_create", name="file_create"),
|
||||
url(r"^files/(\d+)/([^/]+)$", "file_download", name="file_download"),
|
||||
url(r"^files/(\d+)/delete/$", "file_delete", name="file_delete"),
|
||||
url(r"^(?P<path>%s)_edit/$" % PAGE_RE, "page_edit", name="cms_page_edit"),
|
||||
url(r"^(?P<path>%s)$" % PAGE_RE, "page", name="cms_page"),
|
||||
)
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
from django.http import Http404
|
||||
from django.shortcuts import render, redirect
|
||||
from django.template import RequestContext
|
||||
from django.conf import settings
|
||||
from django.db import transaction
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import render, redirect, get_object_or_404
|
||||
from django.views import static
|
||||
|
||||
from .models import Page
|
||||
from .forms import PageForm
|
||||
from .models import Page, File
|
||||
from .forms import PageForm, FileUploadForm
|
||||
|
||||
|
||||
def can_edit(user):
|
||||
|
@ -14,6 +16,12 @@ def can_edit(user):
|
|||
return False
|
||||
|
||||
|
||||
def can_upload(user):
|
||||
if user.is_staff or user.is_superuser:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def page(request, path):
|
||||
|
||||
editable = can_edit(request.user)
|
||||
|
@ -57,3 +65,61 @@ def page_edit(request, path):
|
|||
"path": path,
|
||||
"form": form
|
||||
})
|
||||
|
||||
|
||||
def file_index(request):
|
||||
if not can_upload(request.user):
|
||||
raise Http404
|
||||
|
||||
ctx = {
|
||||
"files": File.objects.all(),
|
||||
}
|
||||
return render(request, "cms/file_index.html", ctx)
|
||||
|
||||
|
||||
def file_create(request):
|
||||
if not can_upload(request.user):
|
||||
raise Http404
|
||||
|
||||
if request.method == "POST":
|
||||
form = FileUploadForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
with transaction.commit_on_success():
|
||||
kwargs = {
|
||||
"file": form.cleaned_data["file"],
|
||||
}
|
||||
File.objects.create(**kwargs)
|
||||
return redirect("file_index")
|
||||
else:
|
||||
form = FileUploadForm()
|
||||
|
||||
ctx = {
|
||||
"form": form,
|
||||
}
|
||||
return render(request, "cms/file_create.html", ctx)
|
||||
|
||||
|
||||
def file_download(request, pk, *args):
|
||||
file = get_object_or_404(File, pk=pk)
|
||||
|
||||
if getattr(settings, "USE_X_ACCEL_REDIRECT", False):
|
||||
response = HttpResponse()
|
||||
response["X-Accel-Redirect"] = file.file.url
|
||||
# delete content-type to allow Gondor to determine the filetype and
|
||||
# we definitely don't want Django's default :-)
|
||||
del response["content-type"]
|
||||
else:
|
||||
response = static.serve(request, file.file.name, document_root=settings.MEDIA_ROOT)
|
||||
|
||||
return response
|
||||
|
||||
|
||||
def file_delete(request, pk):
|
||||
if not can_upload(request.user):
|
||||
raise Http404
|
||||
|
||||
file = get_object_or_404(File, pk=pk)
|
||||
if request.method == "POST":
|
||||
file.delete()
|
||||
# @@@ message
|
||||
return redirect("file_index")
|
||||
|
|
20
symposion/templates/cms/file_create.html
Normal file
20
symposion/templates/cms/file_create.html
Normal file
|
@ -0,0 +1,20 @@
|
|||
{% extends "site_base.html" %}
|
||||
|
||||
{% load bootstrap_tags %}
|
||||
|
||||
{% block head_title %}Upload File{% endblock %}
|
||||
|
||||
{% block body_outer %}
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<h1>Upload File</h1>
|
||||
<form method="POST" action="{% url file_create %}" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{{ form|as_bootstrap }}
|
||||
<div class="form-actions">
|
||||
<button class="btn btn-primary" type="submit">Upload</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
30
symposion/templates/cms/file_index.html
Normal file
30
symposion/templates/cms/file_index.html
Normal file
|
@ -0,0 +1,30 @@
|
|||
{% extends "site_base.html" %}
|
||||
|
||||
{% block head_title %}Uploaded Files{% endblock %}
|
||||
|
||||
{% block body_outer %}
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<h1>Files</h1>
|
||||
|
||||
{% for file in files %}
|
||||
<div style="margin-top: 1em;">
|
||||
<form class="pull-right" action="{% url file_delete file.pk %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-error"><i class="icon-trash"></i> delete</button>
|
||||
</form>
|
||||
<h3><a href="{{ file.download_url }}">{{ file.file }}</a></h3>
|
||||
<span style="font-style:italic; color: #999;">Uploaded {{ file.created|date:"N j, Y" }}</span>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p>No uploaded files.</p>
|
||||
{% endfor %}
|
||||
<div style="margin-top: 2em">
|
||||
<a class="btn btn-success" href="{% url file_create %}">
|
||||
<i class="icon-plus icon-white"></i>
|
||||
Add File
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
80
symposion/templates/reviews/review_review.html
Normal file
80
symposion/templates/reviews/review_review.html
Normal file
|
@ -0,0 +1,80 @@
|
|||
{% extends "site_base.html" %}
|
||||
|
||||
{% load markitup_tags %}
|
||||
{% load uni_form_tags %}
|
||||
|
||||
{% block body_class %}review{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Proposal Review</h1>
|
||||
|
||||
<div class="proposal">
|
||||
<h2>{{ proposal.title }}</h2>
|
||||
|
||||
<p>
|
||||
{% if proposal.cancelled %}
|
||||
Cancelled
|
||||
{% endif %}
|
||||
</p>
|
||||
|
||||
<div>
|
||||
{{ proposal.description }}
|
||||
</div>
|
||||
|
||||
<p><b>Type</b>: {{ proposal.get_session_type_display }}</p>
|
||||
|
||||
<h3>Abstract</h3>
|
||||
<div class="abstract">
|
||||
{{ proposal.abstract_html|safe }}
|
||||
</div>
|
||||
|
||||
<p><b>Audience level</b>: {{ proposal.get_audience_level_display }}</p>
|
||||
|
||||
<p><b>Submitting speaker</b>: {{ proposal.speaker }}</p> {# @@@ bio? #}
|
||||
|
||||
{% if proposal.additional_speakers.all %}
|
||||
<p><b>Additional speakers</b>:</p>
|
||||
<ul>
|
||||
{% for speaker in proposal.additional_speakers.all %}
|
||||
{% if speaker.user %}
|
||||
<li><b>{{ speaker.name }}</b> — {{ speaker.email }}</li>
|
||||
{% else %}
|
||||
<li>{{ speaker.email }} — pending invitation</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
|
||||
<h3>Additional Notes (private from submitter)</h3>
|
||||
<div class="additional_notes">
|
||||
{{ proposal.additional_notes }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% markitup_media %}
|
||||
|
||||
<h2>Review</h2>
|
||||
|
||||
<form method="POST" action="{% url review_review proposal.pk %}" class="uniForm">
|
||||
{% csrf_token %}
|
||||
<fieldset class="inlineLabels">
|
||||
{{ review_form|as_uni_form }}
|
||||
<div class="form_block">
|
||||
<input type="submit" value="Submit" />
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<h2>Comment</h2>
|
||||
|
||||
<form method="POST" action="{% url review_comment proposal.pk %}" class="uniForm">
|
||||
{% csrf_token %}
|
||||
<fieldset>
|
||||
{{ comment_form|as_uni_form }}
|
||||
<div class="form_block">
|
||||
<input type="submit" value="Submit" />
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
Loading…
Reference in a new issue