Django多图上传——通过重写imagefield实现(可后端,xadmin适用)

目录

一、app目录

二、各py文件

2.1model.py

 2.2adminx.py

2.3fields.py

2.4widgets.py

2.6 admin.py    test.py    view.py  forms.py此次都没使用

三、实现效果

3.1多选效果

3.2展示效果

扫描二维码关注公众号,回复: 13177786 查看本文章

一、app目录

二、各py文件

fields和widgets可直接复制,只有widgets中的(多图上传预览)根据实际情况改动

2.1model.py

from django.db import models

from .fields import UploaderImageField

# Create your models here.
class test(models.Model):
    name = models.CharField(max_length=128)
    imgs = UploaderImageField(max_length=500,verbose_name='多图上传',null=True, blank=True,upload_to='img')
    def __str__(self):
        return self.name
    class Mate:
        verbose_name = '多图上传'
        verbose_name_plural = verbose_name


class Img(models.Model):
    model = models.ForeignKey(test,on_delete=models.CASCADE,verbose_name='外键关联')
    creattime = models.DateTimeField(verbose_name='创建时间',auto_now_add=True)
    updatetime = models.DateTimeField(verbose_name='更新时间',auto_now=datetime.now)
    image = models.ImageField(upload_to='Loopwater/img', verbose_name='图片', null=True, blank=True)

    class Meta:
        verbose_name = u'单图'
        verbose_name_plural = verbose_name

 2.2adminx.py

from datetime import datetime
from SmallOA import settings
import xadmin

from .models import test,img


class testadmin(object):
    list_field = [ 'name','imgs']

    def save_models(self):
        try:
            if self.new_obj:
                obj = self.new_obj
                files = self.request.FILES.getlist('imgs')
                print(files)
                if files:
                    img_url = []
                    for f in files:
                        img_obj = Img()
                        img_obj.model = obj
                        img_obj.image = f
                        img_obj.save()
                        img_url.append(img_obj.image.name)

                str_json = json.dumps(img_url, ensure_ascii=False)
                obj.imgs = str_json
                obj.segment = obj.pointposition.segment
                obj.user = self.request.user
                obj.save()
        except Exception as e:
            print(e)
        super().save_models()


class imgadmin(object):
    list_field = [ 'name','image',]

xadmin.site.register(test,testadmin)
xadmin.site.register(img,imgadmin)

2.3fields.py

from django import forms
from django.db import models

from django.db import models
from django import forms
from django.utils.translation import ugettext as _
from django.utils.safestring import mark_safe
from xadmin.sites import site
from xadmin.views import BaseAdminPlugin, ModelFormAdminView, DetailAdminView, ListAdminView


