Как настроить HTML-вывод виджета в Django?
Я не мог найти это в документах, но думаю, что это возможно. Я говорю конкретно о виджете ClearableFileInput. Из проекта в Django 1.2.6 у меня есть такая форма:
# the profile picture upload form
class ProfileImageUploadForm(forms.ModelForm):
"""
simple form for uploading an image. only a filefield is provided
"""
delete = forms.BooleanField(required=False,widget=forms.CheckboxInput())
def save(self):
# some stuff here to check if "delete" is checked
# and then delete the file
# 8 lines
def is_valid(self):
# some more stuff here to make the form valid
# allthough the file input field is empty
# another 8 lines
class Meta:
model = SocialUserProfile
fields = ('image',)
который я затем визуализировал, используя этот код шаблона:
<form action="/profile/edit/" method="post" enctype="multipart/form-data">
Delete your image:
<label> {{ upload_form.delete }} Ok, delete </label>
<button name="delete_image" type="submit" value="Save">Delete Image</button>
Or upload a new image:
{{ upload_form.image }}
<button name="upload_image" type="submit" value="Save">Start Upload</button>
{% csrf_token %}
</form>
поскольку Django 1.3.1 теперь использует ClearableFileInput в качестве виджета по умолчанию, я уверен, что могу пропустить 16 строк моей формы.сохраните и просто сократите код формы следующим образом:
# the profile picture upload form
class ProfileImageUploadForm(forms.ModelForm):
"""
simple form for uploading an image. only a filefield is provided
"""
class Meta:
model = SocialUserProfile
fields = ('image',)
это дало бы мне хорошее чувство, что у меня меньше настроенного formcode, и я могу положиться на встроенные Django.
Я бы, конечно, хотел сохранить html-вывод таким же, как и раньше. Когда просто используйте существующий код шаблона, такие вещи, как " в настоящее время: somefilename.png " всплывают в местах, где я их не хочу.
разделение поля формы дальше, как {{ upload_form.image.file }}
не работает. Следующее, что пришло мне в голову, - написать пользовательский виджет. Что будет работать точно против моего усилия по удалению как можно большего количества настраиваемого кода.
есть идеи, что было бы самым простым в этом сценарии?
1 ответов
во-первых, создать widgets.py
файл в приложении. Например, я сделаю тебе AdminImageWidget
класс, который расширяет AdminFileWidget
. По сути, я хочу поле загрузки изображения, которое показывает загруженное изображение в <img src="" />
тег вместо того, чтобы просто выводить путь к файлу.
поместите следующий класс в свой :
from django.contrib.admin.widgets import AdminFileWidget
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
import os
import Image
class AdminImageWidget(AdminFileWidget):
def render(self, name, value, attrs=None):
output = []
if value and getattr(value, "url", None):
image_url = value.url
file_name=str(value)
# defining the size
size='100x100'
x, y = [int(x) for x in size.split('x')]
try :
# defining the filename and the miniature filename
filehead, filetail = os.path.split(value.path)
basename, format = os.path.splitext(filetail)
miniature = basename + '_' + size + format
filename = value.path
miniature_filename = os.path.join(filehead, miniature)
filehead, filetail = os.path.split(value.url)
miniature_url = filehead + '/' + miniature
# make sure that the thumbnail is a version of the current original sized image
if os.path.exists(miniature_filename) and os.path.getmtime(filename) > os.path.getmtime(miniature_filename):
os.unlink(miniature_filename)
# if the image wasn't already resized, resize it
if not os.path.exists(miniature_filename):
image = Image.open(filename)
image.thumbnail([x, y], Image.ANTIALIAS)
try:
image.save(miniature_filename, image.format, quality=100, optimize=1)
except:
image.save(miniature_filename, image.format, quality=100)
output.append(u' <div><a href="%s" target="_blank"><img src="%s" alt="%s" /></a></div> %s ' % \
(miniature_url, miniature_url, miniature_filename, _('Change:')))
except:
pass
output.append(super(AdminFileWidget, self).render(name, value, attrs))
return mark_safe(u''.join(output))
ок, так что здесь происходит?
- я импортирую существующий виджет (вы можете начать с нуля, но вероятно, вы сможете расширить ClearableFileInput, если это то, с чего вы начинаете)
- я хочу изменить только вывод / представление виджета, а не базовую логику. Итак, я переопределяю виджет .
- в функции рендеринга я строю вывод, который я хочу как массив
output = []
вам не обязательно это делать, но это экономит некоторую конкатенацию. 3 основные направления:-
output.append(u' <div><a href="%s" target="_blank"><img src="%s" alt="%s" /></a></div> %s ' % (miniature_url, miniature_url, miniature_filename, _('Change:')))
добавляет тег img к выходу -
output.append(super(AdminFileWidget, self).render(name, value, attrs))
добавляет вывод родителя в мой виджет -
return mark_safe(u''.join(output))
присоединяется к моему выходному массиву с пустыми строками и освобождает его от экранирования перед отображением
-
как мне это использовать?
class SomeModelForm(forms.ModelForm):
"""Author Form"""
photo = forms.ImageField(
widget = AdminImageWidget()
)
class Meta:
model = SomeModel
или
class SomeModelForm(forms.ModelForm):
"""Author Form"""
class Meta:
model = SomeModel
widgets = {'photo' : AdminImageWidget(),}
что дает нам: