Source

django_flatcms / widgets.py

Full commit
#-*- coding: utf-8 -*- 
"""
  flatcms : A simple CMS for Django
  (C)2010 - Apidev - http://www.apidev.fr
  This is distributed under GNU LGPL license, see license.txt

  VerboseManyToManyRawIdWidget by Luc JEAN - see http://djangosnippets.org/snippets/2108/
"""

from django.contrib.admin.widgets import ManyToManyRawIdWidget, AdminFileWidget
from django.forms.widgets import Select
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.conf import settings
from django.db import models
from django.utils.encoding import smart_unicode
from django.utils.translation import ugettext as _
from django.core.urlresolvers import reverse

def render_flatcms_image_links():
    s = u'<a href="{0}" onclick="return showAddAnotherPopup(this);" '\
        u'style="color: black; text-decoration: underline; border: solid thin #777; background: #eee; padding:8px 8px 8px 8px;"'\
        u'>{1}</a>'
    buttons = (
        s.format(reverse('admin:flatcms_image_changelist'),  _('List of images')),
        s.format(reverse('admin:flatcms_image_add'),  _('Add a new image')),
    )
    return mark_safe((u'&nbsp;'*8).join(buttons))

def replace_widget(kwargs, db_field, fields, new_widget):
    '''Replace a widget by another in the adin site'''
    if db_field.name in fields:
        kwargs.pop('request', None)
        kwargs['widget'] = new_widget
        return db_field.formfield(**kwargs)

class AdminImageWidget(AdminFileWidget):
    """subclass the AdminFileWidget in order to display the image"""
    def render(self, name, value, attrs=None):
        output = []
        if value:
            output.append(u'<div>{0}</div>'.format(value))
        output.append(super(AdminFileWidget, self).render(name, value, attrs))
        try:
            if value and getattr(value, "url", None):
                height = min(128, value.height)
                output.append(u'<div><a href="{0}" target="_blank"><img src="{0}" height="{1}px"/></a></div>'.format(
                    value.url, height))
        except Exception, msg:
            output.append(u'<div><a href="{0}" target="_blank">{0}</a> {1}</div>'.format(
                    value.url, msg))
        return mark_safe(u''.join(output))
        
class VerboseManyToManyRawIdWidget(ManyToManyRawIdWidget):
    """
    A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
    in a <select multiple> box. Display user-friendly value like the ForeignKeyRawId widget
    """
    def __init__(self, rel, attrs=None):
        self._rel = rel
        super(VerboseManyToManyRawIdWidget, self).__init__(rel, attrs)

    def label_for_value(self, value):
        values = value.split(',')
        str_values = []
        key = self.rel.get_related_field().name
        for v in values:
            try:
                obj = self.rel.to._default_manager.using(self.db).get(**{key: v})
                # manage unicode error 
                x = smart_unicode(obj)
                # no HTML
                str_values += [escape(x)]
            except self.rel.to.DoesNotExist:
                str_values += [u'???']
        return u'&nbsp;<strong>%s</strong>' % (u',&nbsp;'.join(str_values))

class ImageManyToManyRawIdWidget(VerboseManyToManyRawIdWidget):
    """
    A Widget for displaying ManyToMany ids in the "raw_id" interface rather than
    in a <select multiple> box. Display images rather than text
    """
    
    def label_for_value(self, value):
        values = value.split(',')
        str_values = []
        key = self.rel.get_related_field().name
        for v in values:
            try:
                obj = self.rel.to._default_manager.using(self.db).get(**{key: v})
                # manage unicode error
                height = min(100, obj.image.height)
                title = u'{0} ({1}x{2})'.format(smart_unicode(obj.name), obj.image.width,
                    obj.image.height)
                x = u'<a href="{0}" target="_blank"><img alt="{1}" title="{1}" src="{0}" height="{2}px"/></a>'.format(
                    smart_unicode(obj.url()), title, height)
                # no HTML
                str_values += [x]
            except self.rel.to.DoesNotExist:
                str_values += [u'???']
        return u'<div>{0}</div>'.format(u'&nbsp;'.join(str_values))

class SelectAndLinkWidget(Select):
    add_button_template = """
        <a onclick="return showAddAnotherPopup(this);" class="add-another"
        href="{0}">
        <img height="10" width="10" alt="{2}" title="{2}" src="{1}flatcms/img/icon_addlink.gif">
        </a>
    """
    
    edit_button_template = """
        <a onclick="return showAddAnotherPopup(this);" class="add-another"
        href="{0}">
        <img height="10" width="10" alt="{2}" title="{2}" src="{1}flatcms/img/icon_changelink.gif">
        </a>
    """

    def render(self, name, value, attrs=None):
        widget = super(SelectAndLinkWidget, self).render(name, value, attrs)
        app_name, model_name = self.model._meta.app_label, self.model._meta.module_name
        add_url = reverse('admin:{0}_{1}_add'.format(app_name,  model_name))
        self.add_button = self.add_button_template.format(add_url, settings.MEDIA_URL, _('Add another'))
        html = u'{0}{1}'.format(widget, self.add_button)
        if value:
            edit_url = reverse('admin:{0}_{1}_change'.format(app_name,  model_name), args=[value])
            try:
                label = _("Edit '{0}'").format(self.model.objects.get(id=value))
            except:
                label = _('Edit')
            html += self.edit_button_template.format(edit_url, settings.MEDIA_URL, label)
        return mark_safe(html)