Как добавить изображение в пост в django
Я создаю систему блогов, которая позволяет пользователям добавлять изображения в свой блог.
Когда пользователь добавляет изображение, оно будет загружено автоматически, это произошло до того, как блог был опубликован, поэтому, как я должен обрабатывать загруженное изображение, это как временное изображение, потому что если пользователь публикует блог, эти изображения будут иметь внешний ключ к этому блогу, и сохраненный в некоторой папке, но если пользователь отклоняет блог, эти временные изображения должны быть удалены.
проблема в том, как получить первые загруженные изображения, когда блог действительно размещен? где я должен хранить эти временные изображения? и как я могу сказать, если пользователь отказывается от блога?
2 ответа
Я бы предложил следующее:
- Измените модель Post, чтобы добавить поле даты и времени, называемое опубликованным, что позволяет использовать NULL.
- Используйте поле опубликовано, чтобы определить, опубликовано сообщение еще или нет. Сообщение будет считаться черновиком, если опубликованное поле имеет значение NULL, в противном случае будет опубликовано.
- Создайте сообщение, как только вы нажмете кнопку "Создать сообщение". Это даст вам объект Post с идентификатором, который вы можете привязать к ModelForm и отобразить пользователю для редактирования. Поэтому, когда они добавляют изображение, вы можете загрузить его и связать с идентификатором сообщения любым удобным для вас способом.
- Измените опубликованное на datetime.now(), только когда вы нажмете кнопку публикации.
- Удаление опубликованного или черновика сообщения должно удалить все связанные ресурсы, такие как изображения.
Надеюсь, поможет.
Вы используете django.contrib.auth
модуль для входа и выхода пользователей? Это компонент промежуточного программного обеспечения, который добавляет текущий User
возражать против request
параметр и работает достаточно хорошо с Ajax. Он также предоставляет перенаправления для входа на страницы, если пользователь не вошел в систему. Подробнее здесь. Возможное решение:
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")
Первый метод отображает страницу и форму для создания записи в блоге, а другой обрабатывает 2 вызова ajax для загрузки изображения и текста. После того, как изображение было загружено временное BlogEntry
сохраняется, если предыдущая запись не была завершена, она удаляется сейчас. Когда текст загружен, временная запись в блоге завершается и сохраняется.
Было бы возможно иметь несколько временных записей в блоге (для нескольких вкладок в браузере - как этот сайт), возможно, с максимальным количеством установленных элементов. Если django.auth.contrib
пакет не используется, вместо него должно быть возможно использовать промежуточное программное обеспечение сеанса - здесь довольно много вариантов.
Эскиз остальных файлов:
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)
Метод delete был переопределен для удаления файла изображения после удаления файла ввода.
шаблон: 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>
Это использует jquery-file-upload для загрузки файлов.
Там могут быть некоторые проблемы с использованием защиты Ajax и Django CSRF см. Здесь. Может потребоваться скопировать токен csrf в вызов ajax, см. Здесь. Ajax done callback для jquery-file-upload загрузит загруженное изображение на страницу, заменив удерживающее изображение.
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
);