Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
gjl2004yn
jumpserver
提交
3aea9941
J
jumpserver
项目概览
gjl2004yn
/
jumpserver
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jumpserver
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
3aea9941
编写于
11月 27, 2016
作者:
baltery
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
asset import
上级
c1c9c7b6
变更
14
展开全部
隐藏空白更改
内联
并排
Showing
14 changed file
with
210 addition
and
67 deletion
+210
-67
apps/assets/forms.py
apps/assets/forms.py
+5
-1
apps/assets/models.py
apps/assets/models.py
+3
-3
apps/assets/serializers.py
apps/assets/serializers.py
+7
-7
apps/assets/templates/assets/_asset_import_modal.html
apps/assets/templates/assets/_asset_import_modal.html
+27
-0
apps/assets/templates/assets/asset_detail.html
apps/assets/templates/assets/asset_detail.html
+1
-1
apps/assets/templates/assets/asset_list.html
apps/assets/templates/assets/asset_list.html
+40
-20
apps/assets/urls/views_urls.py
apps/assets/urls/views_urls.py
+2
-0
apps/assets/views.py
apps/assets/views.py
+111
-28
apps/fixtures/fake.json
apps/fixtures/fake.json
+1
-1
apps/users/templates/users/user_list.html
apps/users/templates/users/user_list.html
+1
-1
apps/users/urls/views_urls.py
apps/users/urls/views_urls.py
+1
-1
apps/users/views.py
apps/users/views.py
+2
-2
utils/clean_migrations.sh
utils/clean_migrations.sh
+1
-1
utils/make_fake_json.sh
utils/make_fake_json.sh
+8
-1
未找到文件。
apps/assets/forms.py
浏览文件 @
3aea9941
...
...
@@ -309,4 +309,8 @@ class AssetTagForm(forms.ModelForm):
}
help_texts
=
{
'name'
:
'* required'
,
}
\ No newline at end of file
}
class
FileForm
(
forms
.
Form
):
file
=
forms
.
FileField
()
\ No newline at end of file
apps/assets/models.py
浏览文件 @
3aea9941
...
...
@@ -309,12 +309,12 @@ class Asset(models.Model):
cabinet_no
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet number'
))
cabinet_pos
=
models
.
IntegerField
(
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Cabinet position'
))
number
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Asset number'
))
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
1
,
null
=
True
,
blank
=
True
,
default
=
'I'
,
verbose_name
=
_
(
'Asset status'
))
status
=
models
.
CharField
(
choices
=
STATUS_CHOICES
,
max_length
=
8
,
null
=
True
,
blank
=
True
,
default
=
'I
n use
'
,
verbose_name
=
_
(
'Asset status'
))
type
=
models
.
CharField
(
choices
=
TYPE_CHOICES
,
max_length
=
16
,
blank
=
True
,
null
=
True
,
default
=
'Server'
,
verbose_name
=
_
(
'Asset type'
),)
env
=
models
.
CharField
(
choices
=
ENV_CHOICES
,
max_length
=
8
,
blank
=
True
,
null
=
True
,
default
=
'P'
,
verbose_name
=
_
(
'Asset environment'
),)
default
=
'P
rod
'
,
verbose_name
=
_
(
'Asset environment'
),)
sn
=
models
.
CharField
(
max_length
=
128
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Serial number'
))
created_by
=
models
.
CharField
(
max_length
=
32
,
null
=
True
,
blank
=
True
,
verbose_name
=
_
(
'Created by'
))
is_active
=
models
.
BooleanField
(
default
=
True
,
verbose_name
=
_
(
'Is active'
))
...
...
apps/assets/serializers.py
浏览文件 @
3aea9941
...
...
@@ -43,7 +43,6 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
# system_users = SystemUserSerializer(many=True, read_only=True)
# admin_user = AdminUserSerializer(many=False, read_only=True)
hardware
=
serializers
.
SerializerMethodField
()
type_display
=
serializers
.
SerializerMethodField
()
class
Meta
(
object
):
model
=
Asset
...
...
@@ -51,15 +50,16 @@ class AssetSerializer(BulkSerializerMixin, serializers.ModelSerializer):
@
staticmethod
def
get_hardware
(
obj
):
return
'%s %s %s'
%
(
obj
.
cpu
,
obj
.
memory
,
obj
.
disk
)
@
staticmethod
def
get_type_display
(
obj
):
if
obj
.
type
:
return
obj
.
type
.
value
if
obj
.
cpu
:
return
'%s %s %s'
%
(
obj
.
cpu
,
obj
.
memory
,
obj
.
disk
)
else
:
return
''
def
get_field_names
(
self
,
declared_fields
,
info
):
fields
=
super
(
AssetSerializer
,
self
).
get_field_names
(
declared_fields
,
info
)
fields
.
extend
([
'get_type_display'
,
'get_env_display'
])
return
fields
class
AssetGrantedSerializer
(
serializers
.
ModelSerializer
):
system_users
=
SystemUserSerializer
(
many
=
True
,
read_only
=
True
)
...
...
apps/assets/templates/assets/_asset_import_modal.html
0 → 100644
浏览文件 @
3aea9941
{% extends '_modal.html' %}
{% load i18n %}
{% block modal_id %}asset_import_modal{% endblock %}
{% block modal_title%}{% trans "Import asset" %}{% endblock %}
{% block modal_body %}
<p
class=
"text-success"
>
{% trans "Download template or use export excel format" %}
</p>
<form
method=
"post"
action=
"{% url 'assets:asset-import' %}"
id=
"fm_asset_import"
enctype=
"multipart/form-data"
>
{% csrf_token %}
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_assets"
>
{% trans "Template" %}
</label>
<a
href=
"{{ MEDIA_URL }}files/asset_import_template.xlsx"
style=
"display: block"
>
{% trans 'Download' %}
</a>
</div>
<div
class=
"form-group"
>
<label
class=
"control-label"
for=
"id_users"
>
{% trans "Asset excel file" %}
</label>
<input
id=
"id_assets"
type=
"file"
name=
"file"
/>
</div>
</form>
<p>
<p
class=
"text-success"
id=
"id_created"
></p>
<p
id=
"id_created_detail"
></p>
<p
class=
"text-warning"
id=
"id_updated"
></p>
<p
id=
"id_updated_detail"
></p>
<p
class=
"text-danger"
id=
"id_failed"
></p>
<p
id=
"id_failed_detail"
></p>
</p>
{% endblock %}
{% block modal_confirm_id %}btn_asset_import{% endblock %}
apps/assets/templates/assets/asset_detail.html
浏览文件 @
3aea9941
...
...
@@ -96,7 +96,7 @@
</tr>
<tr>
<td>
{% trans 'Asset status' %}:
</td>
<td><b>
{{ asset.
status
}}
</b></td>
<td><b>
{{ asset.
get_status_display()
}}
</b></td>
</tr>
<tr>
<td>
{% trans 'Is active' %}:
</td>
...
...
apps/assets/templates/assets/asset_list.html
浏览文件 @
3aea9941
...
...
@@ -48,7 +48,6 @@
{% block table_container %}
<div
class=
"uc pull-left m-l-5 m-r-5"
><a
href=
"{% url "
assets:asset-create
"
%}"
class=
"btn btn-sm btn-primary"
>
{% trans "Create asset" %}
</a></div>
<div
class=
"uc pull-left"
><a
href=
"javascript:void(0);"
class=
"btn btn-sm btn-primary"
data-toggle=
"modal"
data-target=
"#asset_import_modal"
>
{% trans "Import asset" %}
</a></div>
<table
class=
"table table-striped table-bordered table-hover "
id=
"asset_list_table"
>
<thead>
<tr>
...
...
@@ -81,6 +80,7 @@
</div>
</div>
</div>
{% include 'assets/_asset_import_modal.html' %}
{% endblock %}
{% block custom_foot_js %}
...
...
@@ -100,7 +100,7 @@
}
else
{
oDiv
.
style
.
display
=
"
none
"
;
}
}
;
//onload;
}
//onload;
$
(
document
).
ready
(
function
(){
var
options
=
{
...
...
@@ -132,31 +132,51 @@
],
ajax_url
:
'
{% url "api-assets:asset-list" %}
'
,
columns
:
[{
data
:
"
id
"
},
{
data
:
"
hostname
"
},
{
data
:
"
ip
"
},
{
data
:
"
port
"
},
{
data
:
"
type_display
"
},
{
data
:
"
env
"
},
{
data
:
"
hardware
"
},
{
data
:
"
is_active
"
},
{
data
:
"
is_active
"
},
{
data
:
"
id
"
}],
{
data
:
"
get_type_display
"
},
{
data
:
"
get_env_display
"
},
{
data
:
"
hardware
"
},
{
data
:
"
is_active
"
},
{
data
:
"
is_active
"
},
{
data
:
"
id
"
}],
op_html
:
$
(
'
#actions
'
).
html
()
};
var
table
=
jumpserver
.
initDataTable
(
options
);
$
(
'
.btn_export
'
).
click
(
function
()
{
var
assets
=
[];
var
rows
=
table
.
rows
(
'
.selected
'
).
data
();
$
.
each
(
rows
,
function
(
index
,
obj
)
{
assets
.
push
(
obj
.
id
)
var
assets
=
[];
var
rows
=
table
.
rows
(
'
.selected
'
).
data
();
$
.
each
(
rows
,
function
(
index
,
obj
)
{
assets
.
push
(
obj
.
id
)
});
$
.
ajax
({
url
:
"
{% url
"
assets
:
asset
-
export
"
%}
"
,
method
:
'
POST
'
,
data
:
JSON
.
stringify
({
assets_id
:
assets
}),
dataType
:
"
json
"
,
success
:
function
(
data
,
textStatus
)
{
window
.
open
(
data
.
redirect
)
},
error
:
function
()
{
toastr
.
error
(
'
Export failed
'
);
}
})
});
$
.
ajax
({
url
:
"
{% url
"
assets
:
export
-
assets
-
xlsx
"
%}
"
,
method
:
'
POST
'
,
data
:
JSON
.
stringify
({
users_id
:
users
}),
dataType
:
"
json
"
,
success
:
function
(
data
,
textStatus
)
{
window
.
open
(
data
.
redirect
)
},
error
:
function
()
{
toastr
.
error
(
'
Export failed
'
);
$
(
'
#btn_asset_import
'
).
click
(
function
()
{
var
$form
=
$
(
'
#fm_asset_import
'
);
$form
.
find
(
'
.help-block
'
).
remove
();
function
success
(
data
)
{
if
(
data
.
valid
===
false
)
{
$
(
'
<span />
'
,
{
class
:
'
help-block text-danger
'
}).
html
(
data
.
msg
).
insertAfter
(
$
(
'
#id_users
'
));
}
else
{
$
(
'
#id_created
'
).
html
(
data
.
created_info
);
$
(
'
#id_created_detail
'
).
html
(
data
.
created
.
join
(
'
,
'
));
$
(
'
#id_updated
'
).
html
(
data
.
updated_info
);
$
(
'
#id_updated_detail
'
).
html
(
data
.
updated
.
join
(
'
,
'
));
$
(
'
#id_failed
'
).
html
(
data
.
failed_info
);
$
(
'
#id_failed_detail
'
).
html
(
data
.
failed
.
join
(
'
,
'
));
var
$data_table
=
$
(
'
#asset_list_table
'
).
DataTable
();
$data_table
.
ajax
.
reload
();
}
})
});
}
$form
.
ajaxSubmit
({
success
:
success
});
})
});
</script>
...
...
apps/assets/urls/views_urls.py
浏览文件 @
3aea9941
...
...
@@ -9,6 +9,8 @@ urlpatterns = [
url
(
r
'^$'
,
views
.
AssetListView
.
as_view
(),
name
=
'asset-index'
),
url
(
r
'^asset/$'
,
views
.
AssetListView
.
as_view
(),
name
=
'asset-list'
),
url
(
r
'^asset/create/$'
,
views
.
AssetCreateView
.
as_view
(),
name
=
'asset-create'
),
url
(
r
'^asset/export/$'
,
views
.
AssetExportView
.
as_view
(),
name
=
'asset-export'
),
url
(
r
'^asset/import/$'
,
views
.
BulkImportAssetView
.
as_view
(),
name
=
'asset-import'
),
url
(
r
'^asset/(?P<pk>[0-9]+)/$'
,
views
.
AssetDetailView
.
as_view
(),
name
=
'asset-detail'
),
url
(
r
'^asset/(?P<pk>[0-9]+)/update/$'
,
views
.
AssetUpdateView
.
as_view
(),
name
=
'asset-update'
),
url
(
r
'^asset/(?P<pk>[0-9]+)/delete/$'
,
views
.
AssetDeleteView
.
as_view
(),
name
=
'asset-delete'
),
...
...
apps/assets/views.py
浏览文件 @
3aea9941
...
...
@@ -9,6 +9,7 @@ from openpyxl import load_workbook
from
django.utils.translation
import
ugettext
as
_
from
django.conf
import
settings
from
django.db.models
import
Q
from
django.db
import
IntegrityError
from
django.views.generic
import
TemplateView
,
ListView
,
View
from
django.views.generic.edit
import
CreateView
,
DeleteView
,
FormView
,
UpdateView
from
django.urls
import
reverse_lazy
...
...
@@ -21,10 +22,11 @@ from django.utils.decorators import method_decorator
from
django.core.cache
import
cache
from
django.utils
import
timezone
from
common.utils
import
int_seq
from
.utils
import
CreateAssetTagsMiXin
,
UpdateAssetTagsMiXin
from
.models
import
Asset
,
AssetGroup
,
IDC
,
AdminUser
,
SystemUser
,
Tag
from
.forms
import
*
from
common.mixins
import
JSONResponseMixin
from
common.utils
import
get_object_or_none
from
.utils
import
CreateAssetTagsMiXin
,
UpdateAssetTagsMiXin
from
.
import
forms
from
.models
import
Asset
,
AssetGroup
,
AdminUser
,
IDC
,
SystemUser
,
Tag
from
.hands
import
AdminUserRequiredMixin
...
...
@@ -45,7 +47,7 @@ class AssetListView(AdminUserRequiredMixin, TemplateView):
class
AssetCreateView
(
AdminUserRequiredMixin
,
CreateAssetTagsMiXin
,
CreateView
):
model
=
Asset
tag_type
=
'asset'
form_class
=
AssetCreateForm
form_class
=
forms
.
AssetCreateForm
template_name
=
'assets/asset_create.html'
success_url
=
reverse_lazy
(
'assets:asset-list'
)
...
...
@@ -71,7 +73,7 @@ class AssetCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, CreateView):
class
AssetModalCreateView
(
AdminUserRequiredMixin
,
CreateAssetTagsMiXin
,
ListView
):
model
=
Asset
form_class
=
AssetCreateForm
form_class
=
forms
.
AssetCreateForm
template_name
=
'assets/asset_modal_update.html'
success_url
=
reverse_lazy
(
'assets:asset-list'
)
...
...
@@ -99,7 +101,7 @@ class AssetModalCreateView(AdminUserRequiredMixin, CreateAssetTagsMiXin, ListVie
class
AssetUpdateView
(
AdminUserRequiredMixin
,
UpdateAssetTagsMiXin
,
UpdateView
):
model
=
Asset
form_class
=
AssetCreateForm
form_class
=
forms
.
AssetCreateForm
template_name
=
'assets/asset_update.html'
success_url
=
reverse_lazy
(
'assets:asset-list'
)
new_form
=
''
...
...
@@ -226,7 +228,7 @@ class AssetModalListView(AdminUserRequiredMixin, ListView):
class
AssetGroupCreateView
(
AdminUserRequiredMixin
,
CreateView
):
model
=
AssetGroup
form_class
=
AssetGroupForm
form_class
=
forms
.
AssetGroupForm
template_name
=
'assets/asset_group_create.html'
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
#ordering = '-id'
...
...
@@ -287,7 +289,7 @@ class AssetGroupDetailView(AdminUserRequiredMixin, DetailView):
class
AssetGroupUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
AssetGroup
form_class
=
AssetGroupForm
form_class
=
forms
.
AssetGroupForm
template_name
=
'assets/asset_group_create.html'
success_url
=
reverse_lazy
(
'assets:asset-group-list'
)
...
...
@@ -329,7 +331,7 @@ class IDCListView(AdminUserRequiredMixin, TemplateView):
class
IDCCreateView
(
AdminUserRequiredMixin
,
CreateView
):
model
=
IDC
form_class
=
IDCForm
form_class
=
forms
.
IDCForm
template_name
=
'assets/idc_create_update.html'
success_url
=
reverse_lazy
(
'assets:idc-list'
)
...
...
@@ -351,7 +353,7 @@ class IDCCreateView(AdminUserRequiredMixin, CreateView):
class
IDCUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
IDC
form_class
=
IDCForm
form_class
=
forms
.
IDCForm
template_name
=
'assets/idc_create_update.html'
context_object_name
=
'idc'
success_url
=
reverse_lazy
(
'assets:idc-list'
)
...
...
@@ -420,7 +422,7 @@ class AdminUserListView(AdminUserRequiredMixin, TemplateView):
class
AdminUserCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
AdminUser
form_class
=
AdminUserForm
form_class
=
forms
.
AdminUserForm
template_name
=
'assets/admin_user_create_update.html'
success_url
=
reverse_lazy
(
'assets:admin-user-list'
)
...
...
@@ -446,7 +448,7 @@ class AdminUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVie
class
AdminUserUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
AdminUser
form_class
=
AdminUserForm
form_class
=
forms
.
AdminUserForm
template_name
=
'assets/admin_user_create_update.html'
def
get_context_data
(
self
,
**
kwargs
):
...
...
@@ -504,7 +506,7 @@ class SystemUserListView(AdminUserRequiredMixin, TemplateView):
class
SystemUserCreateView
(
AdminUserRequiredMixin
,
SuccessMessageMixin
,
CreateView
):
model
=
SystemUser
form_class
=
SystemUserForm
form_class
=
forms
.
SystemUserForm
template_name
=
'assets/system_user_create_update.html'
success_url
=
reverse_lazy
(
'assets:system-user-list'
)
...
...
@@ -528,7 +530,7 @@ class SystemUserCreateView(AdminUserRequiredMixin, SuccessMessageMixin, CreateVi
class
SystemUserUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
SystemUser
form_class
=
SystemUserForm
form_class
=
forms
.
SystemUserForm
template_name
=
'assets/system_user_create_update.html'
def
get_context_data
(
self
,
**
kwargs
):
...
...
@@ -630,7 +632,7 @@ class TagsListView(AdminUserRequiredMixin, ListView):
class
AssetTagCreateView
(
AdminUserRequiredMixin
,
CreateView
):
model
=
Tag
form_class
=
AssetTagForm
form_class
=
forms
.
AssetTagForm
template_name
=
'assets/asset_tag_create.html'
success_url
=
reverse_lazy
(
'assets:asset-tag-list'
)
#ordering = '-id'
...
...
@@ -679,7 +681,7 @@ class AssetTagDetailView(SingleObjectMixin, AdminUserRequiredMixin, ListView):
class
AssetTagUpdateView
(
AdminUserRequiredMixin
,
UpdateView
):
model
=
Tag
form_class
=
AssetTagForm
form_class
=
forms
.
AssetTagForm
template_name
=
'assets/asset_tag_create.html'
success_url
=
reverse_lazy
(
'assets:asset-tag-list'
)
...
...
@@ -707,13 +709,15 @@ class AssetTagDeleteView(AdminUserRequiredMixin, DeleteView):
@
method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
ExportAsse
tView
(
View
):
class
AssetExpor
tView
(
View
):
@
staticmethod
def
asset_g
et_attr
(
asset
,
attr
):
def
get_ass
et_attr
(
asset
,
attr
):
if
attr
in
[
'admin_user'
,
'idc'
]:
return
getattr
(
asset
,
attr
).
name
if
attr
in
[
'status'
,
'tyoe'
,
'env'
]:
return
getattr
(
asset
,
'get_{}_display'
)
elif
attr
in
[
'status'
,
'type'
,
'env'
]:
return
getattr
(
asset
,
'get_{}_display'
.
format
(
attr
))()
else
:
return
getattr
(
asset
,
attr
)
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
spm
=
request
.
GET
.
get
(
'spm'
,
''
)
...
...
@@ -725,16 +729,15 @@ class ExportAssetView(View):
wb
=
Workbook
()
ws
=
wb
.
active
ws
.
title
=
'Asset'
header
=
[
'hostname'
,
'ip'
,
'port'
,
'admin_user'
,
'system_users'
,
'idc'
,
'cpu'
,
'memory'
,
'disk'
,
'mac_address'
,
'other_ip'
,
'remote_card_ip'
,
'os'
,
'cabinet_no'
,
'cabinet_pos'
,
'number'
,
'status'
,
'type'
,
'env'
,
'sn'
,
'comment'
]
header
=
[
'hostname'
,
'ip'
,
'port'
,
'admin_user'
,
'idc'
,
'cpu'
,
'memory'
,
'disk'
,
'mac_address'
,
'other_ip'
,
'remote_card_ip'
,
'os'
,
'cabinet_no'
,
'cabinet_pos'
,
'number'
,
'status'
,
'type'
,
'env'
,
'sn'
,
'comment'
]
ws
.
append
(
header
)
for
asset
in
assets
:
ws
.
append
([
get
attr
(
asset
,
attr
)
for
attr
in
header
])
ws
.
append
([
self
.
get_asset_
attr
(
asset
,
attr
)
for
attr
in
header
])
filename
=
'
user
s-{}.xlsx'
.
format
(
timezone
.
localtime
(
timezone
.
now
()).
strftime
(
'%Y-%m-%d_%H-%M-%S'
))
filename
=
'
asset
s-{}.xlsx'
.
format
(
timezone
.
localtime
(
timezone
.
now
()).
strftime
(
'%Y-%m-%d_%H-%M-%S'
))
response
=
HttpResponse
(
save_virtual_workbook
(
wb
),
content_type
=
'application/vnd.ms-excel'
)
response
[
'Content-Disposition'
]
=
'attachment; filename="%s"'
%
filename
return
response
...
...
@@ -742,9 +745,89 @@ class ExportAssetView(View):
def
post
(
self
,
request
,
*
args
,
**
kwargs
):
try
:
assets_id
=
json
.
loads
(
request
.
body
).
get
(
'assets_id'
,
[])
print
(
assets_id
)
except
ValueError
:
return
HttpResponse
(
'Json object not valid'
,
status
=
400
)
spm
=
uuid
.
uuid4
().
get_hex
()
cache
.
set
(
spm
,
assets_id
,
300
)
url
=
reverse
(
'
users:export-user-csv
'
)
+
'?spm=%s'
%
spm
url
=
reverse
(
'
assets:asset-export
'
)
+
'?spm=%s'
%
spm
return
JsonResponse
({
'redirect'
:
url
})
class
BulkImportAssetView
(
AdminUserRequiredMixin
,
JSONResponseMixin
,
FormView
):
form_class
=
forms
.
FileForm
def
form_valid
(
self
,
form
):
try
:
wb
=
load_workbook
(
form
.
cleaned_data
[
'file'
])
ws
=
wb
.
get_active_sheet
()
except
Exception
as
e
:
print
(
e
)
data
=
{
'valid'
:
False
,
'msg'
:
'Not a valid Excel file'
}
return
self
.
render_json_response
(
data
)
rows
=
ws
.
rows
header_all
=
[
'hostname'
,
'ip'
,
'port'
,
'admin_user'
,
'idc'
,
'cpu'
,
'memory'
,
'disk'
,
'mac_address'
,
'other_ip'
,
'remote_card_ip'
,
'os'
,
'cabinet_no'
,
'cabinet_pos'
,
'number'
,
'status'
,
'type'
,
'env'
,
'sn'
,
'comment'
]
header_min
=
[
'hostname'
,
'ip'
,
'port'
,
'admin_user'
,
'comment'
]
header
=
[
col
.
value
for
col
in
next
(
rows
)]
if
header
not
in
header_all
and
header_min
not
in
header
:
data
=
{
'valid'
:
False
,
'msg'
:
'Must be same format as template or export file'
}
return
self
.
render_json_response
(
data
)
created
=
[]
updated
=
[]
failed
=
[]
for
row
in
rows
:
asset_dict
=
dict
(
zip
(
header
,
[
col
.
value
for
col
in
row
]))
if
asset_dict
.
get
(
'admin_user'
,
None
):
admin_user
=
get_object_or_none
(
AdminUser
,
name
=
asset_dict
[
'admin_user'
])
asset_dict
[
'admin_user'
]
=
admin_user
if
asset_dict
.
get
(
'idc'
):
idc
=
get_object_or_none
(
IDC
,
name
=
asset_dict
[
'idc'
])
asset_dict
[
'idc'
]
=
idc
if
asset_dict
.
get
(
'type'
):
asset_display_type_map
=
dict
(
zip
(
dict
(
Asset
.
TYPE_CHOICES
).
values
,
dict
(
Asset
.
TYPE_CHOICES
).
keys
()))
asset_type
=
asset_display_type_map
.
get
(
asset_dict
[
'type'
],
'Server'
)
asset_dict
[
'type'
]
=
asset_type
if
asset_dict
.
get
(
'status'
):
asset_display_status_map
=
dict
(
zip
(
dict
(
Asset
.
STATUS_CHOICES
).
values
,
dict
(
Asset
.
STATUS_CHOICES
).
keys
()))
asset_status
=
asset_display_status_map
.
get
(
asset_dict
[
'status'
],
'In use'
)
asset_dict
[
'status'
]
=
asset_status
if
asset_dict
.
get
(
'env'
):
asset_display_env_map
=
dict
(
zip
(
dict
(
Asset
.
ENV_CHOICES
).
values
(),
dict
(
Asset
.
ENV_CHOICES
).
keys
()))
asset_env
=
asset_display_env_map
.
get
(
asset_dict
[
'env'
],
'Prod'
)
asset_dict
[
'env'
]
=
asset_env
try
:
Asset
.
objects
.
create
(
**
asset_dict
)
created
.
append
(
asset_dict
[
'ip'
])
except
IntegrityError
as
e
:
asset
=
Asset
.
objects
.
filter
(
ip
=
asset_dict
[
'ip'
],
port
=
asset_dict
[
'port'
])
if
not
asset
:
failed
.
append
(
asset_dict
[
'ip'
])
continue
asset
.
update
(
**
asset_dict
)
updated
.
append
(
asset_dict
[
'ip'
])
except
TypeError
as
e
:
print
(
e
)
failed
.
append
(
asset_dict
[
'ip'
])
data
=
{
'created'
:
created
,
'created_info'
:
'Created {}'
.
format
(
len
(
created
)),
'updated'
:
updated
,
'updated_info'
:
'Updated {}'
.
format
(
len
(
updated
)),
'failed'
:
failed
,
'failed_info'
:
'Failed {}'
.
format
(
len
(
failed
)),
'valid'
:
True
,
'msg'
:
'Created: {}. Updated: {}, Error: {}'
.
format
(
len
(
created
),
len
(
updated
),
len
(
failed
))
}
return
self
.
render_json_response
(
data
)
apps/fixtures/fake.json
浏览文件 @
3aea9941
此差异已折叠。
点击以展开。
apps/users/templates/users/user_list.html
浏览文件 @
3aea9941
...
...
@@ -99,7 +99,7 @@ $(document).ready(function(){
users
.
push
(
obj
.
id
)
});
$
.
ajax
({
url
:
"
{% url
"
users
:
export
-
user
"
%}
"
,
url
:
"
{% url
'users:user-export'
%}
"
,
method
:
'
POST
'
,
data
:
JSON
.
stringify
({
users_id
:
users
}),
dataType
:
"
json
"
,
...
...
apps/users/urls/views_urls.py
浏览文件 @
3aea9941
...
...
@@ -23,6 +23,7 @@ urlpatterns = [
name
=
'user-asset-permission-create'
),
url
(
r
'^user/(?P<pk>[0-9]+)/assets'
,
views
.
UserGrantedAssetView
.
as_view
(),
name
=
'user-granted-asset'
),
url
(
r
'^user/(?P<pk>[0-9]+)/login-history'
,
views
.
UserDetailView
.
as_view
(),
name
=
'user-login-history'
),
url
(
r
'^user/export/'
,
views
.
UserExportView
.
as_view
(),
name
=
'user-export'
),
url
(
r
'^first-login/$'
,
views
.
UserFirstLoginView
.
as_view
(),
name
=
'user-first-login'
),
url
(
r
'^user/import/$'
,
views
.
BulkImportUserView
.
as_view
(),
name
=
'user-import'
),
# url(r'^user/(?P<pk>[0-9]+)/assets-perm$', views.UserDetailView.as_view(), name='user-detail'),
...
...
@@ -40,5 +41,4 @@ urlpatterns = [
name
=
'user-group-asset-permission-create'
),
url
(
r
'^user-group/(?P<pk>[0-9]+)/assets'
,
views
.
UserGroupGrantedAssetView
.
as_view
(),
name
=
'user-group-granted-asset'
),
url
(
r
'^export/user/'
,
views
.
ExportUserView
.
as_view
(),
name
=
'export-user'
),
]
apps/users/views.py
浏览文件 @
3aea9941
...
...
@@ -557,7 +557,7 @@ class BulkImportUserView(AdminUserRequiredMixin, JSONResponseMixin, FormView):
@
method_decorator
(
csrf_exempt
,
name
=
'dispatch'
)
class
ExportUser
View
(
View
):
class
UserExport
View
(
View
):
def
get
(
self
,
request
,
*
args
,
**
kwargs
):
spm
=
request
.
GET
.
get
(
'spm'
,
''
)
users_id
=
cache
.
get
(
spm
)
...
...
@@ -588,6 +588,6 @@ class ExportUserView(View):
return
HttpResponse
(
'Json object not valid'
,
status
=
400
)
spm
=
uuid
.
uuid4
().
get_hex
()
cache
.
set
(
spm
,
users_id
,
300
)
url
=
reverse
(
'users:
export-user-csv
'
)
+
'?spm=%s'
%
spm
url
=
reverse
(
'users:
user-export
'
)
+
'?spm=%s'
%
spm
return
JsonResponse
({
'redirect'
:
url
})
utils/clean_migrations.sh
浏览文件 @
3aea9941
...
...
@@ -2,5 +2,5 @@
#
for
app
in
users
assets perms audits teminal ops
;
do
rm
-f
$app
/migrations/000
*
rm
-f
../apps/
$app
/migrations/000
*
done
utils/make_fake_json.sh
浏览文件 @
3aea9941
#!/bin/bash
#
python ../apps/manage.py shell
<<
EOF
from users.models import *
generate_fake()
from assets.models import *
generate_fake()
EOF
python ../apps/manage.py dbshell
<<
EOF
delete from django_content_type;
delete from auth_permission;
EOF
python ../apps/manage.py dumpdata
>
../apps/fixtures/
init
.json
python ../apps/manage.py dumpdata
>
../apps/fixtures/
fake
.json
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录