寫在開頭: 建議使用源碼安裝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)
再保存刷新一次, 選擇多張圖片後就可以在後臺數據庫中看到成功保存所選圖片