views:

721

answers:

1

A have 3 models: Project, Image and Video with ManyToManyField relation:

class Project(models.Model):
    images = models.ManyToManyField('Image', through='Project_Images')
    video = models.ManyToManyField('Video', through='Project_Video')

class Image(models.Model):
    original = models.ImageField()
    projects = models.ManyToManyField('Project', through='Project_Images')

class Video(models.Model):
    projects = models.ManyToManyField('Project', through='Project_Video')

I configure project's admin form with inline forms of Images and Videos linked to current project:

class ProjectAdmin(admin.ModelAdmin):
    inlines = [VideoInline, ImagesInline]

class ImagesInline(admin.TabularInline):    
    model = Project_Images
    raw_id_fields = ['project','image']

class VideoInline(admin.TabularInline):    
    model = Project_Video
    raw_id_fields = ['project','video']

But inline table with simple select field and delete checkbox is much miserable for me, and I want to show here previews of images or video (youtube). I solve this for images with help of AdminImageWidget:

class ImageForm(forms.ModelForm):
    class Meta:
        model = Image

    preview = forms.ImageField(widget=AdminImageWidget())
    def __init__(self, *args, **kwargs):
        super(ImageForm, self).__init__(*args, **kwargs)
        try:
            image = Image.objects.get(id=self.instance.image_id)
            self.fields["preview"].initial = image.original
        except:
            pass

class ImagesInline(admin.TabularInline):
    .....
    form = ImageForm

Is it best way to do this? In my case I don't need file upload input, only image-preview in inline form table. I need also preview for youtube video, should I write my own widget for displaying video and apply it to some fake field ?

It's strange to solve this issue by widget for unnecessary fake field. Or is it normal way?

Any help will be very much appreciated! Thanks!

+1  A: 

You should create a widget similar to AdminImageWidget but that displays only the image, not the upload box. To apply that widget you don't need a custom Form class or a fake field, just use formfield_overrides on your ImageInline:

class ImageInline(admin.TabularInline):
    ...
    formfield_overrides = { models.ImageField: {'widget': YourPreviewWidget}}

EDIT: Oops, didn't fully process the ManyToManyField issue - you're displaying inlines for the "through" table, not the table with the actual ImageFields. Given that, what you're doing now may be not such a bad solution. The alternative I can think of would be to write a specialized replacement widget for the Select, that knows how to display both the select box and a preview image for the currently selected Image object. That way you could avoid the need for the fake extra field.

Carl Meyer
But I use ManyToMany relation! It's very important! I have only LINKS to real Image and Video objects in form inlines. I haven't any ImageFields inside these link objects.
ramusus
What do you recomend to do in this case?
ramusus