views:

166

answers:

1

I keep field imdb_id for models Movie in my db:

class Movie(models.Model):
    imdb_id = models.IntegerField('imdb ID', blank=True, null=True, unique=True)

    def _get_imdb_url(self):
        return self.imdb_id and 'http://www.imdb.com/title/tt%s/' % str(self.imdb_id).zfill(7) or ''

    def _set_imdb_url(self, imdb_url):
        self.imdb_id = int( re.compile(r'[^\d]').sub('', imdb_url))

    imdb_url = property(_get_imdb_url, _set_imdb_url)

And I want to make special widget for displaying external link to imdb.com in the admin form near text input for field 'imdb_id'. I think it may be global widget for any form field with external link, generated by using special mask (in my case, this mask is 'http://www.imdb.com/title/tt%s/'). I know how to write widget, but I don't know how push my mask, defined in my Movie model, to this widget. I don't want to violate DRY principe and define this mask in two different places. And also it will be a good tool for the same purpose with other external links in future.

What do you think about this widget? How it is posssible to realize it? May be someone wrote it before me?

Thanks!

A: 

So, I decided not waiting for help and wrote this widget:

import re
from django import forms
class LinkFieldWidget(Widget):
    '''
    A TextField widget with previewing link, generated from field's value with special url mask
    '''
    def __init__(self, text, url='%s', *args, **kwargs):
        self.url = url
        self.text = text
        if not re.search('%', self.url):
            raise forms.ValidationError, u'Invalid URL mask'
        super(LinkFieldWidget, self).__init__(*args, **kwargs)

    def render(self, name, value, attrs=None):
        output = []
        output.append('''<input type="text" name="%s" value="%s" onkeyup="$('a#%s-link').attr('href', '%s'.replace('%s', this.value)).css({'display': (this.value ? 'inline' : 'none')})" />''' % (name, value or '', name, self.url, '%s'))
        if self.url and self.text:
            output.append('<span><a href="%s" id="%s-link" target="blank" style="display: %s;">%s</a></span>' % (value and self.url % value or '#', name, value and 'inline' or 'none', self.text))

        return mark_safe(u' '.join(output))

Example using it in admin:

from utils.widgets import LinkFieldWidget
class MovieAdminForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(MovieAdminForm, self).__init__(*args, **kwargs)
        self.fields['imdb_id'].widget = LinkFieldWidget(text='imdb', url=self.instance.imdb_link)

class MovieAdmin(admin.ModelAdmin):
    form = MovieAdminForm

Model:

class Movie(models.Model):
    .....    
    imdb_link = 'http://www.imdb.com/title/tt%s/'
    def _get_imdb_url(self):
        return self.imdb_id and self.imdb_link % str(self.imdb_id).zfill(7) or ''
    def _set_imdb_url(self, imdb_url):
        self.imdb_id = int( re.compile(r'[^\d]').sub('', imdb_url))
    imdb_url = property(_get_imdb_url, _set_imdb_url)
ramusus