views:

86

answers:

1

The models below show a simple GenericForeignKey relationship. It has been set up in this way to allow an Image to be reused by any other model.

class Image(models.Model):
    name = models.CharField(max_length=150)
    desc = models.TextField(max_length=400)
    resource = models.ImageField(upload_to='imgs/generic/%Y/%m/%d')

    def __unicode__(self):
        return self.name

class ImageItem(models.Model):
    image = models.ForeignKey(Image, related_name='items', db_index=True)
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField(db_index=True)
    object = generic.GenericForeignKey('content_type','object_id')

    class Meta:
        unique_together = (('image', 'content_type', 'object_id'),)

        def __unicode__(self):
            return u'%s [%s]' % (self.object,  self.image)

class ImageInline(generic.GenericTabularInline):
    model = ImageItem

At present using ImageInline within another model's admin will show a list box with all the images within the system.

Is it possible to get the inline admin to show the actual Image model instead, showing only the images assigned to the model being edited? Thus allowing the user to see immediately all the related info on the images attached to the model being added/edited. As well as being able to add/remove related images.

Thanks in advance for your help on this one.

+2  A: 

You would have to change your code to:

class Image(models.Model):
    name = models.CharField(max_length=150)
    desc = models.TextField(max_length=400)
    resource = models.ImageField(upload_to='imgs/generic/%Y/%m/%d')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField(db_index=True)
    object = generic.GenericForeignKey('content_type','object_id')

    class Meta:
        unique_together = (('resource', 'content_type', 'object_id'),)

    def __unicode__(self):
        return u'%s [%s]' % (self.object,  self.resource)


class ImageInline(generic.GenericTabularInline):
    model = Image


class MyModelAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

This way when you go to add/change MyModel in admin you can add images as inlines.

UPDATE:

Solution with file browser field:

class Image(models.Model):
    name = models.CharField(max_length=150)
    desc = models.TextField(max_length=400)
    resource = FileBrowseField("Image", max_length=200, directory="imgs/generic/%Y/%m/%d", extensions=['.jpg', '.gif', '.png'], format='Image')
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField(db_index=True)
    object = generic.GenericForeignKey('content_type','object_id')

    class Meta:
        unique_together = (('resource', 'content_type', 'object_id'),)

    def __unicode__(self):
        return u'%s [%s]' % (self.object,  self.resource)


class ImageInline(generic.GenericTabularInline):
    model = Image


class MyModelAdmin(admin.ModelAdmin):
    inlines = [
        ImageInline,
    ]

More info about filebrowser field can be found here: http://code.google.com/p/django-filebrowser/wiki/installationfilebrowsefield

Dominik Szopa
This is a good idea, and certainly would solve the problem I am having. However I wanted the images to be reusable to reduce data redundancy and therefore for example allow two articles to use the same image. Do you think it could be done in any way through use of a manager on the Image model side?
Nick
You could also use FileBrowseField from http://code.google.com/p/django-filebrowser/. This way files would uploaded only once in filebrowser.
Dominik Szopa