使用Django我正在创建使用标准ImageField上传的图像的缩略图,在通常的图像文件字段旁边的单独字段“缩略图”中添加表格的路径。我正在尝试使用formset访问使用formset在自定义模板中渲染imagefield对象的缩略图路径,以便我可以显示它。
我想我需要在inlineformset_factory中添加一个'form = CarImageForm',然后修改我的forms.py,但是我无法弄清楚如何做到这一点,甚至是否这种方法是正确的。为清楚起见,我没有在下面的代码示例中包含我的尝试。
我的最终目标是返回链接到原始图像的缩略图 - 已经通过Imagefile字段显示。
提前致谢!
模板是:
<form method="post" action="" enctype="multipart/form-data">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset.forms %}
{% for field in form %}
{{ field.label }}: {{ field }}<br>
{% endfor %}
{% endfor %}
<p><input type="submit" value="Enter"/></p>
forms.py:
class CarForm(ModelForm):
class Meta:
model = Car
exclude = ['owner', 'uploaded']
views.py:
# Edit an existing record
@login_required
def edit_existing(request, object_id=False):
try:
car = Car.objects.get(pk=object_id)
except Car.DoesNotExist:
raise Http404
ImageFormSet = inlineformset_factory(Car, CarImage, extra=1, max_num=1)
if request.method == 'POST':
form = forms.CarForm(request.POST, instance=car)
formset = ImageFormSet(request.POST, request.FILES, instance=car)
if formset.is_valid() and form.is_valid():
# Handle form.save() to include user id
new_car = form.save(commit=False)
new_car.owner = request.user
new_car.save()
# Formset - contains the attached images
formset.save()
return HttpResponseRedirect(new_car.get_absolute_url())
else:
form = forms.CarForm(instance=car)
formset = ImageFormSet(instance=car)
return render_to_response('edit_existing.html',
{'form': form, 'formset': formset},
context_instance=RequestContext(request))
models.py:
class Car(models.Model):
make = models.CharField(max_length=64)
model = models.CharField(max_length=64)
owner = models.ForeignKey(User,editable=False)
uploaded = models.DateField(default=datetime.date.today,editable=False)
def get_absolute_url(self):
return reverse('vehicle_admin.views.car_detail', args=[str(self.id)])
def orig_car_id_folder(instance, filename):
return 'uploads/images/orig/{0}/{1}'.format(instance.car_id, filename)
def thumb_car_id_folder(instance, filename):
return 'uploads/images/thumb/{0}/{1}'.format(instance.car_id, filename)
class CarImage(models.Model):
car = models.ForeignKey(Car)
imagefile = models.ImageField(upload_to=orig_car_id_folder)
thumbnail = models.ImageField(upload_to=thumb_car_id_folder, editable=False)
# PIL tips from
# https://snipt.net/danfreak/generate-thumbnails-in-django-with-pil/
# http://www.mechanicalgirl.com/post/image-resizing-file-uploads-doing-it-easy-way/
def save(self):
import os
from PIL import Image
from cStringIO import StringIO
from django.core.files.uploadedfile import SimpleUploadedFile
THUMBNAIL_SIZE = (75, 75)
super(CarImage, self).save() # Use the commit=False param here?
image = Image.open(self.imagefile.path)
if image.mode not in ('L', 'RGB'):
image = image.convert('RGB')
image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS)
temp_handle = StringIO()
image.save(temp_handle, 'png')
temp_handle.seek(0)
name_ext = os.path.splitext(os.path.split(self.imagefile.name)[-1])
suf = SimpleUploadedFile(name_ext[0],
temp_handle.read(), content_type='image/png')
self.thumbnail.save(suf.name+'.png', suf, save=False)
super(CarImage, self).save()
答案 0 :(得分:0)
我认为这是我的基本疏忽。
我的问题是在我的CarImage模型中为缩略图&#39;设置了editable = False。领域。这对于初始数据提交很好,但是在编辑条目时会出现问题,因为该字段会自动排除在表单中。 (有关详细信息,请参阅上面的代码段。)
我的下一步是为我的add_new视图设置一个自定义表单(我最初没有包含此视图,但这是我用来启用数据的初始上传),如下所示:
class InitialCarImageForm(ModelForm):
class Meta:
model = CarImage
exclude = ['thumbnail']
我想正确的方法是使用editable = False,但除非我采用这种方法犯下严重的错误,否则它可能对我有用。
我是该网站的新手,所以如果以这种方式回答我的问题是关闭它的正确方法,请告诉我。
答案 1 :(得分:0)
如果您愿意尝试使用我的django-extra-views库,您可以执行以下操作:
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
from extra_views import UpdateWithInlinesView, InlineFormSet
class CarForm(ModelForm):
def __init__(self, *args, **kwargs):
self.user = self.kwargs.pop('user')
super(CarForm, self).__init__(*args, **kwargs)
def save(self, commit=True)
instance = super(CarForm, self).save(commit=False)
instance.user = self.user
if commit:
instance.save()
return instance
class Meta:
model = Car
exclude = ['owner', 'uploaded']
CarImageInline(InlineFormSet):
model = CarImage
extra = 1
max_num = 1
UpdateCarView(UpdateWithInlinesView):
pk_url_kwarg = 'object_id'
inlines = [CarImageInline]
template_name = 'edit_existing.html'
form_class = CarForm
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(UpdateCarView, self).dispatch(*args, **kwargs)
def get_form_kwargs(self):
kwargs = super(UpdateCarView, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def get_success_url(self):
return self.object.get_absolute_url()
主要差异:
formset
,而是获得inlines
,这是一个表单集列表。这是因为你可以在技术上拥有你想要的尽可能多的内联表单集,即使在这种情况下你只有一个,它实际上与Django管理员的工作方式相同。dispatch
以应用login_required
装饰器是笨重的,幸运的是,它很容易被抽象为mixin,请参阅django-braces以获取一些现成的装饰。