django2.0 + xadmin2.0 一次性選擇多張圖片並存儲的一個方法

寫在開頭: 建議使用源碼安裝xadmin, 這樣可以根據自己實際需求做更靈活的處理
xadmin中圖片選擇按鈕默認是隻能單選,如圖:
單選按鈕
並不能一次性選擇多張圖片並存儲, 這裏只需要修改一點xadmin源代碼, 就可以實現一次性選擇多張圖片並存儲.
在xadmin源碼目錄xadmin/plugins/images.py裏找到第38行AdminImageWidget這個類:

# xadmin/plugins/images.py 第38行

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

   def render(self, name, value, attrs=None):
       output = []
       if value and hasattr(value, "url"):
           label = self.attrs.get('label', name)
           output.append('<a href="%s" target="_blank" title="%s" data-gallery="gallery"><img src="%s" class="field_img"/></a><br/>%s ' %
                        (value.url, label, value.url, _('Change:')))
       output.append(super(AdminImageWidget, self).render(name, value, attrs))
       return mark_safe(u''.join(output))

AdminImageWidget的註釋就說明了它就是xadmin處理ImageField的插件,如果有圖片, 就顯示當前圖片,下面的方法render返回的就包含前面支付截圖選項(xadmin是在這裏根據加載的數據生成前端頁面所需要的a標籤並返回-----xadmin管理頁面有很多都是這中處理方式), 而選擇圖片也只需要在return mark_safe前面加上幾行代碼就可以把單選改爲多選:

class AdminImageWidget(forms.FileInput):
    """
    ...
    """
    def render(self, name, value, attrs=None):
        output = []
        if value and hasattr(value, "url"):
            label = self.attrs.get('label', name)
            output.append('<a href="%s" target="_blank" title="%s" data-gallery="gallery"><img src="%s" class="field_img"/></a><br/>%s ' %
                         (value.url, label, value.url, _('Change:')))
        output.append(super(AdminImageWidget, self).render(name, value, attrs))
        
        """
        因爲前端頁面中選擇按鈕變多選,需要在對應標籤裏添加上multiple="multiple"
        而這裏的output就是xadmin後端生成的html所需要的標籤的文本流
        所以我們只需要在output的對應位置用代碼添加上這一條件
        """
        if self.attrs['label'] and self.attrs['label'] == '訪問截圖':
	        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))

這裏我自己的邏輯是隻給訪問截圖添加多張圖片,支付截圖沒有這個需求,所以對標籤做了篩選, 支付截圖保持單選, 其中 self.attrs['label'] == '訪問截圖'中的訪問截圖, 就是我們頁面中對應選項的文字描述:
標籤
保存刷新, 此時測試頁面點擊選擇文件, 在選擇的時候按住ctrl就能夠同時選擇多張圖片了:
圖片多選

現在能夠選擇多張圖片, 但是xadmin在存儲的時候還是隻會存儲一張, 需要在自己的admin.py文件裏面的插件下添加方法save_models 來處理自己的存儲邏輯, 我這裏處理的很簡單, visit_img是多張圖, 另建了一張表來存路徑+圖片名, 另外由於沒有巨量圖片的存儲需求, 也沒有用到雲存儲, 直接在服務器上把圖片寫入一個文件夾:

# admin.py

import xadmin

from .models import TestBasci, VisitImg


class TestBasicView(object):
    list_display = ['name', 'url', 'record_num', 'record_company', 'ip', 'addr', 'client_type', 'pay_type', 'order', 'image_data', 'vi_img_data', ]
    """
    ...
    """

    def save_models(self):
        obj = self.new_obj
        files = self.request.FILES.getlist('visit_image')
        if files:
            for f in files:
                fname = ''
                if VisitImg.objects.filter(image='visit_imgs/%s' % f.name).first():
                    fname = str(datetime.timestamp(datetime.now())).split('.')[0] + '_' + f.name
                else:
                    # 如果圖片名不存在,則使用當前圖片名
                    fname = f.name
                with open('%s/visit_imgs/%s' % (settings.MEDIA_ROOT, fname), 'wb+') as pic:
                    for chunk in f.chunks():
                        pic.write(chunk)
                # 圖片名信息寫入數據庫
                img_obj = VisitImg(name=self.new_obj.name,
                                   image='visit_imgs/%s' % fname,)
                img_obj.save()
        obj.save()

# 註冊插件
xadmin.site.register(TestBasic, TestBasicView)

再保存刷新一次, 選擇多張圖片後就可以在後臺數據庫中看到成功保存所選圖片

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章