class UploaderImageField(models.ImageField):
    def __init__(self,*args,**kwargs):
        super(UploaderImageField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        defaults = {
            'form_class': self._get_form_class(),
        }
        defaults.update(kwargs)
        return super(UploaderImageField,self).formfield(**defaults)


    @staticmethod
    def _get_form_class():
        return UploaderFormField

class UploaderFormField(forms.ImageField):

    def __init__( self,*args,**kwargs):
        from .widgets import UploaderWidget
        kwargs.update({"widget":UploaderWidget()})
        super(UploaderFormField, self).__init__(*args, **kwargs)

    def widget_attrs(self, widget):
        return {'label': self.label}


def get_gallery_modal():
    return """
        <!-- modal-gallery is the modal dialog used for the image gallery -->
        <div id="modal-gallery" class="modal modal-gallery fade" tabindex="-1">
          <div class="modal-dialog">
            <div class="modal-content">
              <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
                <h4 class="modal-title"></h4>
              </div>
              <div class="modal-body"><div class="modal-image"><h1 class="loader"><i class="fa-spinner fa-spin fa fa-large loader"></i></h1></div></div>
              <div class="modal-footer">
                  <a class="btn btn-info modal-prev"><i class="fa fa-arrow-left"></i> <span>%s</span></a>
                  <a class="btn btn-primary modal-next"><span>%s</span> <i class="fa fa-arrow-right"></i></a>
                  <a class="btn btn-success modal-play modal-slideshow" data-slideshow="5000"><i class="fa fa-play"></i> <span>%s</span></a>
                  <a class="btn btn-default modal-download" target="_blank"><i class="fa fa-download"></i> <span>%s</span></a>
              </div>
            </div><!-- /.modal-content -->
          </div><!-- /.modal-dialog -->
        </div>
    """ % (_('Previous'), _('Next'), _('Slideshow'), _('Download'))

class ModelDetailPlugin22(BaseAdminPlugin):

    def __init__(self, admin_view):
        super(ModelDetailPlugin22, self).__init__(admin_view)
        self.include_image = False

    def get_field_attrs(self, attrs, db_field, **kwargs):
        if isinstance(db_field, UploaderImageField):
            from .widgets import UploaderWidget
            attrs['widget'] = UploaderWidget
            attrs['form_class'] = UploaderFormField
            self.include_image = True
        return attrs

    def get_field_result(self, result, field_name):
        if isinstance(result.field, models.ImageField):
            if result.value:
                img = getattr(result.obj, field_name)
                result.text = mark_safe('<a href="%s" target="_blank" title="%s" data-gallery="gallery"><img src="%s" class="field_img"/></a>' % (img.url, result.label, img.url))
                self.include_image = True
        return result

    # Media
    def get_media(self, media):
        if self.include_image:
            media = media + self.vendor('image-gallery.js',
                                        'image-gallery.css')
        return media

    def block_before_fieldsets(self, context, node):
        if self.include_image:
            return '<div id="gallery" data-toggle="modal-gallery" data-target="#modal-gallery">'

    def block_after_fieldsets(self, context, node):
        if self.include_image:
            return "</div>"

    def block_extrabody(self, context, node):
        if self.include_image:
            return get_gallery_modal()


class ModelListPlugin(BaseAdminPlugin):

    list_gallery = False

    def init_request(self, *args, **kwargs):
        return bool(self.list_gallery)

    # Media
    def get_media(self, media):
        return media + self.vendor('image-gallery.js', 'image-gallery.css')

    def block_results_top(self, context, node):
        return '<div id="gallery" data-toggle="modal-gallery" data-target="#modal-gallery">'

    def block_results_bottom(self, context, node):
        return "</div>"

    def block_extrabody(self, context, node):
        return get_gallery_modal()


site.register_plugin(ModelDetailPlugin22, DetailAdminView)
site.register_plugin(ModelDetailPlugin22, ModelFormAdminView)

2.4widgets.py

from django import forms
from django.utils.safestring import mark_safe

from .models import img as img#存储图片的表,修改as前的模型函数,保留 as img

class UploaderWidget(forms.FileInput):
    """
    A ImageField Widget that shows its current value if it has one.
    """
    def __init__(self, attrs={}):
        super(UploaderWidget, self).__init__(attrs)

    def render(self, name, value, attrs=None, renderer=None, img=img):
        output = []
        if value and hasattr(value, "url"):
            #多图上传预览
            img_names = img.objects.filter(model=value.instance.pk).values('image')
            if img_names:
                for img in img_names:
                    output.append(
                        '<a href="/media/%s" target="_blank" title="多图上传" data-gallery="gallery"> '
                        '<img src="/media/%s" class="field_img">'
                        '</a>' % (img["image"], img["image"]))
        output.append(super(UploaderWidget, self).render(name, value, attrs, renderer))
        """
        因为前端页面中选择按钮变多选,需要在对应标签里添加上multiple="multiple"
        而这里的output就是xadmin后端生成的html所需要的标签的文本流
        所以我们只需要在output的对应位置用代码添加上这一条件
        """
        #多图选择
        if len(output) > 1:
            output[-1] = output[-1][:-2] + ' multiple="multiple">'
        else:
            output[0] = output[0][:-2] + ' multiple="multiple">'
        return mark_safe(u''.join(output))

2.6 admin.py    test.py    view.py  forms.py此次都没使用

三、实现效果

3.1多选效果

3.2展示效果

参考链接:django2.0 + xadmin2.0 一次性选择多张图片并存储的一个方法, 以及详情页面多图展示_thisMoments的博客-CSDN博客

gitee链接:imgsdemo: xadmin多图上传 (gitee.com)icon-default.png?t=LA92https://gitee.com/li-pf/imgsdemo

猜你喜欢

转载自blog.csdn.net/qq_15028721/article/details/117962297
今日推荐