mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Add data file UI view
This commit is contained in:
parent
b38b4e11a6
commit
7ae6d821fa
@ -3,6 +3,7 @@ from django.utils.translation import gettext as _
|
||||
|
||||
import django_filters
|
||||
|
||||
from netbox.filtersets import ChangeLoggedModelFilterSet
|
||||
from .models import *
|
||||
|
||||
__all__ = (
|
||||
@ -11,7 +12,7 @@ __all__ = (
|
||||
)
|
||||
|
||||
|
||||
class DataSourceFilterSet(django_filters.FilterSet):
|
||||
class DataSourceFilterSet(ChangeLoggedModelFilterSet):
|
||||
|
||||
class Meta:
|
||||
model = DataSource
|
||||
@ -27,11 +28,14 @@ class DataSourceFilterSet(django_filters.FilterSet):
|
||||
|
||||
|
||||
class DataFileFilterSet(django_filters.FilterSet):
|
||||
datasource_id = django_filters.ModelMultipleChoiceFilter(
|
||||
q = django_filters.CharFilter(
|
||||
method='search'
|
||||
)
|
||||
source_id = django_filters.ModelMultipleChoiceFilter(
|
||||
queryset=DataSource.objects.all(),
|
||||
label=_('Data source (ID)'),
|
||||
)
|
||||
datasource = django_filters.ModelMultipleChoiceFilter(
|
||||
source = django_filters.ModelMultipleChoiceFilter(
|
||||
field_name='source__name',
|
||||
queryset=DataSource.objects.all(),
|
||||
to_field_name='name',
|
||||
|
@ -1,4 +1,5 @@
|
||||
from django import forms
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from core.choices import *
|
||||
from core.models import *
|
||||
@ -38,11 +39,12 @@ class DataFileFilterForm(NetBoxModelFilterSetForm):
|
||||
model = DataFile
|
||||
fieldsets = (
|
||||
(None, ('q', 'filter_id')),
|
||||
('File', ('datasource_id',)),
|
||||
('File', ('source_id',)),
|
||||
)
|
||||
datasource_id = DynamicModelMultipleChoiceField(
|
||||
source_id = DynamicModelMultipleChoiceField(
|
||||
queryset=DataSource.objects.all(),
|
||||
required=False
|
||||
required=False,
|
||||
label=_('Data source')
|
||||
)
|
||||
type = MultipleChoiceField(
|
||||
choices=DataSourceTypeChoices,
|
||||
|
@ -306,6 +306,16 @@ class DataFile(models.Model):
|
||||
def __str__(self):
|
||||
return self.path
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse('core:datafile', args=[self.pk])
|
||||
|
||||
@property
|
||||
def data_as_string(self):
|
||||
try:
|
||||
return self.data.tobytes().decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
return None
|
||||
|
||||
def refresh_from_disk(self, source_root):
|
||||
"""
|
||||
Update instance attributes from the file on disk. Returns True if any attribute
|
||||
|
@ -33,6 +33,9 @@ class DataFileTable(NetBoxTable):
|
||||
source = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
path = tables.Column(
|
||||
linkify=True
|
||||
)
|
||||
last_updated = columns.DateTimeColumn()
|
||||
actions = None
|
||||
|
||||
|
@ -16,5 +16,6 @@ urlpatterns = (
|
||||
|
||||
# Data files
|
||||
path('data-files/', views.DataFileListView.as_view(), name='datafile_list'),
|
||||
path('data-files/<int:pk>/', include(get_model_urls('core', 'datafile'))),
|
||||
|
||||
)
|
||||
|
@ -1,14 +1,11 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
|
||||
from extras.models import JobResult
|
||||
from netbox.views import generic
|
||||
from netbox.views.generic.base import BaseObjectView
|
||||
from utilities.utils import count_related
|
||||
from utilities.views import register_model_view
|
||||
from . import filtersets, forms, jobs, tables
|
||||
from .choices import *
|
||||
from . import filtersets, forms, tables
|
||||
from .models import *
|
||||
|
||||
|
||||
@ -29,6 +26,15 @@ class DataSourceListView(generic.ObjectListView):
|
||||
class DataSourceView(generic.ObjectView):
|
||||
queryset = DataSource.objects.all()
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
related_models = (
|
||||
(DataFile.objects.restrict(request.user, 'view').filter(source=instance), 'source_id'),
|
||||
)
|
||||
|
||||
return {
|
||||
'related_models': related_models,
|
||||
}
|
||||
|
||||
|
||||
@register_model_view(DataSource, 'sync')
|
||||
class DataSourceSyncView(BaseObjectView):
|
||||
@ -94,3 +100,8 @@ class DataFileListView(generic.ObjectListView):
|
||||
filterset_form = forms.DataFileFilterForm
|
||||
table = tables.DataFileTable
|
||||
actions = ('edit',)
|
||||
|
||||
|
||||
@register_model_view(DataFile)
|
||||
class DataFileView(generic.ObjectView):
|
||||
queryset = DataFile.objects.all()
|
||||
|
77
netbox/templates/core/datafile.html
Normal file
77
netbox/templates/core/datafile.html
Normal file
@ -0,0 +1,77 @@
|
||||
{% extends 'generic/object.html' %}
|
||||
{% load custom_links %}
|
||||
{% load helpers %}
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
{{ block.super }}
|
||||
<li class="breadcrumb-item"><a href="{% url 'core:datafile_list' %}?source_id={{ object.source.pk }}">{{ object.source }}</a></li>
|
||||
{% endblock %}
|
||||
|
||||
{% block controls %}
|
||||
{# Clone/Edit/Delete Buttons #}
|
||||
<div class="controls">
|
||||
<div class="control-group">
|
||||
{% plugin_buttons object %}
|
||||
</div>
|
||||
<div class="control-group">
|
||||
{% custom_links object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock controls %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row mb-3">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<h5 class="card-header">Data File</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">Source</th>
|
||||
<td><a href="{{ object.source.get_absolute_url }}">{{ object.source }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Path</th>
|
||||
<td>
|
||||
<span class="font-monospace" id="datafile_path">{{ object.path }}</span>
|
||||
<a class="btn btn-sm btn-primary copy-token" data-clipboard-target="#datafile_path" title="Copy to clipboard">
|
||||
<i class="mdi mdi-content-copy"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Last Updated</th>
|
||||
<td>{{ object.last_updated }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Size</th>
|
||||
<td>{{ object.size }} byte{{ object.size|pluralize }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">SHA256 Hash</th>
|
||||
<td>
|
||||
<span class="font-monospace" id="datafile_hash">{{ object.hash }}</span>
|
||||
<a class="btn btn-sm btn-primary copy-token" data-clipboard-target="#datafile_hash" title="Copy to clipboard">
|
||||
<i class="mdi mdi-content-copy"></i>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<h5 class="card-header">Content</h5>
|
||||
<div class="card-body">
|
||||
<pre>{{ object.data_as_string }}</pre>
|
||||
</div>
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col col-md-12">
|
||||
{% plugin_full_width_page object %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
@ -95,6 +95,8 @@
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'inc/panels/related_objects.html' %}
|
||||
{% include 'inc/panels/custom_fields.html' %}
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user