mirror of https://github.com/jumpserver/jumpserver
[Bugfix] 资产树节点,取消model value unique,并添加唯一性校验,修改新增节点计数器规则
parent
3af01d6a31
commit
2583c0b26c
|
@ -45,16 +45,15 @@ class NodeViewSet(BulkModelViewSet):
|
||||||
|
|
||||||
def get_serializer_class(self):
|
def get_serializer_class(self):
|
||||||
show_current_asset = self.request.query_params.get('show_current_asset')
|
show_current_asset = self.request.query_params.get('show_current_asset')
|
||||||
print(show_current_asset)
|
|
||||||
if show_current_asset:
|
if show_current_asset:
|
||||||
return serializers.NodeCurrentSerializer
|
return serializers.NodeCurrentSerializer
|
||||||
else:
|
else:
|
||||||
return serializers.NodeSerializer
|
return serializers.NodeSerializer
|
||||||
|
|
||||||
def perform_create(self, serializer):
|
# def perform_create(self, serializer):
|
||||||
child_key = Node.root().get_next_child_key()
|
# child_key = Node.root().get_next_child_key()
|
||||||
serializer.validated_data["key"] = child_key
|
# serializer.validated_data["key"] = child_key
|
||||||
serializer.save()
|
# serializer.save()
|
||||||
|
|
||||||
|
|
||||||
class NodeWithAssetsApi(generics.ListAPIView):
|
class NodeWithAssetsApi(generics.ListAPIView):
|
||||||
|
@ -91,16 +90,27 @@ class NodeChildrenApi(mixins.ListModelMixin, generics.CreateAPIView):
|
||||||
serializer_class = serializers.NodeSerializer
|
serializer_class = serializers.NodeSerializer
|
||||||
instance = None
|
instance = None
|
||||||
|
|
||||||
|
def counter(self):
|
||||||
|
values = [
|
||||||
|
child.value[child.value.rfind(' '):]
|
||||||
|
for child in self.get_object().get_children()
|
||||||
|
if child.value.startswith("新节点 ")
|
||||||
|
]
|
||||||
|
values = [int(value) for value in values if value.strip().isdigit()]
|
||||||
|
count = max(values)+1 if values else 1
|
||||||
|
return count
|
||||||
|
|
||||||
def post(self, request, *args, **kwargs):
|
def post(self, request, *args, **kwargs):
|
||||||
if not request.data.get("value"):
|
if not request.data.get("value"):
|
||||||
request.data["value"] = _("New node {}").format(
|
request.data["value"] = _("New node {}").format(self.counter())
|
||||||
Node.root().get_next_child_key().split(":")[-1]
|
|
||||||
)
|
|
||||||
return super().post(request, *args, **kwargs)
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
instance = self.get_object()
|
instance = self.get_object()
|
||||||
value = request.data.get("value")
|
value = request.data.get("value")
|
||||||
|
values = [child.value for child in instance.get_children()]
|
||||||
|
if value in values:
|
||||||
|
raise AssertionError('The same level node name cannot be the same')
|
||||||
node = instance.create_child(value=value)
|
node = instance.create_child(value=value)
|
||||||
return Response(
|
return Response(
|
||||||
{"id": node.id, "key": node.key, "value": node.value},
|
{"id": node.id, "key": node.key, "value": node.value},
|
||||||
|
@ -199,6 +209,9 @@ class NodeRemoveAssetsApi(generics.UpdateAPIView):
|
||||||
instance = self.get_object()
|
instance = self.get_object()
|
||||||
if instance != Node.root():
|
if instance != Node.root():
|
||||||
instance.assets.remove(*tuple(assets))
|
instance.assets.remove(*tuple(assets))
|
||||||
|
else:
|
||||||
|
assets = [asset for asset in assets if asset.nodes.count() > 1]
|
||||||
|
instance.assets.remove(*tuple(assets))
|
||||||
|
|
||||||
|
|
||||||
class NodeReplaceAssetsApi(generics.UpdateAPIView):
|
class NodeReplaceAssetsApi(generics.UpdateAPIView):
|
||||||
|
|
|
@ -12,7 +12,10 @@ __all__ = ['Node']
|
||||||
class Node(models.Model):
|
class Node(models.Model):
|
||||||
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
id = models.UUIDField(default=uuid.uuid4, primary_key=True)
|
||||||
key = models.CharField(unique=True, max_length=64, verbose_name=_("Key")) # '1:1:1:1'
|
key = models.CharField(unique=True, max_length=64, verbose_name=_("Key")) # '1:1:1:1'
|
||||||
value = models.CharField(max_length=128, unique=True, verbose_name=_("Value"))
|
# value = models.CharField(
|
||||||
|
# max_length=128, unique=True, verbose_name=_("Value")
|
||||||
|
# )
|
||||||
|
value = models.CharField(max_length=128, verbose_name=_("Value"))
|
||||||
child_mark = models.IntegerField(default=0)
|
child_mark = models.IntegerField(default=0)
|
||||||
date_create = models.DateTimeField(auto_now_add=True)
|
date_create = models.DateTimeField(auto_now_add=True)
|
||||||
|
|
||||||
|
@ -48,7 +51,7 @@ class Node(models.Model):
|
||||||
return child
|
return child
|
||||||
|
|
||||||
def get_children(self):
|
def get_children(self):
|
||||||
return self.__class__.objects.filter(key__regex=r'{}:[0-9]+$'.format(self.key))
|
return self.__class__.objects.filter(key__regex=r'^{}:[0-9]+$'.format(self.key))
|
||||||
|
|
||||||
def get_all_children(self):
|
def get_all_children(self):
|
||||||
return self.__class__.objects.filter(key__startswith='{}:'.format(self.key))
|
return self.__class__.objects.filter(key__startswith='{}:'.format(self.key))
|
||||||
|
|
|
@ -51,6 +51,15 @@ class NodeSerializer(serializers.ModelSerializer):
|
||||||
fields = ['id', 'key', 'value', 'parent', 'assets_amount', 'is_node']
|
fields = ['id', 'key', 'value', 'parent', 'assets_amount', 'is_node']
|
||||||
list_serializer_class = BulkListSerializer
|
list_serializer_class = BulkListSerializer
|
||||||
|
|
||||||
|
def update(self, instance, validated_data):
|
||||||
|
value = validated_data.get('value')
|
||||||
|
if not instance.is_root():
|
||||||
|
children = instance.parent.get_children().exclude(key=instance.key)
|
||||||
|
values = [child.value for child in children]
|
||||||
|
if value in values:
|
||||||
|
raise AssertionError('The same level node name cannot be the same')
|
||||||
|
return super().update(instance, validated_data)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_parent(obj):
|
def get_parent(obj):
|
||||||
return obj.parent.id
|
return obj.parent.id
|
||||||
|
|
|
@ -98,7 +98,10 @@ function initTree2() {
|
||||||
$.get("{% url 'api-assets:node-list' %}", function(data, status){
|
$.get("{% url 'api-assets:node-list' %}", function(data, status){
|
||||||
$.each(data, function (index, value) {
|
$.each(data, function (index, value) {
|
||||||
value["pId"] = value["parent"];
|
value["pId"] = value["parent"];
|
||||||
value["open"] = true;
|
{#value["open"] = true;#}
|
||||||
|
if (value["key"] === "0") {
|
||||||
|
value["open"] = true;
|
||||||
|
}
|
||||||
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
||||||
value['value'] = value['value'];
|
value['value'] = value['value'];
|
||||||
});
|
});
|
||||||
|
|
|
@ -190,7 +190,7 @@
|
||||||
<td colspan="2" class="no-borders">
|
<td colspan="2" class="no-borders">
|
||||||
<select data-placeholder="{% trans 'Nodes' %}" id="groups_selected" class="select2 groups" style="width: 100%" multiple="" tabindex="4">
|
<select data-placeholder="{% trans 'Nodes' %}" id="groups_selected" class="select2 groups" style="width: 100%" multiple="" tabindex="4">
|
||||||
{% for node in nodes_remain %}
|
{% for node in nodes_remain %}
|
||||||
<option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node.name }}</option>
|
<option value="{{ node.id }}" id="opt_{{ node.id }}" >{{ node }}</option>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</select>
|
</select>
|
||||||
</td>
|
</td>
|
||||||
|
@ -204,7 +204,7 @@
|
||||||
|
|
||||||
{% for node in asset.nodes.all %}
|
{% for node in asset.nodes.all %}
|
||||||
<tr>
|
<tr>
|
||||||
<td ><b class="bdg_node" data-gid={{ node.id }}>{{ node.name }}</b></td>
|
<td ><b class="bdg_node" data-gid={{ node.id }}>{{ node }}</b></td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn btn-danger pull-right btn-xs btn-leave-node" type="button"><i class="fa fa-minus"></i></button>
|
<button class="btn btn-danger pull-right btn-xs btn-leave-node" type="button"><i class="fa fa-minus"></i></button>
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -211,6 +211,8 @@ function addTreeNode() {
|
||||||
};
|
};
|
||||||
newNode.checked = zTree.getSelectedNodes()[0].checked;
|
newNode.checked = zTree.getSelectedNodes()[0].checked;
|
||||||
zTree.addNodes(parentNode, 0, newNode);
|
zTree.addNodes(parentNode, 0, newNode);
|
||||||
|
var node = zTree.getNodeByParam('id', newNode.id, parentNode)
|
||||||
|
zTree.editName(node);
|
||||||
} else {
|
} else {
|
||||||
alert("{% trans 'Create node failed' %}")
|
alert("{% trans 'Create node failed' %}")
|
||||||
}
|
}
|
||||||
|
@ -241,9 +243,9 @@ function removeTreeNode() {
|
||||||
|
|
||||||
function editTreeNode() {
|
function editTreeNode() {
|
||||||
hideRMenu();
|
hideRMenu();
|
||||||
var current_node = zTree.getSelectedNodes()[0];
|
var current_node = zTree.getSelectedNodes()[0];
|
||||||
if (!current_node){
|
if (!current_node){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (current_node.value) {
|
if (current_node.value) {
|
||||||
current_node.name = current_node.value;
|
current_node.name = current_node.value;
|
||||||
|
@ -398,9 +400,9 @@ function initTree() {
|
||||||
$.get("{% url 'api-assets:node-list' %}", query_params, function(data, status){
|
$.get("{% url 'api-assets:node-list' %}", query_params, function(data, status){
|
||||||
$.each(data, function (index, value) {
|
$.each(data, function (index, value) {
|
||||||
value["pId"] = value["parent"];
|
value["pId"] = value["parent"];
|
||||||
{#if (value["key"] === "0") {#}
|
if (value["key"] === "0") {
|
||||||
value["open"] = true;
|
value["open"] = true;
|
||||||
{# }#}
|
}
|
||||||
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
value["name"] = value["value"] + ' (' + value['assets_amount'] + ')';
|
||||||
value['value'] = value['value'];
|
value['value'] = value['value'];
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,7 +68,7 @@ var asset_table;
|
||||||
|
|
||||||
function initTable() {
|
function initTable() {
|
||||||
if (inited){
|
if (inited){
|
||||||
return
|
return asset_table
|
||||||
} else {
|
} else {
|
||||||
inited = true;
|
inited = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue