轉載自:https://blog.csdn.net/zcyuefan/article/details/77748850css
1. 需求vs現狀
1.1 需求
要求作一個ERP後臺輔助管理的程序,有如下幾項基本要求:
1. 基本的增刪改查功能
2. 基於對象的權限控制(如:系統用戶分爲平臺運營人員和商家用戶,商家用戶小A只能查看編輯所屬商家記錄,而管理員能夠縱覽全局)
3. 數據庫記錄導入導出(xsl, json等),而且擁有對象級的權限控制(如:小A不能導出小B公司的信息,更不能導入小B公司信息進行更新和新增)html
1.2 現狀
實現需求1:Django-admin讓咱們可以很方便的實現一個管理後臺程序。django-xadmin則在擁有admin基本功能的基礎上增長了更爲豐富的功能、界面也更加漂亮。相似還有django-suit等,本文使用xadmin(功能更豐富);
實現需求2:django-admin,以及xadmin都只有基於model級的權限控制機制,須要本身擴展或者使用開源解決方案,如django-guardian,django-rules,本文結合django-rules實現了該功能;
實現需求3:xadmin雖然自帶導出功能,可是導入功能沒有實現,django自帶後臺結合django-import-export能夠很容易實現,可是xadmin並不直接兼容,只有經過xadmin的插件機制實現。
2. 功能實現
本節主要展現需求3導入導出功能實現。node
2.1 安裝並配置django-import-export
django-import-export主要原理是爲待導入導出的model類設置一個Resource類,經過Resource類的export()方法進行導出,import_data()方法進行導入,靈活設置Resource便能實現多種文件格式數據導入導出。
pip安裝:數據庫
$ pip install django-import-export
1
配置settings.pydjango
# settings.py
INSTALLED_APPS = (
...
'import_export',
)
2.2 創建model(同上篇)
新增CompanyUser模型表示商家帳戶(即對django自帶user模塊進行擴展,使每一個帳號綁定本身的公司碼),新增Customer模型表示商家的客戶信息幷包含公司碼字段,商家帳號只能查看、編輯、導入、導出公司碼一致的商家客戶信息json
# model.py
class CompanyUser(models.Model):
user = models.OneToOneField(User, verbose_name='用戶名')
is_taixiang_admin = models.BooleanField('是否運營人員', default=False)
company_code = models.CharField('公司碼', max_length=20, blank=True, default='')app
def __unicode__(self):
return '%s' % self.userui
class Meta:
verbose_name = '導入帳號'
verbose_name_plural = verbose_name
class Customer(models.Model):
name = models.CharField('客戶姓名', max_length=50)
phone = models.CharField('客戶電話', max_length=12)
type_choice = ((1, '普通'), (2, '批發'), (3, 'VIP'))
creator = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='建立人', blank=True, null=True)
company_code = models.CharField('公司碼', max_length=20, blank=True, null=True)url
def __unicode__(self):
return '%s-%s-%s' % (self.company_code, self.name, self.phone1).net
class Meta:
permissions = (
("simulate_import_customer", "容許模擬導入客戶"),
("import_customer", "容許導入客戶至商家系統"),
)
verbose_name = "客戶"
verbose_name_plural = verbose_name
2.3 建立Resource
在model統計目錄新增resources.py,配置Resource類
# resources.py
from import_export import resources
from .models import Customer
class CustomerResource(resources.ModelResource):
class Meta:
model = Customer
fields = ('id', 'name', 'phone1', 'c_type', 'company_code')
2.4 原生django-admin導入導出實現
使用原生的django-admin,ModelAdminClass能夠經過繼承ImportExportModelAdmin類實現導入導出,繼承ImportExportActionModelAdmin類實現導出action:
# admin.py
from django.contrib import admin
from .models import Customer
from import_export.admin import ImportExportModelAdmin, ImportExportActionModelAdmin
from .resources import CustomerResource
class CustomerAdmin(ImportExportActionModelAdmin, ImportExportModelAdmin):
resource_class = CustomerResource
admin.site.register(Customer, CustomerAdmin)
2.5 django-xadmin導入導出實現(代碼修改挺多的,此處展現基本思路,但願能push到xadmin項目中)
基於xadmin強大的plugin功能(參考Xadmin插件製做),此次咱們開發一個importexport插件。具體實現轉下章。
3. xadmin-importexport-plugin開發
開發思路:
相似admin使用importexport,須要在adminx.py ModelAdmin類中設置import_export_args屬性用於關聯Resource類,在list頁面中會顯示導入和導出按鈕(ImportMenuPlugin,ExportMenuPlugin生效)。
# adminx.py
class CustomerAdmin(object):
import_export_args = {'import_resource_class': CustomerResource, 'export_resource_class': CustomerResource}
...
2. 點擊導出按鈕,會彈出若干選項,點擊肯定發送get請求後,觸發ExportPlugin插件調用resource的export()方法進行導出。
3. 點擊導入按鈕,則會跳轉至導入頁面(ImportView),上傳文件後點擊導入會進行基本的檢測
4. 點擊確認導入(ImportProcessView)調用django-import-export導入至數據庫。
3.1.1 插件部分代碼
# xadmin/plugins/importexport.py
# 繼承BaseAdminPlugin類
class ImportMenuPlugin(BaseAdminPlugin):
# 使用插件時須要在ModelAdmin類中設置import_export_args屬性,插件初始化時使用ModelAdmin的import_export_args進行賦值
import_export_args = {}
# 返回True則加載插件,在list列表中顯示導入按鈕
def init_request(self, *args, **kwargs):
return bool(self.import_export_args.get('import_resource_class'))
def block_top_toolbar(self, context, nodes):
has_change_perm = self.has_model_perm(self.model, 'change')
has_add_perm = self.has_model_perm(self.model, 'add')
if has_change_perm and has_add_perm:
model_info = (self.opts.app_label, self.opts.model_name)
import_url = reverse('xadmin:%s_%s_import' % model_info, current_app=self.admin_site.name)
context = get_context_dict(context or {}) # no error!
context.update({
'import_url': import_url,
})
nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.importexport.import.html',
context=context))
class ExportMenuPlugin(BaseAdminPlugin):
import_export_args = {}
# Media
def get_media(self, media):
return media + self.vendor('xadmin.plugin.importexport.css', 'xadmin.plugin.importexport.js')
def init_request(self, *args, **kwargs):
return bool(self.import_export_args.get('export_resource_class'))
def block_top_toolbar(self, context, nodes):
formats = self.get_export_formats()
form = ExportForm(formats)
context = get_context_dict(context or {}) # no error!
context.update({
'form': form,
'opts': self.opts,
'form_params': self.admin_view.get_form_params({'_action_': 'export'}),
})
nodes.append(loader.render_to_string('xadmin/blocks/model_list.top_toolbar.importexport.export.html',
context=context))
site.register_plugin(ImportMenuPlugin, ListAdminView)site.register_plugin(ExportMenuPlugin, ListAdminView)--------------------- 做者:zcyuefan 來源:CSDN 原文:https://blog.csdn.net/zcyuefan/article/details/77748850 版權聲明:本文爲博主原創文章,轉載請附上博文連接!