Commit 1b9c9c48 authored by ibuler's avatar ibuler

Merge branch 'cmdb'

parents 22e20d29 0604f76f
#!/usr/bin/env python #!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
if __name__ == '__main__': if __name__ == '__main__':
pass pass
...@@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer): ...@@ -22,7 +22,8 @@ class IDCSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = IDC model = IDC
#fields = ('id', 'title', 'code', 'linenos', 'language', 'style') #fields = ('id', 'title', 'code', 'linenos', 'language', 'style')
class AssetGroupViewSet(viewsets.ModelViewSet): class AssetGroupViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows AssetGroup to be viewed or edited. API endpoint that allows AssetGroup to be viewed or edited.
...@@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet): ...@@ -30,6 +31,7 @@ class AssetGroupViewSet(viewsets.ModelViewSet):
queryset = AssetGroup.objects.all() queryset = AssetGroup.objects.all()
serializer_class = AssetGroupSerializer serializer_class = AssetGroupSerializer
class AssetViewSet(viewsets.ModelViewSet): class AssetViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows Asset to be viewed or edited. API endpoint that allows Asset to be viewed or edited.
...@@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet): ...@@ -37,6 +39,7 @@ class AssetViewSet(viewsets.ModelViewSet):
queryset = Asset.objects.all() queryset = Asset.objects.all()
serializer_class = AssetSerializer serializer_class = AssetSerializer
class IDCViewSet(viewsets.ModelViewSet): class IDCViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows IDC to be viewed or edited. API endpoint that allows IDC to be viewed or edited.
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
from django import forms from django import forms
from .models import IDC, Asset, AssetGroup from .models import IDC, Asset, AssetGroup
from django.utils.translation import gettext_lazy as _
class AssetForm(forms.ModelForm): class AssetForm(forms.ModelForm):
...@@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm): ...@@ -10,11 +11,15 @@ class AssetForm(forms.ModelForm):
model = Asset model = Asset
fields = [ fields = [
"ip", "other_ip", "hostname", "port", "group", "username", "password", "idc", "mac_addr", "ip", "other_ip", "remote_card_ip", "hostname", "port", "groups", "username", "password",
"remote_card_ip", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos", "idc", "mac_addr", "brand", "cpu", "memory", "disk", "os", "cabinet_no", "cabinet_pos",
"number", "status", "type", "env", "sn", "is_active", "comment" "number", "status", "type", "env", "sn", "is_active", "comment"
] ]
widgets = {
'groups': forms.SelectMultiple(attrs={'class': 'select2', 'data-placeholder': _('Join assetgroups')}),
}
class AssetGroupForm(forms.ModelForm): class AssetGroupForm(forms.ModelForm):
class Meta: class Meta:
......
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-09-03 14:30
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Asset',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('ip', models.CharField(blank=True, max_length=32, verbose_name='\u8d44\u4ea7IP')),
('other_ip', models.CharField(blank=True, max_length=255, verbose_name='\u5176\u4ed6IP')),
('remote_card_ip', models.CharField(blank=True, max_length=16, verbose_name='\u8fdc\u63a7\u5361IP')),
('hostname', models.CharField(blank=True, max_length=128, unique=True, verbose_name='\u4e3b\u673a\u540d')),
('port', models.IntegerField(blank=True, verbose_name='\u7aef\u53e3')),
('username', models.CharField(blank=True, max_length=16, verbose_name='\u7ba1\u7406\u7528\u6237\u540d')),
('password', models.CharField(blank=True, max_length=256, verbose_name='\u5bc6\u7801')),
('mac_addr', models.CharField(blank=True, max_length=20, unique=True, verbose_name='MAC\u5730\u5740')),
('brand', models.CharField(blank=True, max_length=64, verbose_name='\u786c\u4ef6\u5382\u5546\u578b\u53f7')),
('cpu', models.CharField(blank=True, max_length=64, verbose_name='CPU')),
('memory', models.CharField(blank=True, max_length=128, verbose_name='\u5185\u5b58')),
('disk', models.CharField(blank=True, max_length=1024, verbose_name='\u786c\u76d8')),
('os', models.CharField(blank=True, max_length=128, verbose_name='\u7cfb\u7edf\u4fe1\u606f')),
('cabinet_no', models.CharField(blank=True, max_length=32, verbose_name='\u673a\u67dc\u53f7')),
('cabinet_pos', models.IntegerField(blank=True, null=True, verbose_name='\u8d44\u4ea7\u4f4d\u7f6e')),
('number', models.CharField(blank=True, max_length=32, unique=True, verbose_name='\u8d44\u4ea7\u7f16\u53f7')),
('sn', models.CharField(blank=True, max_length=128, unique=True, verbose_name='SN\u7f16\u53f7')),
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
('is_active', models.BooleanField(default=True, verbose_name='\u662f\u5426\u6fc0\u6d3b')),
('date_added', models.DateTimeField(auto_now=True, null=True)),
('comment', models.CharField(blank=True, max_length=128, verbose_name='\u5907\u6ce8')),
],
options={
'db_table': 'asset',
},
),
migrations.CreateModel(
name='AssetExtend',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
),
migrations.CreateModel(
name='AssetGroup',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=64, unique=True)),
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
('comment', models.CharField(blank=True, max_length=128, null=True)),
],
options={
'db_table': 'assetgroup',
},
),
migrations.CreateModel(
name='IDC',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=32, verbose_name='\u673a\u623f\u540d\u79f0')),
('bandwidth', models.CharField(blank=True, max_length=32, verbose_name='\u673a\u623f\u5e26\u5bbd')),
('contact', models.CharField(blank=True, max_length=16, verbose_name='\u8054\u7cfb\u4eba')),
('phone', models.CharField(blank=True, max_length=32, verbose_name='\u8054\u7cfb\u7535\u8bdd')),
('address', models.CharField(blank=True, max_length=128, verbose_name='\u673a\u623f\u5730\u5740')),
('network', models.TextField(blank=True, verbose_name='IP\u5730\u5740\u6bb5')),
('date_added', models.DateField(auto_now=True, null=True)),
('operator', models.CharField(blank=True, max_length=32, verbose_name='\u8fd0\u8425\u5546')),
('created_by', models.CharField(blank=True, max_length=32, verbose_name='\u521b\u5efa\u8005')),
('comment', models.CharField(blank=True, max_length=128, verbose_name='\u5907\u6ce8')),
],
options={
'db_table': 'idc',
'verbose_name': 'IDC\u673a\u623f',
'verbose_name_plural': 'IDC\u673a\u623f',
},
),
migrations.AddField(
model_name='asset',
name='env',
field=models.ManyToManyField(blank=True, related_name='asset_env_extend', to='assets.AssetExtend', verbose_name='\u6240\u5c5e\u4e3b\u673a\u7ec4\u73af\u5883'),
),
migrations.AddField(
model_name='asset',
name='group',
field=models.ManyToManyField(blank=True, to='assets.AssetGroup', verbose_name='\u6240\u5c5e\u4e3b\u673a\u7ec4'),
),
migrations.AddField(
model_name='asset',
name='idc',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='assets.IDC', verbose_name='\u673a\u623f'),
),
migrations.AddField(
model_name='asset',
name='status',
field=models.ManyToManyField(blank=True, related_name='asset_status_extend', to='assets.AssetExtend', verbose_name='\u8d44\u4ea7\u72b6\u6001'),
),
migrations.AddField(
model_name='asset',
name='type',
field=models.ManyToManyField(blank=True, related_name='asset_type_extend', to='assets.AssetExtend', verbose_name='\u8d44\u4ea7\u7c7b\u578b'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-21 09:57
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='asset',
name='cabinet_pos',
field=models.IntegerField(blank=True, max_length=4, verbose_name='\u673a\u5668\u4f4d\u7f6e'),
),
]
# -*- coding: utf-8 -*-
# Generated by Django 1.10 on 2016-08-21 09:59
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('assets', '0002_auto_20160821_1757'),
]
operations = [
migrations.AlterField(
model_name='asset',
name='cabinet_pos',
field=models.IntegerField(blank=True, max_length=4, null=True, verbose_name='\u673a\u5668\u4f4d\u7f6e'),
),
]
# coding:utf-8 # coding:utf-8
from __future__ import unicode_literals from __future__ import unicode_literals, absolute_import
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _
class AssetGroup(models.Model): class AssetGroup(models.Model):
name = models.CharField(max_length=64, unique=True) name = models.CharField(max_length=64, unique=True, null=True, blank=True, verbose_name=_('Name'))
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者") created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
comment = models.CharField(max_length=128, blank=True, null=True) comment = models.TextField(blank=True, verbose_name=_('Comment'))
def __unicode__(self): def __unicode__(self):
return self.name return self.name
...@@ -17,71 +18,137 @@ class AssetGroup(models.Model): ...@@ -17,71 +18,137 @@ class AssetGroup(models.Model):
class IDC(models.Model): class IDC(models.Model):
name = models.CharField(max_length=32, verbose_name=u'机房名称') name = models.CharField(max_length=32, verbose_name=_('Name'))
bandwidth = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'机房带宽') bandwidth = models.CharField(max_length=32, blank=True, verbose_name=_('Bandwidth'))
contact = models.CharField(max_length=16, blank=True, null=True, default='', verbose_name=u'联系人') contact = models.CharField(max_length=16, blank=True, verbose_name=_('Contact'))
phone = models.CharField(max_length=32, blank=True, null=True, default='', verbose_name=u'联系电话') phone = models.CharField(max_length=32, blank=True, verbose_name=_('Phone'))
address = models.CharField(max_length=128, blank=True, null=True, default='', verbose_name=u"机房地址") address = models.CharField(max_length=128, blank=True, verbose_name=_("Address"))
network = models.TextField(blank=True, null=True, default='', verbose_name=u"IP地址段") network = models.TextField(blank=True, verbose_name=_('Network'))
date_added = models.DateField(auto_now=True, null=True) date_added = models.DateField(auto_now=True, null=True, verbose_name=_('Date added'))
operator = models.CharField(max_length=32, blank=True, default='', null=True, verbose_name=u"运营商") operator = models.CharField(max_length=32, blank=True, verbose_name=_('Operator'))
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者") created_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
comment = models.CharField(max_length=128, blank=True, default='', null=True, verbose_name=u"备注") comment = models.TextField(blank=True, verbose_name=_('Comment'))
def __unicode__(self): def __unicode__(self):
return self.name return self.name
class Meta: class Meta:
db_table = 'idc' db_table = 'idc'
verbose_name = u"IDC机房"
verbose_name_plural = verbose_name
class AssetExtend(models.Model): class AssetExtend(models.Model):
pass key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
comment = models.TextField(blank=True, verbose_name=_('Comment'))
def __unicode__(self):
return self.name
class Meta:
db_table = 'assetextend'
class Asset(models.Model):
ip = models.CharField(max_length=32, blank=True, verbose_name="主机IP") class AdminUser(models.Model):
other_ip = models.CharField(max_length=255, blank=True, null=True, verbose_name="其他IP") name = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Name'))
remote_card_ip = models.CharField(max_length=16, blank=True, null=True, verbose_name=u'远控卡IP') username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Username'))
hostname = models.CharField(unique=True, max_length=128, verbose_name=u"主机名") password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_('Password'))
port = models.IntegerField(blank=True, null=True, verbose_name=u"端口号") private_key = models.CharField(max_length=4096, null=True, blank=True, verbose_name=_('SSH private key'))
group = models.ManyToManyField(AssetGroup, blank=True, verbose_name=u"所属主机组") is_default = models.BooleanField(default=True, verbose_name=_('As default'))
username = models.CharField(max_length=16, blank=True, null=True, verbose_name=u"管理用户名") auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key'))
password = models.CharField(max_length=256, blank=True, null=True, verbose_name=u"密码") date_added = models.DateTimeField(auto_now=True, null=True, blank=True)
idc = models.ForeignKey(IDC, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=u'机房') create_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
mac_addr = models.CharField(max_length=20, blank=True, null=True, verbose_name=u"MAC地址") comment = models.TextField(blank=True, verbose_name=_('Comment'))
brand = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'硬件厂商型号')
cpu = models.CharField(max_length=64, blank=True, null=True, verbose_name=u'CPU')
memory = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'内存')
disk = models.CharField(max_length=1024, blank=True, null=True, verbose_name=u'硬盘')
os = models.CharField(max_length=128, blank=True, null=True, verbose_name=u'系统信息')
cabinet_no = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'机柜号')
cabinet_pos = models.IntegerField(blank=True, null=True, verbose_name=u'机器位置')
number = models.CharField(max_length=32, blank=True, null=True, verbose_name=u'资产编号')
status = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_status_extend", verbose_name="机器状态")
type = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_type_extend", verbose_name="机器类型")
env = models.ManyToManyField(AssetExtend, blank=True, related_name="asset_env_extend", verbose_name="所属主机组环境")
sn = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"SN编号")
created_by = models.CharField(max_length=32, blank=True, null=True, verbose_name=u"创建者")
is_active = models.BooleanField(default=True, verbose_name=u"是否激活")
date_added = models.DateTimeField(auto_now=True, null=True)
comment = models.CharField(max_length=128, blank=True, null=True, verbose_name=u"备注")
def __unicode__(self): def __unicode__(self):
return self.ip return self.name
class Meta: class Meta:
db_table = 'asset' db_table = 'adminuser'
class SysUser(models.Model):
PROTOCOL_CHOICES = (
('ssh', 'ssh'),
('telnet', 'telnet'),
)
name = models.CharField(max_length=128, unique=True, verbose_name=_('Name'))
username = models.CharField(max_length=16, blank=True, verbose_name=_('Username'))
password = models.CharField(max_length=256, blank=True, verbose_name=_('Password'))
protocol = models.CharField(max_length=16, default='ssh', verbose_name=_('Protocol'))
private_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH private key'))
public_key = models.CharField(max_length=4096, blank=True, verbose_name=_('SSH public key'))
is_default = models.BooleanField(default=True, verbose_name=_('As default'))
auto_push = models.BooleanField(default=True, verbose_name=_('Auto push'))
auto_update = models.BooleanField(default=True, verbose_name=_('Auto update pass/key'))
sudo = models.TextField(max_length=4096, blank=True, verbose_name=_('Sudo'))
shell = models.CharField(max_length=64, blank=True, verbose_name=_('Shell'))
home = models.CharField(max_length=64, blank=True, verbose_name=_('Home'))
uid = models.IntegerField(blank=True, verbose_name=_('Uid'))
date_added = models.DateTimeField(auto_now=True, null=True)
create_by = models.CharField(max_length=32, blank=True, verbose_name=_('Created by'))
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
def __unicode__(self):
return self.name
class Meta:
db_table = 'sysuser'
class Asset(models.Model):
ip = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('IP'))
other_ip = models.CharField(max_length=255, null=True, blank=True, verbose_name=_('Other IP'))
remote_card_ip = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Remote card IP'))
hostname = models.CharField(max_length=128, unique=True, null=True, blank=True, verbose_name=_('Hostname'))
port = models.IntegerField(null=True, blank=True, verbose_name=_('Port'))
groups = models.ManyToManyField(AssetGroup, null=True, blank=True, verbose_name=_('Asset groups'))
username = models.CharField(max_length=16, null=True, blank=True, verbose_name=_('Admin user'))
password = models.CharField(max_length=256, null=True, blank=True, verbose_name=_("Admin password"))
admin_user = models.ForeignKey(AdminUser, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_("Admin User"))
sys_user = models.ManyToManyField(SysUser, null=True, blank=True, verbose_name=_("Sys User"))
idc = models.ForeignKey(IDC, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('IDC'))
mac_addr = models.CharField(max_length=20, null=True, blank=True, verbose_name=_("Mac address"))
brand = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('Brand'))
cpu = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('CPU'))
memory = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Memory'))
disk = models.CharField(max_length=1024, null=True, blank=True, verbose_name=_('Disk'))
os = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('OS'))
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, unique=True, verbose_name=_('Asset number'))
status = models.ManyToManyField(AssetExtend, related_name="asset_status_extend", verbose_name=_('Asset status'))
type = models.ManyToManyField(AssetExtend, related_name="asset_type_extend", verbose_name=_('Asset type'))
env = models.ManyToManyField(AssetExtend, related_name="asset_env_extend", verbose_name=_('Asset environment'))
sn = models.CharField(max_length=128, null=True, blank=True, unique=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'))
date_added = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Date added'))
comment = models.CharField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
def __unicode__(self):
return self.ip
def initial(self):
pass
class Meta:
db_table = 'asset'
index_together = ('ip', 'port')
class Label(models.Model):
key = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('KEY'))
value = models.CharField(max_length=64, null=True, blank=True, verbose_name=_('VALUE'))
asset = models.ForeignKey(Asset, null=True, blank=True, on_delete=models.SET_NULL, verbose_name=_('Asset'))
created_by = models.CharField(max_length=32, blank=True, verbose_name=_("Created by"))
date_added = models.DateTimeField(auto_now=True, null=True)
comment = models.CharField(max_length=128, blank=True, verbose_name=_('Comment'))
def __unicode__(self):
return self.name
class Meta:
db_table = 'label'
{% extends 'base.html' %} {% extends 'base.html' %}
{% load static %}
{% load bootstrap %} {% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %}
{% block content %} {% block content %}
<div class="wrapper wrapper-content animated fadeInRight"> <div class="wrapper wrapper-content animated fadeInRight">
<div class="row"> <div class="row">
<div class="col-sm-10"> <div class="col-sm-10">
<div class="ibox float-e-margins"> <div class="ibox float-e-margins">
<div id="ibox-content" class="ibox-title"> <div id="ibox-content" class="ibox-title">
<h5> 填写资产基本信息 </h5> <h5> 添加资产 </h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -22,81 +27,73 @@ ...@@ -22,81 +27,73 @@
<div class="ibox-content"> <div class="ibox-content">
<div class="panel blank-panel"> <div class="panel blank-panel">
<div class="panel-options">
<ul class="nav nav-tabs">
<li class="active"><a href="{% url 'assets:asset-add' %}" class="text-center"><i class="fa fa-laptop"></i> 单台添加 </a></li>
{# <li><a href="{% url 'asset_add_batch' %}" class="text-center"><i class="fa fa-bar-chart-o"></i> 批量添加 </a></li>#}
</ul>
</div>
<div class="panel-body"> <div class="panel-body">
<div class="tab-content"> <div class="tab-content">
<div id="tab-1" class="ibox float-e-margins tab-pane active"> <div id="tab-1" class="ibox float-e-margins tab-pane active"></div>
{% if error %}
<div class="alert alert-warning text-center">{{ error }}</div>
{% endif %}
{% if msg %}
<div class="alert alert-success text-center">{{ msg }}</div>
{% endif %}
<form id="assetForm" method="post" class="form-horizontal"> <form id="assetForm" method="post" class="form-horizontal">
{% csrf_token %} {% csrf_token %}
<h3 class="widget-head-color-box">基本信息</h3>
{{ form.hostname|bootstrap_horizontal }} {{ form.hostname|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
{{ form.ip|bootstrap_horizontal }} {{ form.ip|bootstrap_horizontal }}
<p class="col-sm-offset-2">Tips: 如果IP地址不填写, IP默认会设置与主机名一致</p>
{# <div class="hr-line-dashed"></div>#}
{# <div class="form-group">#}
{# <label for="j_group" class="col-sm-2 control-label">管理用户<span class="red-fonts"> *</span></label>#}
{# <div class="col-sm-2">#}
{# <div class="radio i-checks">#}
{# <label style="padding-left: 0">#}
{# <input type="checkbox" checked="checked" id="id_use_default_auth" name="use_default_auth"><span> 使用默认 </span>#}
{# </label>#}
{# </div>#}
{# </div>#}
{# </div>#}
{# <p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>#}
{# <div class="form-group" id="admin_account" style="display: none">#}
{# <label class="col-sm-2 control-label"> <span class="red-fonts"></span> </label>#}
{# <div class="col-sm-3">#}
{# <input type="text" placeholder="Username" name="username" class="form-control">#}
{# </div>#}
{##}
{# <label class="col-sm-1 control-label"> <span class="red-fonts"></span> </label>#}
{# <div class="col-sm-4">#}
{# <input type="password" placeholder="Password" name="password" class="form-control">#}
{# </div>#}
{# </div>#}
<div class="form-group" id="id_port"> <div class="form-group" id="id_port">
<div class="hr-line-dashed"></div> <label class="col-sm-2 control-label">端口</label>
<label class="col-sm-2 control-label"> 端口<span class="red-fonts">*</span> </label> <div class="col-sm-9">
<div class="col-sm-8"> <input type="text" placeholder="" name="port" class="form-control">
<input type="text" placeholder="Port" name="port" class="form-control" value="{{ default_port }}">
</div> </div>
</div> </div>
<div class="hr-line-dashed"></div> {# <div class="form-group" id="id_type">#}
{{ form.group|bootstrap_horizontal }} {# <label class="col-sm-2 control-label">资产类型</label>#}
{# <div class="col-sm-9">#}
{# <input type="text" placeholder="" name="type" class="form-control">#}
{# </div>#}
{# </div>#}
{{ form.type|bootstrap_horizontal }}
{# {{ af.is_active|bootstrap_horizontal }}#} {{ form.comment|bootstrap_horizontal }}
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"><label class="col-sm-2 control-label"> 是否激活<span class="red-fonts"> *</span> </label> <h3>关联资产用户</h3>
<div class="col-sm-8"> <div class="form-group">
<label for="j_group" class="col-sm-2 control-label">管理用户</label>
<div class="col-sm-9">
<div class="radio i-checks"> <div class="radio i-checks">
<label> <input type="radio" checked="" value="1" name="is_active">激活 </label> <label><input type="radio" checked="checked" id="id_use_default_auth" name="use_default_auth"><span>使用预定义管理用户</span></label>
<label> <input type="radio" value="0" name="is_active"> 禁用</label> <label><input type="radio" id="id_use_default_auth" name="use_default_auth"><span>自定义</span></label>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group" id="id_manager_user">
<div class="col-sm-offset-2 col-sm-9">
<input type="text" placeholder="请选择管理用户" name="manager_user" class="form-control">
</div>
</div>
<p class="col-sm-offset-2">Tips: 管理用户是服务器存在的root或拥有sudo的用户,用来推送系统用户</p>
<div class="form-group">
<label for="system_user" class="col-sm-2 control-label">系统用户</label>
<div class="col-sm-9">
<input type="text" placeholder="" name="system_user" class="form-control">
</div>
</div>
<div class="hr-line-dashed"></div>
<h3>所属</h3>
{{ form.idc|bootstrap_horizontal }}
{{ form.groups|bootstrap_horizontal }}
<div class="hr-line-dashed"></div>
<h3>标签</h3>
<div class="hr-line-dashed"></div> <div class="hr-line-dashed"></div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-5">
<button class="btn btn-white" type="reset"> 重置 </button> <button class="btn btn-white" type="reset"> 重置 </button>
<button class="btn btn-primary" type="submit"> 提交 </button> <button class="btn btn-primary" type="submit"> 提交 </button>
</div> </div>
...@@ -113,85 +110,10 @@ ...@@ -113,85 +110,10 @@
</div> </div>
{% endblock %} {% endblock %}
{% block self_footer_js %} {% block custom_foot_js %}
<script> <script>
$('document').ready(function(){ $(document).ready(function () {
var check_default = "{{ default_setting.name }}"; $('.select2').select2();
console.log(check_default); })
if (check_default != 'default'){ </script>
$('#id_use_default_auth').attr('disabled', true);
$('#id_use_default_auth').attr('checked', false);
$('#admin_account').css('display', 'block');
} else {
$('#id_use_default_auth').click(function(){
if ($(this).is(':checked')){
$('#admin_account').css('display', 'none');
}
else {
$('#admin_account').css('display', 'block');
}
})
}
});
var required_fields = ["id_hostname", "id_port"];
required_fields.forEach(function(field) {
$('label[for="' + field + '"]').parent().addClass("required");
});
$('#assetForm').validator({
timely: 2,
theme: "yellow_right_effect",
rules: {
check_ip: [/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){3}$/, 'ip地址不正确'],
check_port: [/^\d{1,5}$/, '端口号不正确'],
use_default_auth: function() {
var str1 = $("#id_use_default_auth").is(":checked");
if (str1 == true){
var decide = false;
} else {
var decide = true;
}
return decide}
},
fields: {
"ip": {
rule: "check_ip;",
tip: "输入IP",
ok: "",
msg: {required: "必须填写!"}
},
"hostname": {
rule: "required;length[0~53]",
tip: "填写主机名",
ok: "",
msg: {required: "必须填写!"}
},
"port": {
rule: "required",
tip: "输入端口号",
ok: "",
msg: {required: "必须填写!"}
},
"username": {
rule: "required(use_default_auth)",
tip: "输入用户名",
ok: "",
msg: {required: "必须填写!"}
},
"password": {
rule: "required(use_default_auth);length[0~64]",
tip: "输入密码",
ok: "",
msg: {required: "必须填写!"}
}
},
valid: function(form) {
form.submit();
}
});
</script>
{% endblock %} {% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<span class="text text-primary"><b>{{ asset.ip }}</b></span>
<div class="ibox-tools">
{# <a class="" href="{% url 'assets:asset-update' %}">#}
<i class="fa fa-refresh"></i>
</a>
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>主机详细信息</h3>
<small><i class="fa fa-map-marker"></i> 此主机详细信息.</small>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
<table class="table">
<tr>
<td class="text-navy">主机名</td>
<td>{{ asset.hostname|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">IP</td>
<td>{{ asset.ip|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">其他IP</td>
<td>
<table class="table">
{% if asset.other_ip %}
{% for ip in asset.other_ip %}
<tr>
<td>{{ ip }}</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">远控IP</td>
<td>{{ asset.remote_ip|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">端口</td>
<td>{{ asset.port|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">主机组</td>
<td>
<table class="table">
{% for asset_group in asset.group.all %}
<tr>
<td>{{ asset_group.name|default_if_none:"" }}</td>
</tr>
{% endfor %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">使用默认管理账号</td>
{# <td>{{ asset.use_default_auth|bool2str }}</td>#}
{# <td>{{ asset.use_default_auth|bool2str }} {% if not asset.use_default_auth %} <span class="text-info">{{ asset.username }}</span> {% endif %}</td>#}
</tr>
<tr>
<td class="text-navy">机房</td>
<td>{{ asset.idc.name|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">硬件厂商型号</td>
<td>{{ asset.brand|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">CPU</td>
<td>{{ asset.cpu|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">内存</td>
<td>{{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}</td>
</tr>
<tr>
<td class="text-navy">硬盘</td>
<td>
<table class="table">
{% if asset.disk %}
{% for disk, value in asset.disk %}
<tr>
<td><span class="text-navy">{{ disk|default_if_none:"" }}</span> &nbsp&nbsp&nbsp {{ value|default_if_none:"" }}</td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
<tr>
<td class="text-navy">资产编号</td>
<td>{{ asset.number|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">SN</td>
<td>{{ asset.sn|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">主机类型</td>
<td>{{ asset.get_asset_type_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">系统版本</td>
<td>{{ asset.system_type|default_if_none:"" }} {{ asset.system_version|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">系统平台</td>
<td>{{ asset.system_arch|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">运行环境</td>
<td>{{ asset.get_env_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机器状态</td>
<td>{{ asset.get_status_display|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机柜号</td>
<td>{{ asset.cabinet|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">机柜位置</td>
<td>{{ asset.position|default_if_none:"" }}</td>
</tr>
<tr>
<td class="text-navy">激活</td>
<td>{{ asset.is_active }}</td>
</tr>
<tr>
<td class="text-navy">添加日期</td>
<td>{{ asset.date_added|date:"Y-m-d H:i:s" }}</td>
</tr>
<tr>
<td class="text-navy">备注</td>
<td>{{ asset.comment|default_if_none:"" }}</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>拥有权限的用户</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>主机所有授权的信息</h3>
<small><i class="fa fa-map-marker"></i> 包含了此主机所有授权的信息.</small>
</div>
<div class="ibox-content">
<div>
<div class="text-left">
{% if perm_info %}
{% if user_perm %}
<table class="table">
<p>授权用户信息</p>
<td class="text-navy">授权用户</td>
<td class="text-navy">关联用户</td>
{% for perm in user_perm %}
<tr>
<td class="text-navy"><a href="{% url 'user_detail' %}?id={{ perm.0.id }}">{{ perm.0 }}</a></td>
<td>
<table class="table">
{% if perm.1 %}
{% for role in perm.1 %}
<tr>
<td class="text-navy"><a href="{% url 'role_detail' %}?id={{ role.id }}">{{ role }}</a></td>
</tr>
{% endfor %}
{% endif %}
</table>
</td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if user_group_perm %}
<table class="table">
<p>授权用户组信息</p>
<td class="text-navy">授权用户组</td>
<td class="text-navy">组详情</td>
{% for user_group in user_group_perm %}
<tr>
<td class="text-navy">{{ user_group }}</td>
<td class="text-navy"><a href="{% url 'user_group_list' %}?gid={{ user_group.id }}">详情</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
{% if user_rule_perm %}
<table class="table">
<p>授权规则信息</p>
<td class="text-navy">授权规则</td>
<td class="text-navy">详情</td>
{% for rule in user_rule_perm %}
<tr>
<td class="text-navy">{{ rule }}</td>
<td class="text-navy"><a href="{% url 'rule_detail' %}?id={{ rule.id }}">详情</a></td>
</tr>
{% endfor %}
</table>
{% endif %}
{% else %}
<p class="text-center">(暂无)</p>
{% endif %}
</div>
</div>
</div>
<div class="ibox-title">
<h5>主机修改记录</h5>
{# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" data-toggle="tooltip" class="text-success pull-center" data-placement="bottom" title="修改">&nbsp&nbsp&nbsp&nbsp点击修改</a>#}
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>主机修改记录</h3>
<small><i class="fa fa-map-marker"></i> 包含了此主机所有历史修改记录.</small>
</div>
<div class="ibox-content">
<div class="feed-activity-list">
{% if asset_record %}
{# {% for r in asset_record %}#}
{# <div class="feed-element">#}
{# <div>#}
{# <small class="pull-right">{{ r.alert_time|naturaltime }}</small>#}
{# <strong class="text-navy">{{ r.username }}</strong>#}
{# {% for i in r.content|str_to_list %}#}
{# <div>{{ i.0 }} 由 <span class="text-success">{{ i.1|str_to_code }}</span> 改为 <span class="text-warning">{{ i.2|str_to_code }}</span></div>#}
{# {% endfor %}#}
{# <small class="text-success">{{ r.alert_time }}</small>#}
{# </div>#}
{# </div>#}
{# {% endfor %}#}
{% else %}
<p class="text-center">(暂无)</p>
{% endif %}
</div>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>最近一周登录记录</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<ul class="dropdown-menu dropdown-user">
</ul>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content ibox-heading">
<h3>最近一周登录记录</h3>
<small><i class="fa fa-map-marker"></i> 此主机最近一周用户登录信息.</small>
</div>
<div class="ibox-content inspinia-timeline">
{% if log %}
{% for l in log %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-5 date">
<i class="fa fa-info-circle"></i>
<small class="text-navy">{{ l.user }}</small>
<br/>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>详细信息</strong></p>
<p>来源IP: {{ l.remote_ip }}</p>
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
</div>
</div>
</div>
{% endfor %}
<button id="show" class="btn btn-primary btn-block m-t"><i class="fa fa-arrow-down"></i> 所有 </button>
<div id='more' style="display: none">
<br/>
{% for l in log_more %}
<div class="timeline-item">
<div class="row">
<div class="col-xs-5 date">
<i class="fa fa-info-circle"></i>
<small class="text-navy">{{ l.user }}</small>
<br/>
</div>
<div class="col-xs-7 content no-top-border">
<p class="m-b-xs"><strong>详细信息</strong></p>
<p>来源IP: {{ l.remote_ip }}</p>
<p>开始: {{ l.start_time |date:"Y-m-d H:i:s" }}</p>
<p>结束: {{ l.end_time |date:"Y-m-d H:i:s" }}</p>
</div>
</div>
</div>
{% endfor %}
{% else %}
<p class="text-center">(暂无)</p>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function(){
$('#show').click(function(){
$('#show').css('display', 'none');
$('#more').css('display', 'block');
})
})
</script>
{% endblock %}
\ No newline at end of file
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
<div class="col-sm-12"> <div class="col-sm-12">
<div class="ibox float-e-margins" id="all"> <div class="ibox float-e-margins" id="all">
<div class="ibox-title"> <div class="ibox-title">
<h5> 主机详细信息列表</h5> <h5> 资产列表</h5>
<div class="ibox-tools"> <div class="ibox-tools">
<a class="collapse-link"> <a class="collapse-link">
<i class="fa fa-chevron-up"></i> <i class="fa fa-chevron-up"></i>
...@@ -102,14 +102,11 @@ ...@@ -102,14 +102,11 @@
<input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')"> <input id="checkall" type="checkbox" class="i-checks" name="checkall" value="checkall" data-editable='false' onclick="check_all('asset_form')">
</th> </th>
<th class="text-center"> 主机名 </th> <th class="text-center"> 主机名 </th>
<th class="text-center" name="ip"> IP地址 </th> <th class="text-center" name="ip"> IP </th>
<th class="text-center"> IDC </th> <th class="text-center"> 类型 </th>
<th class="text-center"> 所属主机组 </th> <th class="text-center"> 配置 </th>
{# <th class="text-center"> 配置信息 </th>#} <th class="text-center"> 资产组 </th>
<th class="text-center"> 操作系统 </th> <th class="text-center"> 状态 </th>
<th class="text-center"> cpu核数 </th>
<th class="text-center"> 内存 </th>
<th class="text-center"> 硬盘 </th>
<th class="text-center"> 操作 </th> <th class="text-center"> 操作 </th>
</tr> </tr>
</thead> </thead>
...@@ -119,15 +116,18 @@ ...@@ -119,15 +116,18 @@
<td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'> <td class="text-center" name="id" value="{{ asset.id }}" data-editable='false'>
<input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks"> <input name="id" value="{{ asset.id }}" type="checkbox" class="i-checks">
</td> </td>
<td class="text-center hostname"> <a href="{% url 'assets:asset-detail' %}?id={{ asset.id }}">{{ asset.hostname|default_if_none:"" }}</a></td> <td class="text-center"> {{ asset.hostname }} </td>
<td class="text-center"> {{ asset.ip|default_if_none:"" }} </td> <td class="text-center"> {{ asset.ip }} </td>
<td class="text-center"> {{ asset.idc.name|default_if_none:"" }} </td> <td class="text-center">{{ asset.system_type }}</td>
{# <td class="text-center">{{ asset.group.all|group_str2 }}</td>#} <td class="text-center"> {{ asset.cpu }} | {{ asset.memory }} | {{ asset.disk }}</td>
{# <td class="text-center">{{ asset.cpu }}|{{ asset.memory }}|{{ asset.disk }}</td>#} <td class="text-center"> {% for group in asset.group.all %} {{ group.name }} {% endfor %}</td>
<td class="text-center">{{ asset.system_type|default_if_none:"" }}{{ asset.system_version|default_if_none:"" }}</td> <td class="text-center">
<td class="text-center"> {{ asset.cpu|default_if_none:"" }} </td> {% if asset.is_active %}
<td class="text-center"> {{ asset.memory|default_if_none:"" }}{% if asset.memory %}G{% endif %}</td> <i class="fa fa-circle text-navy"></i>
<td class="text-center"> {{ asset.disk }}{% if asset.disk %}G{% endif %}</td> {% else %}
<i class="fa fa-circle text-danger"></i>
{% endif %}
</td>
<td class="text-center" data-editable='false'> <td class="text-center" data-editable='false'>
{# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>#} {# <a href="{% url 'asset_edit' %}?id={{ asset.id }}" class="btn btn-xs btn-info">编辑</a>#}
<a value="{{ asset.id }}" class="conn btn btn-xs btn-warning">连接</a> <a value="{{ asset.id }}" class="conn btn btn-xs btn-warning">连接</a>
...@@ -145,7 +145,7 @@ ...@@ -145,7 +145,7 @@
{# <input type="button" id="asset_update_all" class="btn btn-primary btn-sm" name="update_button" value="更新全部"/>#} {# <input type="button" id="asset_update_all" class="btn btn-primary btn-sm" name="update_button" value="更新全部"/>#}
<input type="button" id="exec_cmd" class="btn btn-sm btn-primary" name="exec_cmd" value="执行命令"/> <input type="button" id="exec_cmd" class="btn btn-sm btn-primary" name="exec_cmd" value="执行命令"/>
</div> </div>
{# {% include 'paginator.html' %}#} {% include '_pagination.html' %}
</div> </div>
</form> </form>
</div> </div>
......
{% extends 'base.html' %}
{% load i18n %}
{% load static %}
{% load bootstrap %}
{% block custom_head_css_js %}
<link href="{% static "css/plugins/select2/select2.min.css" %}" rel="stylesheet">
<script src="{% static "js/plugins/select2/select2.full.min.js" %}"></script>
{% endblock %}
{% block content %}
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-sm-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>{% trans 'Create asset group' %}</h5>
<div class="ibox-tools">
<a class="collapse-link">
<i class="fa fa-chevron-up"></i>
</a>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">
<i class="fa fa-wrench"></i>
</a>
<a class="close-link">
<i class="fa fa-times"></i>
</a>
</div>
</div>
<div class="ibox-content">
<form method="post" id="userForm" class="form-horizontal" action="" >
{% csrf_token %}
{{ form.name|bootstrap_horizontal }}
<div class="form-group">
<label for="users" class="col-sm-2 control-label">{% trans 'Asset' %}</label>
<div class="col-sm-9">
<select name="assets" id="assets" data-placeholder="{% trans 'Select asset' %}" class="select2 form-control m-b" multiple tabindex="2">
{% for asset in assets %}
<option value="{{ asset.id }}">{{ asset.ip }}:{{ asset.port }}</option>
{% endfor %}
</select>
</div>
</div>
{{ form.comment|bootstrap_horizontal }}
<div class="form-group">
<div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
{% block custom_foot_js %}
<script>
$(document).ready(function () {
$('.select2').select2();
})
</script>
{% endblock %}
\ No newline at end of file
{% extends '_list_base.html' %}
{% load i18n %}
{% load common_tags %}
{% block content_left_head %}
<a href="{% url 'assets:assetgroup-add' %}" class="btn btn-sm btn-primary "> {% trans "Create asset group" %} </a>
{% endblock %}
{% block table_head %}
<th class="text-center">
<input type="checkbox" id="check_all" onclick="checkAll('check_all', 'checked')">
</th>
<th class="text-center"><a href="{% url 'assets:assetgroup-list' %}?sort=name">{% trans 'Name' %}</a></th>
<th class="text-center">{% trans 'Asset num' %}</th>
<th class="text-center"><a href="{% url 'assets:assetgroup-list' %}?sort=date_expired">{% trans 'Comment' %}</a></th>
<th class="text-center"></th>
{% endblock %}
{% block table_body %}
{% for assetgroup in assetgroups %}
<tr class="gradeX">
<td class="text-center">
<input type="checkbox" name="checked" value="{{ assetgroup.id }}">
</td>
<td class="text-center">
<a href="{% url 'assets:assetgroup-detail' pk=assetgroup.id %}">
{{ assetgroup.name }}
</a>
</td>
<td class="text-center">{{ assetgroup.asset_set.count }}</td>
<td class="text-center">{{ assetgroup.comment }}</td>
<td class="text-center">
<a href="{% url 'assets:assetgroup-edit' pk=assetgroup.id %}" class="btn btn-xs btn-info">{% trans 'Edit' %}</a>
<a href="{% url 'assets:assetgroup-delete' pk=assetgroup.id %}" class="btn btn-xs btn-danger del">{% trans 'Delete' %}</a>
</td>
</tr>
{% endfor %}
{% endblock %}
{% block content_bottom_left %}
<form id="" method="get" action="" class=" mail-search">
<div class="input-group">
<select class="form-control m-b" style="width: auto">
<option>{% trans 'Delete selected' %}</option>
<option>{% trans 'Update selected' %}</option>
<option>{% trans 'Deactive selected' %}</option>
<option>{% trans 'Export selected' %}</option>
</select>
<div class="input-group-btn pull-left" style="padding-left: 5px;">
<button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Submit' %}
</button>
</div>
</div>
</form>
{% endblock %}
# coding:utf-8 # coding:utf-8
from django.conf.urls import url,include from django.conf.urls import url, include
from .views import * import views
from .api import ( # from .api import (
AssetGroupViewSet,AssetViewSet,IDCViewSet # AssetGroupViewSet, AssetViewSet, IDCViewSet
) # )
from rest_framework import routers # from rest_framework import routers
router = routers.DefaultRouter() # router = routers.DefaultRouter()
router.register(r'assetgroup', AssetGroupViewSet) # router.register(r'assetgroup', AssetGroupViewSet)
router.register(r'asset', AssetViewSet) # router.register(r'asset', AssetViewSet)
router.register(r'idc', IDCViewSet) # router.register(r'idc', IDCViewSet)
app_name = 'assets' app_name = 'assets'
urlpatterns = [ urlpatterns = [
url(r'^add/$', AssetAddView.as_view(), name='asset-add'), url(r'^$', views.AssetListView.as_view(), name='asset-index'),
url(r'^list/$', AssetListView.as_view(), name='asset-list'), url(r'^asset$', views.AssetListView.as_view(), name='asset-list'),
url(r'^(?P<pk>[0-9]+)/delete/$', AssetDeleteView.as_view(), name='asset-list'), url(r'^asset/add$', views.AssetAddView.as_view(), name='asset-add'),
url(r'^(?P<pk>[0-9]+)/detail/$', AssetDetailView.as_view(), name='asset-detail'), url(r'^asset/(?P<pk>[0-9]+)$', views.AssetDetailView.as_view(), name='asset-detail'),
url(r'^api/v1.0/', include(router.urls)), url(r'^asset/(?P<pk>[0-9]+)$/edit', views.AssetEditView.as_view(), name='asset-edit'),
url(r'^asset/(?P<pk>[0-9]+)/delete$', views.AssetDeleteView.as_view(), name='asset-delete'),
url(r'^assetgroup$', views.AssetGroupListView.as_view(), name='assetgroup-list'),
url(r'^assetgroup/add$', views.AssetGroupAddView.as_view(), name='assetgroup-add'),
url(r'^assetgroup/(?P<pk>[0-9]+)$', views.AssetGroupDetailView.as_view(), name='assetgroup-detail'),
url(r'^assetgroup/(?P<pk>[0-9]+)/edit$', views.AssetGroupEditView.as_view(), name='assetgroup-edit'),
url(r'^assetgroup/(?P<pk>[0-9]+)/delete$', views.AssetGroupDeleteView.as_view(), name='assetgroup-delete'),
# url(r'^api/v1.0/', include(router.urls)),
] ]
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
# #
from django.contrib.auth.mixins import UserPassesTestMixin
from django.urls import reverse_lazy
from common.tasks import send_mail_async
from common.utils import reverse
from users.models import User
try:
import cStringIO as StringIO
except ImportError:
import StringIO
class AdminUserRequiredMixin(UserPassesTestMixin):
login_url = reverse_lazy('users:login')
def test_func(self):
return self.request.user.is_staff
from django.views.generic import ( # coding:utf-8
TemplateView, ListView from __future__ import absolute_import, unicode_literals
)
from django.utils.translation import ugettext as _
from django.views.generic import TemplateView, ListView
from django.urls import reverse_lazy from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from django.views.generic import TemplateView, ListView
from django.views.generic.edit import CreateView, DeleteView, FormView, UpdateView
from django.urls import reverse_lazy
from django.views.generic.detail import DetailView
from .models import Asset, AssetGroup, IDC, AssetExtend
from .forms import AssetForm, AssetGroupForm
from django.views.generic.edit import ( from .utils import AdminUserRequiredMixin
CreateView, DeleteView, FormView, UpdateView
)
from django.views.generic.detail import (
DetailView
)
from .models import (
Asset, AssetGroup, IDC, AssetExtend
)
from .forms import (
AssetForm,
)
class AssetAddView(CreateView): class AssetAddView(CreateView):
...@@ -31,8 +22,12 @@ class AssetAddView(CreateView): ...@@ -31,8 +22,12 @@ class AssetAddView(CreateView):
template_name = 'assets/asset_add.html' template_name = 'assets/asset_add.html'
success_url = reverse_lazy('assets:asset-list') success_url = reverse_lazy('assets:asset-list')
def form_invalid(self, form):
print(form.errors)
return super(AssetAddView, self).form_invalid(form)
class AssetEdit(): class AssetEditView(UpdateView):
pass pass
...@@ -52,3 +47,44 @@ class AssetDetailView(DetailView): ...@@ -52,3 +47,44 @@ class AssetDetailView(DetailView):
context_object_name = 'asset' context_object_name = 'asset'
template_name = 'assets/asset_detail.html' template_name = 'assets/asset_detail.html'
class AssetGroupAddView(CreateView):
model = AssetGroup
form_class = AssetGroupForm
template_name = 'assets/assetgroup_add.html'
success_url = reverse_lazy('assets:assetgroup-list')
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Create asset group'),
'assets': Asset.objects.all(),
}
kwargs.update(context)
return super(AssetGroupAddView, self).get_context_data(**kwargs)
class AssetGroupListView(ListView):
model = AssetGroup
context_object_name = 'assetgroups'
template_name = 'assets/assetgroup_list.html'
def get_context_data(self, **kwargs):
context = {
'app': _('Assets'),
'action': _('Asset group list')
}
kwargs.update(context)
return super(AssetGroupListView, self).get_context_data(**kwargs)
class AssetGroupDetailView(DetailView):
pass
class AssetGroupEditView(UpdateView):
pass
class AssetGroupDeleteView(DeleteView):
pass
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
from django import template from django import template
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
register = template.Library() register = template.Library()
@register.filter @register.filter
def join_queryset_attr(queryset, attr, delimiter=', '): def join_queryset_attr(queryset, attr, delimiter=', '):
return delimiter.join([getattr(obj, attr, '') for obj in queryset]) return delimiter.join([getattr(obj, attr, '') for obj in queryset])
@register.filter @register.filter
def pagination_range(total_page, current_num=1, display=5): def pagination_range(total_page, current_num=1, display=5):
"""Return Page range """Return Page range
:param total_page: Total numbers of paginator :param total_page: Total numbers of paginator
:param current_num: current display page num :param current_num: current display page num
:param display: Display as many as [:display:] page :param display: Display as many as [:display:] page
In order to display many page num on web like: In order to display many page num on web like:
< 1 2 3 4 5 > < 1 2 3 4 5 >
""" """
try: try:
current_num = int(current_num) current_num = int(current_num)
except ValueError: except ValueError:
current_num = 1 current_num = 1
start = current_num - display/2 if current_num > display/2 else 1 start = current_num - display/2 if current_num > display/2 else 1
end = start + display if start + display <= total_page else total_page + 1 end = start + display if start + display <= total_page else total_page + 1
return range(start, end) return range(start, end)
\ No newline at end of file
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from __future__ import unicode_literals from __future__ import unicode_literals
from django.shortcuts import reverse as dj_reverse from django.shortcuts import reverse as dj_reverse
from django.conf import settings from django.conf import settings
def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False): def reverse(viewname, urlconf=None, args=None, kwargs=None, current_app=None, external=False):
url = dj_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app) url = dj_reverse(viewname, urlconf=urlconf, args=args, kwargs=kwargs, current_app=current_app)
if external: if external:
url = settings.SITE_URL.strip('/') + url url = settings.SITE_URL.strip('/') + url
return url return url
def get_object_or_none(model, **kwargs): def get_object_or_none(model, **kwargs):
try: try:
obj = model.objects.get(**kwargs) obj = model.objects.get(**kwargs)
except model.DoesNotExist: except model.DoesNotExist:
obj = None obj = None
return obj return obj
...@@ -132,7 +132,7 @@ else: ...@@ -132,7 +132,7 @@ else:
# Password validation # Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators
#
AUTH_PASSWORD_VALIDATORS = [ AUTH_PASSWORD_VALIDATORS = [
{ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
...@@ -215,7 +215,7 @@ LOGGING = { ...@@ -215,7 +215,7 @@ LOGGING = {
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/ # https://docs.djangoproject.com/en/1.10/topics/i18n/
LANGUAGE_CODE = 'zh_CN' LANGUAGE_CODE = 'en_US'
TIME_ZONE = 'Asia/Shanghai' TIME_ZONE = 'Asia/Shanghai'
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-04 12:20+0800\n" "POT-Creation-Date: 2016-09-04 17:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -17,6 +17,140 @@ msgstr "" ...@@ -17,6 +17,140 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: assets/models.py:9 assets/models.py:21
msgid "Name"
msgstr "名称"
#: assets/models.py:10 assets/models.py:29 assets/models.py:71
msgid "Created by"
msgstr "创建者"
#: assets/models.py:11 assets/models.py:30 assets/models.py:74
msgid "Comment"
msgstr "备注"
#: assets/models.py:22
msgid "Bandwidth"
msgstr "带宽"
#: assets/models.py:23
msgid "Contact"
msgstr "联系人"
#: assets/models.py:24
msgid "Phone"
msgstr "手机"
#: assets/models.py:25
msgid "Address"
msgstr "地址"
#: assets/models.py:26
msgid "Network"
msgstr "网络"
#: assets/models.py:27 assets/models.py:73
msgid "Date added"
msgstr "加入日期"
#: assets/models.py:28
msgid "Operator"
msgstr "运营商"
#: assets/models.py:37 assets/models.py:54 templates/_nav.html:23
msgid "IDC"
msgstr "机房"
#: assets/models.py:46
msgid "IP"
msgstr ""
#: assets/models.py:47
msgid "Other IP"
msgstr ""
#: assets/models.py:48
msgid "Remote card IP"
msgstr ""
#: assets/models.py:49
msgid "Hostname"
msgstr "用户名"
#: assets/models.py:50
msgid "Port"
msgstr "端口"
#: assets/models.py:51
msgid "Asset groups"
msgstr "用户组"
#: assets/models.py:52
#, fuzzy
#| msgid "Edit user"
msgid "Admin user"
msgstr "编辑用户"
#: assets/models.py:53
msgid "Admin password"
msgstr "管理员密码"
#: assets/models.py:55
msgid "Mac address"
msgstr "Mac地址"
#: assets/models.py:56
msgid "Brand"
msgstr "品牌"
#: assets/models.py:57
msgid "CPU"
msgstr "CPU"
#: assets/models.py:58
msgid "Memory"
msgstr "内存"
#: assets/models.py:59
msgid "Disk"
msgstr "硬盘"
#: assets/models.py:60
msgid "OS"
msgstr "操作系统"
#: assets/models.py:61
msgid "Cabinet number"
msgstr "机柜编号"
#: assets/models.py:62
msgid "Cabinet position"
msgstr "机柜层号"
#: assets/models.py:63
msgid "Asset number"
msgstr "资产编号"
#: assets/models.py:65
msgid "Asset status"
msgstr "资产状态"
#: assets/models.py:67
msgid "Asset type"
msgstr "系统类型"
#: assets/models.py:69
msgid "Asset environment"
msgstr "资产环境"
#: assets/models.py:70
msgid "Serial number"
msgstr "序列号"
#: assets/models.py:72
msgid "Is active"
msgstr "是否激活"
#: templates/_header_bar.html:8 #: templates/_header_bar.html:8
msgid "Search" msgid "Search"
msgstr "搜索" msgstr "搜索"
...@@ -57,16 +191,16 @@ msgstr "资产" ...@@ -57,16 +191,16 @@ msgstr "资产"
msgid "Assetgroup" msgid "Assetgroup"
msgstr "用户组" msgstr "用户组"
#: templates/_nav.html:23
msgid "IDC"
msgstr "机房"
#: templates/_nav.html:24 #: templates/_nav.html:24
msgid "Asset admin" #, fuzzy
#| msgid "Asset admin"
msgid "Assetadmin"
msgstr "管理用户" msgstr "管理用户"
#: templates/_nav.html:25 #: templates/_nav.html:25
msgid "Asset user" #, fuzzy
#| msgid "Asset user"
msgid "Assetuser"
msgstr "系统用户" msgstr "系统用户"
#: templates/_nav.html:26 #: templates/_nav.html:26
...@@ -121,22 +255,15 @@ msgstr "注销登录" ...@@ -121,22 +255,15 @@ msgstr "注销登录"
msgid "Play CAPTCHA as audio file" msgid "Play CAPTCHA as audio file"
msgstr "" msgstr ""
#~ msgid "Username" #~ msgid "Asset user"
#~ msgstr "用户名" #~ msgstr "系统用户"
#~ msgid "Password" #~ msgid "Password"
#~ msgstr "密码" #~ msgstr "密码"
#, fuzzy
#~ msgid "Join usergroups" #~ msgid "Join usergroups"
#~ msgstr "添加到用户组" #~ msgstr "添加到用户组"
#~ msgid "Name"
#~ msgstr "名称"
#~ msgid "Comment"
#~ msgstr "备注"
#~ msgid "Administrator" #~ msgid "Administrator"
#~ msgstr "管理员" #~ msgstr "管理员"
...@@ -152,9 +279,6 @@ msgstr "" ...@@ -152,9 +279,6 @@ msgstr ""
#~ msgid "Wechat" #~ msgid "Wechat"
#~ msgstr "微信" #~ msgstr "微信"
#~ msgid "Phone"
#~ msgstr "手机"
#~ msgid "Enable OTP" #~ msgid "Enable OTP"
#~ msgstr "二次验证" #~ msgstr "二次验证"
...@@ -200,9 +324,6 @@ msgstr "" ...@@ -200,9 +324,6 @@ msgstr ""
#~ msgid "Captcha invalid" #~ msgid "Captcha invalid"
#~ msgstr "验证码错误" #~ msgstr "验证码错误"
#~ msgid "Reset password"
#~ msgstr "重置密码"
#~ msgid "Password again" #~ msgid "Password again"
#~ msgstr "再次输入密码" #~ msgstr "再次输入密码"
...@@ -224,12 +345,6 @@ msgstr "" ...@@ -224,12 +345,6 @@ msgstr ""
#~ msgid "User log" #~ msgid "User log"
#~ msgstr "登录日志" #~ msgstr "登录日志"
#~ msgid "Created by"
#~ msgstr "创建者"
#~ msgid "Date joined"
#~ msgstr "加入日期"
#~ msgid "Last login" #~ msgid "Last login"
#~ msgstr "最后登录" #~ msgstr "最后登录"
...@@ -245,12 +360,6 @@ msgstr "" ...@@ -245,12 +360,6 @@ msgstr ""
#~ msgid "Add" #~ msgid "Add"
#~ msgstr "添加" #~ msgstr "添加"
#~ msgid "Asset num"
#~ msgstr "资产数量"
#~ msgid "Active"
#~ msgstr "有效"
#~ msgid "Edit" #~ msgid "Edit"
#~ msgstr "编辑" #~ msgstr "编辑"
...@@ -377,9 +486,6 @@ msgstr "" ...@@ -377,9 +486,6 @@ msgstr ""
#~ msgid "Create user<a href=\"%s\">%s</a> success." #~ msgid "Create user<a href=\"%s\">%s</a> success."
#~ msgstr "创建用户<a href=\"%s\">%s</a> 成功" #~ msgstr "创建用户<a href=\"%s\">%s</a> 成功"
#~ msgid "Edit user"
#~ msgstr "编辑用户"
#~ msgid "Usergroup list" #~ msgid "Usergroup list"
#~ msgstr "用户组列表" #~ msgstr "用户组列表"
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
</div> </div>
<ul class="nav navbar-top-links navbar-right"> <ul class="nav navbar-top-links navbar-right">
<li> <li>
<span class="m-r-sm text-muted welcome-message">{% trans 'Welcome use Jumpserver system' %}</span> <span class="m-r-sm text-muted welcome-message">{% trans 'Welcome to use Jumpserver system' %}</span>
</li> </li>
<li class="dropdown"> <li class="dropdown">
<a class="dropdown-toggle count-info" data-toggle="dropdown" href="#"> <a class="dropdown-toggle count-info" data-toggle="dropdown" href="#">
......
...@@ -18,8 +18,8 @@ ...@@ -18,8 +18,8 @@
<i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span> <i class="fa fa-inbox"></i> <span class="nav-label">{% trans 'Assets' %}</span><span class="fa arrow"></span>
</a> </a>
<ul class="nav nav-second-level"> <ul class="nav nav-second-level">
<li class=""><a href="">{% trans 'Asset' %}</a></li> <li class="{% url 'assets:asset-list' %}"><a href="">{% trans 'Asset' %}</a></li>
<li class=""><a href="">{% trans 'Assetgroup' %}</a></li> <li class=""><a href="{% url 'assets:assetgroup-list' %}">{% trans 'Assetgroup' %}</a></li>
<li class=""><a href="">{% trans 'IDC' %}</a></li> <li class=""><a href="">{% trans 'IDC' %}</a></li>
<li class=""><a href="">{% trans 'Assetadmin' %}</a></li> <li class=""><a href="">{% trans 'Assetadmin' %}</a></li>
<li class=""><a href="">{% trans 'Assetuser' %}</a></li> <li class=""><a href="">{% trans 'Assetuser' %}</a></li>
......
...@@ -8,7 +8,7 @@ msgid "" ...@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-09-04 12:20+0800\n" "POT-Creation-Date: 2016-09-04 17:31+0800\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
...@@ -97,6 +97,10 @@ msgstr "" ...@@ -97,6 +97,10 @@ msgstr ""
msgid "Date expired" msgid "Date expired"
msgstr "" msgstr ""
#: users/models.py:122 users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/models.py:228 #: users/models.py:228
msgid "Administrator is the super user of system" msgid "Administrator is the super user of system"
msgstr "" msgstr ""
...@@ -131,7 +135,7 @@ msgstr "" ...@@ -131,7 +135,7 @@ msgstr ""
#: users/templates/users/_user.html:70 #: users/templates/users/_user.html:70
#: users/templates/users/forget_password.html:44 #: users/templates/users/forget_password.html:44
#: users/templates/users/user_list.html:63 #: users/templates/users/user_list.html:63
msgid "Commit" msgid "Submit"
msgstr "" msgstr ""
#: users/templates/users/forget_password.html:26 #: users/templates/users/forget_password.html:26
...@@ -187,10 +191,6 @@ msgstr "" ...@@ -187,10 +191,6 @@ msgstr ""
msgid "Search" msgid "Search"
msgstr "" msgstr ""
#: users/templates/users/user_detail.html:101
msgid "Created by"
msgstr ""
#: users/templates/users/user_detail.html:105 #: users/templates/users/user_detail.html:105
msgid "Date joined" msgid "Date joined"
msgstr "" msgstr ""
......
...@@ -119,7 +119,7 @@ class User(AbstractUser): ...@@ -119,7 +119,7 @@ class User(AbstractUser):
is_first_login = models.BooleanField(default=False) is_first_login = models.BooleanField(default=False)
date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True, date_expired = models.DateTimeField(default=date_expired_default, blank=True, null=True,
verbose_name=_('Date expired')) verbose_name=_('Date expired'))
created_by = models.CharField(max_length=30, default='') created_by = models.CharField(max_length=30, default='', verbose_name=_('Created by'))
@property @property
def password_raw(self): def password_raw(self):
......
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
from rest_framework import serializers from rest_framework import serializers
from .models import User, UserGroup from .models import User, UserGroup
class UserSerializer(serializers.ModelSerializer): class UserSerializer(serializers.ModelSerializer):
groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api') groups = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:usergroup-detail-api')
class Meta: class Meta:
model = User model = User
exclude = [ exclude = [
'password', 'first_name', 'last_name', 'secret_key_otp', 'password', 'first_name', 'last_name', 'secret_key_otp',
'private_key', 'public_key', 'avatar', 'private_key', 'public_key', 'avatar',
] ]
class UserActiveSerializer(serializers.ModelSerializer): class UserActiveSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = ['is_active'] fields = ['is_active']
class UserGroupSerializer(serializers.ModelSerializer): class UserGroupSerializer(serializers.ModelSerializer):
users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api') users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='users:user-detail-api')
class Meta: class Meta:
model = UserGroup model = UserGroup
fields = '__all__' fields = '__all__'
...@@ -67,7 +67,7 @@ ...@@ -67,7 +67,7 @@
<div class="form-group"> <div class="form-group">
<div class="col-sm-4 col-sm-offset-2"> <div class="col-sm-4 col-sm-offset-2">
<button class="btn btn-white" type="reset">{% trans 'Reset' %}</button> <button class="btn btn-white" type="reset">{% trans 'Reset' %}</button>
<button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Commit' %}</button> <button id="submit_button" class="btn btn-primary" type="submit">{% trans 'Submit' %}</button>
</div> </div>
</div> </div>
</form> </form>
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
<input type="email" name="email" class="form-control" placeholder="Email address" required=""> <input type="email" name="email" class="form-control" placeholder="Email address" required="">
</div> </div>
<button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Commit' %}</button> <button type="submit" class="btn btn-primary block full-width m-b">{% trans 'Submit' %}</button>
</form> </form>
</div> </div>
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
<div class="input-group-btn pull-left" style="padding-left: 5px;"> <div class="input-group-btn pull-left" style="padding-left: 5px;">
<button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary"> <button id='search_btn' type="submit" style="height: 32px;" class="btn btn-sm btn-primary">
{% trans 'Commit' %} {% trans 'Submit' %}
</button> </button>
</div> </div>
......
# ~*~ coding: utf-8 ~*~ # ~*~ coding: utf-8 ~*~
import os import os
import urllib import urllib
import hashlib import hashlib
from django import template from django import template
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
register = template.Library() register = template.Library()
@register.filter @register.filter
def join_queryset_attr(queryset, attr, delimiter=', '): def join_queryset_attr(queryset, attr, delimiter=', '):
return delimiter.join([getattr(obj, attr, '') for obj in queryset]) return delimiter.join([getattr(obj, attr, '') for obj in queryset])
@register.filter @register.filter
def is_expired(datetime): def is_expired(datetime):
if datetime > timezone.now(): if datetime > timezone.now():
return False return False
else: else:
return True return True
@register.filter @register.filter
def user_avatar_url(user): def user_avatar_url(user):
if user.avatar: if user.avatar:
return user.avatar.url return user.avatar.url
else: else:
default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default') default_dir = os.path.join(settings.MEDIA_ROOT, 'avatar', 'default')
if os.path.isdir(default_dir): if os.path.isdir(default_dir):
default_avatar_list = os.listdir(default_dir) default_avatar_list = os.listdir(default_dir)
default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)] default_avatar = default_avatar_list[len(user.username) % len(default_avatar_list)]
return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar) return os.path.join(settings.MEDIA_URL, 'avatar', 'default', default_avatar)
return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon' return 'https://www.gravatar.com/avatar/c6812ab450230979465d7bf288eadce2a?s=120&d=identicon'
...@@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView): ...@@ -168,10 +168,10 @@ class UserDetailView(AdminUserRequiredMixin, DetailView):
context_object_name = "user" context_object_name = "user"
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(UserDetailView, self).get_context_data(**kwargs)
groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()] groups = [group for group in UserGroup.objects.iterator() if group not in self.object.groups.iterator()]
context.update({'app': _('Users'), 'action': _('User detail'), 'groups': groups}) context = {'app': _('Users'), 'action': _('User detail'), 'groups': groups}
return context kwargs.update(context)
return super(UserDetailView, self).get_context_data(**kwargs)
class UserGroupListView(AdminUserRequiredMixin, ListView): class UserGroupListView(AdminUserRequiredMixin, ListView):
......
...@@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps') ...@@ -19,7 +19,7 @@ apps_dir = os.path.join(BASE_DIR, 'apps')
def start_django(): def start_django():
http_host = CONFIG.HTTP_LISTEN_HOST or 'locahost' http_host = CONFIG.HTTP_LISTEN_HOST or '127.0.0.1'
http_port = CONFIG.HTTP_LISTEN_PORT or '8080' http_port = CONFIG.HTTP_LISTEN_PORT or '8080'
os.chdir(apps_dir) os.chdir(apps_dir)
print('start django') print('start django')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment