I'm building an blog system, which allow user add image to their blog.
when user add image, the image will be upload automatically, this happened before the blog is posted, so how should I handle the uploaded image, these image is kind of like temporary image, because if the user post the blog, these images will have an foreign key to this blog , and saved into some folder,but if the user discard the blog , these temporary images should be deleted.
the problem is how to get the firstly uploaded images,when the blog is actually posted? where should I store these temporary images? and how can I tell if the user discard the blog?
I would suggest the following:
Hope it helps.
Are you using the django.contrib.auth
module to log users in and out? This has a middleware component that appends the current User
object to the request
parameter and works reasonably well with Ajax. It also provides redirects to log in pages if a user isn't currently logged in. More info here. A possible solution:
views.py:
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.utils import simplejson
from django.contrib.auth.decorators import login_required
from filetransfers.api import prepare_upload, serve_file
from blog.models import BlogEntry
from blog.forms import BlogEntryForm
@login_required
def createBlogEntry(request):
return render_to_response('blogEdit.html', { 'form' : BlogEntryForm() })
@login_required
def uploadImage(request):
if request.method == 'POST':
form = BlogEntryForm(request.POST, request.FILES)
if form.is_valid():
newEntry = BlogEntry()
newEntry = request.FILES['blogImage']
newEntry.image = request.FILES['file'].name
newEntry.user = request.user
# delete unsaved previous blog post
try:
oldEntry = BlogEntry.objects.get(user=request.user,completed=False)
oldEntry.delete()
except:
pass
newEntry.save()
return HttpResponse(simplejson.dumps({'imageLocation' : '/static/media/blogImgs/%s' % request.FILES['image'].name }), mimetype='application/javascript')
return HttpResponse(simplejson.dumps({"error" : 101, "message" : "Big error!"}}), mimetype="application/json")
@login_required
def uploadText(request):
if request.method == 'POST':
if form.is_valid():
newEntry = BlogEntry()
try:
newEntry = BlogEntry.objects.get(user=request.user,completed=False)
except:
pass
newEntry.blogText = request.POST['blogText']
newEntry.completed = True
newEntry.save()
return HttpResponse(simplejson.dumps({'result' : 'success'});
return HttpResponse(simplejson.dumps({"error" : 102, "message" : "other Big error!"}}), mimetype="application/json")
The first method will display the page and form to create the blog entry and the others handle the 2 ajax calls for uploading the image and text. After the image has been uploaded the temporary BlogEntry
is stored, if a previous entry has not been completed it is deleted now. When the text is uploaded the temporary blog entry is completed and saved.
It would be possible to have multiple temporary blog entries (for multiple tab in the browser - like this site), with perhaps a maximum number of items set. If the django.auth.contrib
package is not being used it should be possible to use the session middleware instead - there are quite a few options here.
A sketch of the rest of the files:
models.py:
from django.db import models
from django.contrib.auth.models import User
class blogEntry(models.Model):
user = models.ForeignKey(User)
created = models.DateField(auto_now_add = True)
completed = models.BooleanField(default = False)
blogText = models.TextField()
image = models.ImageField(upload_to = 'blogImgs/')
def delete(self, *args, **kwargs):
# Delete image file also
storage, path = self.image.storage, self.image.path
super(ImageModel, self).delete(*args, **kwargs)
storage.delete(path)
The delete method has been overridden to delete the image file after the entry file has been removed.
template: blogEdit.html
<html><head><title>New Blog Entry</title></head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.fileupload/8.9.0/js/jquery.fileupload.js"></script>
<style type="text/css">
form { float: left; }
#textForm {
width: 320px;
padding: 8px;
}
#textForm textarea {
width: 320px;
height: 150px;
margin-bottom: 8px;
}
#imageForm {
width: 100px;
padding-top: 8px;
}
#blogImage {
width: 120px;
height: 120px;
}
#imageForm input[type=file] {
margin: 8px 0 8px 0;
}
</style>
</head>
<body>
<form id="textForm">{% csrf_token %}
<textarea id="blogText" name="blogText"></textarea>
<input type="button" value="upload text" id="textUpload"/>
<img id="blogImage" src="/static/imgs/holdingImage.png" />
<input id="fileupload" type="file" name="blogImage">
</form>
<script>
$(function () {
$('#fileupload').fileupload({
url: '/ajax/uploadImage/',
dataType: 'json',
done: function (e, data) {
blogImage.attr('src', data.result.imageLocation)
}
});
});
$('#textUpload').click(function() {
$.ajax({
url: '/ajax/uploadText/',
dataType: 'json',
data: $('#blogText').val(),
done: function(e, data) {
if(data.result == 'success') {
// display message / redraw edit area with complete blog, etc..
} else if(data.error) {
// error handing code
}
}
});
});
</script>
</body>
</html>
This uses jquery-file-upload to upload the files.
There can be some issues with using Ajax and Django csrf protection see here. It may be required to copy the csrf token into the ajax call, see here. The Ajax done callback for the jquery-file-upload will load the uploaded image into the page, replacing the holding image.
forms.py
from django import forms
class BlogEntryForm(forms.Form):
blogImage = forms.FileField()
blogText = forms.TextField()
urls.py
from django.conf.urls import patterns, include, url
import blog.views
urlpatterns = patterns('',
url(r'^createEntry/$', 'blog.views.createBlogEntry', name='createBlogEntry'),
url(r'^ajax/uploadImage/', 'blog.views.uploadImage'),
url(r'^ajax/uploadText/', 'blog.views.uploadText'),
...additional urls for django.contrib.auth
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With