Для одного моего проекта потребовалось добавить в модель поле с кодом цветом. Заказчик не имел ни малейшего желания вникать в тонкости #RRGGBB
. Поэтому я решил сделать всё просто.
Скачал Farbtastic - JS плагин для jQuery.
Поле в модели уже было:
color = models.CharField(verbose_name=_(u'Color'), max_length=7,
help_text=_(u'HEX color, as #RRGGBB'))
Осталось заставить его использовать скачанный плагин.
Для этого мы воспользуемся возможностью указать для поля виджет. Наш виджет наследуется от стандартного forms.widgets.TextInput
. В подклассе Media
прописываем пути до ресурсов плагина. Самое вкусное находится в методе render
.
Как видно из кода, к стандартному выводу родительского класса мы добавляем ссылку, указывая ей соответствующий идентификатор. По данному идентификатору происходит поиск этой ссылки и добавление к ней обработчика onclick
.
# widgets.py
class ColorPickerWidget(forms.widgets.TextInput):
class Media:
css = {
'all': ('/static/farbtastic/farbtastic.css',)
}
js = ('/static/farbtastic/colorpicker.js',
'/static/farbtastic/farbtastic.js',)
def render(self, name, value, attrs=None):
text_input_html = super(ColorPickerWidget, self).render(name, value, attrs)
text_link_html = u'<a id="id_color_picker" href="#" onclick="return false;">%s</a>' % _(u'Palette')
return mark_safe('%s %s' % (text_input_html, text_link_html))
Для отображения виджета выбора цвета и привязки его появления/сокрытия к нажатию на ссылку, я написал следующий код (обратите внимание, он подключается в коде выше):
// colorpicker.js
var $ = django.jQuery;
var picker_widget = "<div id='colorpicker'></div>";
$(document).ready(function() {
var id_color = $('#id_color');
$(picker_widget).appendTo('body');
$('#id_color_picker').bind('click', function() {
var offset = id_color.offset();
var helper_style = {
'top': offset.top + id_color.height() + 3,
'left': offset.left,
'opacity': 0.9,
};
$('#colorpicker').css(helper_style).toggle(400);
});
$('#colorpicker').hide().farbtastic(id_color);
});
Так как доступ к редактированию данной модели должен быть разрешён только из административного интерфейса Django, надо зарегистрировать модель и обеспечить подмену виджета для поля color
с помощью грязного хака (см. formfield_for_dbfield
):
сlass Room(admin.ModelAdmin):
list_display = ('title', 'color', 'is_active', 'reg_datetime')
ordering = ('title', )
search_fields = ('title',)
fieldsets = ((None, {'fields': ('title', 'color', 'is_active')}),)
def formfield_for_dbfield(self, db_field, **kwargs):
from widgets import ColorPickerWidget
if db_field.name == 'color':
kwargs['widget'] = ColorPickerWidget
return super(Room, self).formfield_for_dbfield(db_field, **kwargs)
admin.site.register(models.Room, Room)
В результате, у модели появится функционал заполнения поля с цветом, понятный практически любому пользователю: