mirror of https://github.com/jumpserver/jumpserver
assets:add tag
parent
05e961f29f
commit
2829445f4f
|
@ -23,8 +23,6 @@ from django.utils.translation import gettext_lazy as _
|
||||||
#
|
#
|
||||||
|
|
||||||
class AssetCreateForm(forms.ModelForm):
|
class AssetCreateForm(forms.ModelForm):
|
||||||
tags = forms.CharField(label=_('Tags'), widget=forms.TextInput(attrs={'id': 'tags'}),
|
|
||||||
required=False, help_text='Use `,` split')
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
instance = kwargs.get('instance', None)
|
instance = kwargs.get('instance', None)
|
||||||
|
@ -32,19 +30,15 @@ class AssetCreateForm(forms.ModelForm):
|
||||||
if instance:
|
if instance:
|
||||||
initial = kwargs.get('initial', {})
|
initial = kwargs.get('initial', {})
|
||||||
tags = instance.tags.all()
|
tags = instance.tags.all()
|
||||||
initial['tags'] = ",".join([tag.value for tag in tags])
|
initial['tags'] = [t.pk for t in kwargs['instance'].tags.all()]
|
||||||
print(kwargs.get('initial'))
|
print(kwargs.get('initial'))
|
||||||
super(AssetCreateForm, self).__init__(*args, **kwargs)
|
super(AssetCreateForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
def _save_m2m(self):
|
def _save_m2m(self):
|
||||||
|
super(AssetCreateForm, self)._save_m2m()
|
||||||
tags = self.cleaned_data['tags']
|
tags = self.cleaned_data['tags']
|
||||||
|
self.instance.tags.clear()
|
||||||
if tags:
|
self.instance.tags.add(*tuple(tags))
|
||||||
value_list = tags.split(',')
|
|
||||||
self.instance.tags.all().delete()
|
|
||||||
Tag.objects.bulk_create(
|
|
||||||
[Tag(value=value, asset=self.instance) for value in value_list]
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Asset
|
model = Asset
|
||||||
|
@ -52,11 +46,14 @@ class AssetCreateForm(forms.ModelForm):
|
||||||
fields = [
|
fields = [
|
||||||
'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups',
|
'hostname', 'ip', 'port', 'type', 'comment', 'admin_user', 'system_users', 'idc', 'groups',
|
||||||
'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no',
|
'other_ip', 'remote_card_ip', 'mac_address', 'brand', 'cpu', 'memory', 'disk', 'os', 'cabinet_no',
|
||||||
'cabinet_pos', 'number', 'status', 'env', 'sn',
|
'cabinet_pos', 'number', 'status', 'env', 'sn','tags',
|
||||||
]
|
]
|
||||||
|
tags = forms.ModelMultipleChoiceField(queryset=Tag.objects.all())
|
||||||
widgets = {
|
widgets = {
|
||||||
'groups': forms.SelectMultiple(attrs={'class': 'select2',
|
'groups': forms.SelectMultiple(attrs={'class': 'select2',
|
||||||
'data-placeholder': _('Select asset groups')}),
|
'data-placeholder': _('Select asset groups')}),
|
||||||
|
'tags': forms.SelectMultiple(attrs={'class': 'select2',
|
||||||
|
'data-placeholder': _('Select asset groups')}),
|
||||||
'system_users': forms.SelectMultiple(attrs={'class': 'select2',
|
'system_users': forms.SelectMultiple(attrs={'class': 'select2',
|
||||||
'data-placeholder': _('Select asset system users')}),
|
'data-placeholder': _('Select asset system users')}),
|
||||||
'admin_user': forms.Select(attrs={'class': 'select2', 'data-placeholder': _('Select asset admin user')}),
|
'admin_user': forms.Select(attrs={'class': 'select2', 'data-placeholder': _('Select asset admin user')}),
|
||||||
|
@ -64,6 +61,7 @@ class AssetCreateForm(forms.ModelForm):
|
||||||
help_texts = {
|
help_texts = {
|
||||||
'hostname': '* required',
|
'hostname': '* required',
|
||||||
'ip': '* required',
|
'ip': '* required',
|
||||||
|
'tags': '最多5个标签,单个标签最长8个汉字,按回车确认'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,7 @@ class Asset(models.Model):
|
||||||
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
is_active = models.BooleanField(default=True, verbose_name=_('Is active'))
|
||||||
date_created = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Date added'))
|
date_created = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Date added'))
|
||||||
comment = models.TextField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
|
comment = models.TextField(max_length=128, null=True, blank=True, verbose_name=_('Comment'))
|
||||||
|
tags = models.ManyToManyField('Tag', verbose_name='标签集合', blank=True)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port}
|
return '%(ip)s:%(port)s' % {'ip': self.ip, 'port': self.port}
|
||||||
|
@ -364,15 +365,17 @@ class Asset(models.Model):
|
||||||
|
|
||||||
|
|
||||||
class Tag(models.Model):
|
class Tag(models.Model):
|
||||||
value = models.CharField(max_length=64, verbose_name=_('VALUE'))
|
name = models.CharField('标签名', max_length=64)
|
||||||
asset = models.ForeignKey(Asset, related_name='tags', on_delete=models.CASCADE, verbose_name=_('Asset'))
|
created_time = models.DateTimeField('创建时间', auto_now_add=True)
|
||||||
|
created_by = models.CharField(max_length=32, null=True, blank=True, verbose_name=_('Created by'))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.value
|
return self.name
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = 'tag'
|
db_table = 'tag'
|
||||||
unique_together = ('value', 'asset')
|
|
||||||
|
|
||||||
|
|
||||||
def init_all_models():
|
def init_all_models():
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
<h3>{% trans 'Other' %}</h3>
|
<h3>{% trans 'Other' %}</h3>
|
||||||
{{ form.tags|bootstrap_horizontal }}
|
{{ form.tags|bootstrap_horizontal }}
|
||||||
|
|
||||||
|
|
||||||
{{ form.comment|bootstrap_horizontal }}
|
{{ form.comment|bootstrap_horizontal }}
|
||||||
|
|
||||||
<div class="hr-line-dashed"></div>
|
<div class="hr-line-dashed"></div>
|
||||||
|
@ -42,7 +44,11 @@
|
||||||
<script>
|
<script>
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
$('.select2').select2();
|
$('.select2').select2();
|
||||||
$('#tags').inputTags();
|
$("#tags").select2({
|
||||||
|
tags: true,
|
||||||
|
maximumSelectionLength: 8 //最多能够选择的个数
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -47,6 +47,7 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block content_bottom_left %}
|
{% block content_bottom_left %}
|
||||||
|
@ -67,5 +68,12 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
{% for tag in tag_list %}
|
||||||
|
<a href="{% url 'assets:asset-tags' tag_id=tag.0%}">
|
||||||
|
{{ tag.1}}({{ tag.2 }})
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ urlpatterns = [
|
||||||
url(r'^asset-group/(?P<pk>[0-9]+)$', views.AssetGroupDetailView.as_view(), name='asset-group-detail'),
|
url(r'^asset-group/(?P<pk>[0-9]+)$', views.AssetGroupDetailView.as_view(), name='asset-group-detail'),
|
||||||
url(r'^asset-group/(?P<pk>[0-9]+)/update$', views.AssetGroupUpdateView.as_view(), name='asset-group-update'),
|
url(r'^asset-group/(?P<pk>[0-9]+)/update$', views.AssetGroupUpdateView.as_view(), name='asset-group-update'),
|
||||||
url(r'^asset-group/(?P<pk>[0-9]+)/delete$', views.AssetGroupDeleteView.as_view(), name='asset-group-delete'),
|
url(r'^asset-group/(?P<pk>[0-9]+)/delete$', views.AssetGroupDeleteView.as_view(), name='asset-group-delete'),
|
||||||
|
url(r'^asset-tag/(?P<tag_id>[0-9]+)$', views.TagView.as_view(), name='asset-tags'),
|
||||||
|
|
||||||
# Resource idc url
|
# Resource idc url
|
||||||
url(r'^idc$', views.IDCListView.as_view(), name='idc-list'),
|
url(r'^idc$', views.IDCListView.as_view(), name='idc-list'),
|
||||||
|
|
|
@ -38,6 +38,8 @@ class AssetListView(AdminUserRequiredMixin, ListView):
|
||||||
context = {
|
context = {
|
||||||
'app': 'Assets',
|
'app': 'Assets',
|
||||||
'action': 'Asset list',
|
'action': 'Asset list',
|
||||||
|
'tag_list': [(i.id,i.name,i.asset_set.all().count())for i in Tag.objects.all().order_by('name')]
|
||||||
|
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
return super(AssetListView, self).get_context_data(**kwargs)
|
return super(AssetListView, self).get_context_data(**kwargs)
|
||||||
|
@ -45,6 +47,7 @@ class AssetListView(AdminUserRequiredMixin, ListView):
|
||||||
|
|
||||||
class AssetCreateView(AdminUserRequiredMixin, CreateView):
|
class AssetCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
model = Asset
|
model = Asset
|
||||||
|
tag_type = 'asset'
|
||||||
form_class = AssetCreateForm
|
form_class = AssetCreateForm
|
||||||
template_name = 'assets/asset_create.html'
|
template_name = 'assets/asset_create.html'
|
||||||
success_url = reverse_lazy('assets:asset-list')
|
success_url = reverse_lazy('assets:asset-list')
|
||||||
|
@ -53,12 +56,19 @@ class AssetCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
print(form.errors)
|
print(form.errors)
|
||||||
return super(AssetCreateView, self).form_invalid(form)
|
return super(AssetCreateView, self).form_invalid(form)
|
||||||
|
|
||||||
|
def form_valid(self, form):
|
||||||
|
tag_name_list = form.cleaned_data['tags']
|
||||||
|
print self.tag_type,tag_name_list
|
||||||
|
return super(AssetCreateView, self).form_valid(form)
|
||||||
|
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs):
|
||||||
context = {
|
context = {
|
||||||
'app': 'Assets',
|
'app': 'Assets',
|
||||||
'action': 'Create asset',
|
'action': 'Create asset',
|
||||||
}
|
}
|
||||||
kwargs.update(context)
|
kwargs.update(context)
|
||||||
|
|
||||||
return super(AssetCreateView, self).get_context_data(**kwargs)
|
return super(AssetCreateView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
@ -122,6 +132,7 @@ class AssetGroupCreateView(AdminUserRequiredMixin, CreateView):
|
||||||
form_class = AssetGroupForm
|
form_class = AssetGroupForm
|
||||||
template_name = 'assets/asset_group_create.html'
|
template_name = 'assets/asset_group_create.html'
|
||||||
success_url = reverse_lazy('assets:asset-group-list')
|
success_url = reverse_lazy('assets:asset-group-list')
|
||||||
|
#ordering = '-id'
|
||||||
|
|
||||||
# Todo: Asset group create template select assets so hard, need be resolve next
|
# Todo: Asset group create template select assets so hard, need be resolve next
|
||||||
|
|
||||||
|
@ -547,4 +558,14 @@ class SystemUserAssetView(AdminUserRequiredMixin, SingleObjectMixin, ListView):
|
||||||
# return super(SystemUserAssetGroupView, self).get_context_data(**kwargs)
|
# return super(SystemUserAssetGroupView, self).get_context_data(**kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class TagView(ListView):
|
||||||
|
context_object_name = 'asset_list'
|
||||||
|
template_name = 'assets/asset_list.html'
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
asset_list = Asset.objects.filter(tags=self.kwargs['tag_id'])
|
||||||
|
return asset_list
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
kwargs['tag_list'] = [(i.id,i.name,i.asset_set.all().count() )for i in Tag.objects.all().order_by('name')]
|
||||||
|
return super(TagView, self).get_context_data(**kwargs)
|
||||||
|
|
Loading…
Reference in New Issue