How to show only one image in Django admin inline

后端 未结 3 1932
我在风中等你
我在风中等你 2020-12-23 11:52

I\'m using django.contrib.admin in one of my apps.

my models:

class Gallery(models.Model):
    location = models.ForeignKey(Location)
           


        
相关标签:
3条回答
  • 2020-12-23 12:45

    In case if you use sorl-thumbnails , widget is like this:

    from django.contrib.admin.widgets import AdminFileWidget
    from django.utils.safestring import mark_safe
    from sorl import thumbnail
    
    
    class AdminImageWidget(AdminFileWidget):
        def render(self, name, value, attrs=None):
            output = []
            if value and getattr(value, "url", None):
                t = thumbnail.get_thumbnail(value,'100x100')
                output.append('<img src="{}">'.format(t.url))
            output.append(super(AdminFileWidget, self).render(name, value, attrs))
            return mark_safe(u''.join(output))
    
    
    class GalleryImageForm(forms.ModelForm):
        """
        Image Admin Form
        """
        class Meta:
            model = Image
            widgets = {
                'image' : AdminImageWidget,
            }
    
    class GalleryImageInline(admin.TabularInline):
        ...
        form = GalleryImageForm
        ...
    
    0 讨论(0)
  • 2020-12-23 12:49

    Check the docs for InlineModelAdmin.extra and InlineModelAdmin.max_num.

    I believe in your case max_num needs to be 1 and extra 0.

    0 讨论(0)
  • 2020-12-23 12:57

    extra = 0

    class GalleryImageInline(admin.TabularInline):
        """
        Gallery Image inline
        """
        fieldsets = (
            (
                None, 
                {
                    'fields': ('name', 'image',)
                }
            ),
        )
    
        model = Image
        extra = 0
    
    
    class GalleryAdmin(admin.ModelAdmin):
        """
        Case Study Admin
        """
        fieldsets = (
            (
                None, 
                {
                    'fields': ('location', 'date',)
                }
            ),
        )
    
        inlines = (GalleryImageInline, )
        list_display = ['location', 'date']
        list_filter = ['location', ]
    

    And in my opinion, for a inline that has images to be useful you need to actually display the image inline (so custom override the image widget):

    from django.contrib.admin.widgets import AdminFileWidget
    from django.utils.translation import ugettext as _
    from django.utils.safestring import mark_safe
    import os
    import Image
    
    class AdminImageWidget(AdminFileWidget):
        def render(self, name, value, attrs=None):
            output = []
            if value and getattr(value, "url", None):
    
                image_url = value.url
                file_name=str(value)
    
                # defining the size
                size='100x100'
                x, y = [int(x) for x in size.split('x')]
                try :
                    # defining the filename and the miniature filename
                    filehead, filetail  = os.path.split(value.path)
                    basename, format    = os.path.splitext(filetail)
                    miniature           = basename + '_' + size + format
                    filename            = value.path
                    miniature_filename  = os.path.join(filehead, miniature)
                    filehead, filetail  = os.path.split(value.url)
                    miniature_url       = filehead + '/' + miniature
    
                    # make sure that the thumbnail is a version of the current original sized image
                    if os.path.exists(miniature_filename) and os.path.getmtime(filename) > os.path.getmtime(miniature_filename):
                        os.unlink(miniature_filename)
    
                    # if the image wasn't already resized, resize it
                    if not os.path.exists(miniature_filename):
                        image = Image.open(filename)
                        image.thumbnail([x, y], Image.ANTIALIAS)
                        try:
                            image.save(miniature_filename, image.format, quality=100, optimize=1)
                        except:
                            image.save(miniature_filename, image.format, quality=100)
    
                    output.append(u' <div><a href="%s" target="_blank"><img src="%s" alt="%s" /></a></div> %s ' % \
                    (miniature_url, miniature_url, miniature_filename, _('Change:')))
                except:
                    pass
            output.append(super(AdminFileWidget, self).render(name, value, attrs))
            return mark_safe(u''.join(output))
    

    Note: that this does some resizey stuff you may not like - so you may need to rewrite the thumb sizing part of the widget yourself.

    so then you are going to need to override the widget in your inline's form:

    class GalleryImageForm(forms.ModelForm):
        """
        Image Admin Form
        """
        class Meta:
            model = Image
            widgets = {
                'image' : AdminImageWidget,
            }
    
    class GalleryImageInline(admin.TabularInline):
        ...
        form = GalleryImageForm
        ...
    

    and you end up with somethig like this (this is part of another project and has a bunch of extra stuff): screenshot of the image admin inline

    0 讨论(0)
提交回复
热议问题