diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..8de7556 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f65808 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +**/netbox +**/netbox-docker +**/*.pyc +**/__pycache__ +**/.idea +.vscode/ +dist/* +ci/docker-compose.override.yml +ci/reports +out/production +*.iml +build/* +netbox_excel.egg-info/* \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..cb04ac8 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,7 @@ +include LICENSE +include README.md +include SECURITY.md +graft netbox_excel +prune netbox_excel/tests +global-exclude *.py[cod] +global-exclude __pycache__ diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..d6c6182 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,63 @@ +Metadata-Version: 2.1 +Name: netbox-excel +Version: 1.0.0 +Summary: Import device from file excel Netbox Plugin +Home-page: https://github.com/hocchudong/netbox-excel +Author-email: ducna +License: Apache-2.0 +Classifier: Environment :: Web Environment +Classifier: Framework :: Django +Classifier: Intended Audience :: Developers +Classifier: License :: OSI Approved :: Apache Software License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3 :: Only +Classifier: Programming Language :: Python :: 3.11 +Classifier: Programming Language :: Python :: 3.12 +Classifier: Topic :: Internet :: WWW/HTTP +Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content +Requires-Python: >=3.10.12 +Description-Content-Type: text/markdown +License-File: LICENSE +Provides-Extra: build +Requires-Dist: build==1.2.1; extra == "build" +Requires-Dist: setuptools==70.3.0; extra == "build" +Requires-Dist: twine==5.1.1; extra == "build" +Provides-Extra: tools +Requires-Dist: ruff==0.5.1; extra == "tools" + + +## Install Require + +netbox version >= 4.0 + +## Known Issues + +- WARNING: This plugin is only tested with a single NetBox version at this time. + +## Installation Guide + +### In mono service: + +To install the plugin, first using pip and install netbox-excel: + + ``` + cd /opt/netbox + source venv/bin/activate + pip install netbox-excel + ``` + +Next, enable the plugin in /opt/netbox/netbox/netbox/configuration.py, or if you have a /configuration/plugins.py file, the plugins.py file will take precedence. + + ``` + PLUGINS = [ + 'netbox_excel' + ] + ``` +Then you may need to perform the final step of restarting the service to ensure that the changes take effect correctly: + + ``` + python netbox/manage.py migrate netbox_excel + sudo systemctl restart netbox + ``` diff --git a/netbox_excel/.DS_Store b/netbox_excel/.DS_Store new file mode 100644 index 0000000..a9f4bfe Binary files /dev/null and b/netbox_excel/.DS_Store differ diff --git a/netbox_excel/__init__.py b/netbox_excel/__init__.py new file mode 100644 index 0000000..12a25d9 --- /dev/null +++ b/netbox_excel/__init__.py @@ -0,0 +1,16 @@ +from netbox.plugins import PluginConfig + +__version__ = "1.0.0" + +class NetboxExcelConfig(PluginConfig): + name = "netbox_excel" + verbose_name = "Netbox excel" + description = "Import object from file excel" + version = __version__ + author = "ducna" + author_email = "ducna@hcd.com.vn" + base_url = "netbox-excel" + required_settings = [] + default_settings = {"version_info": False} + +config = NetboxExcelConfig diff --git a/netbox_excel/__pycache__/__init__.cpython-310.pyc b/netbox_excel/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..ecd7676 Binary files /dev/null and b/netbox_excel/__pycache__/__init__.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/forms.cpython-310.pyc b/netbox_excel/__pycache__/forms.cpython-310.pyc new file mode 100644 index 0000000..f507b00 Binary files /dev/null and b/netbox_excel/__pycache__/forms.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/models.cpython-310.pyc b/netbox_excel/__pycache__/models.cpython-310.pyc new file mode 100644 index 0000000..55eb5e2 Binary files /dev/null and b/netbox_excel/__pycache__/models.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/navigation.cpython-310.pyc b/netbox_excel/__pycache__/navigation.cpython-310.pyc new file mode 100644 index 0000000..426536b Binary files /dev/null and b/netbox_excel/__pycache__/navigation.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/template_content.cpython-310.pyc b/netbox_excel/__pycache__/template_content.cpython-310.pyc new file mode 100644 index 0000000..0a9f446 Binary files /dev/null and b/netbox_excel/__pycache__/template_content.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/urls.cpython-310.pyc b/netbox_excel/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000..3f2289e Binary files /dev/null and b/netbox_excel/__pycache__/urls.cpython-310.pyc differ diff --git a/netbox_excel/__pycache__/views.cpython-310.pyc b/netbox_excel/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000..54390e7 Binary files /dev/null and b/netbox_excel/__pycache__/views.cpython-310.pyc differ diff --git a/netbox_excel/api/__init__.py b/netbox_excel/api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_excel/api/__pycache__/__init__.cpython-310.pyc b/netbox_excel/api/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..ed5552d Binary files /dev/null and b/netbox_excel/api/__pycache__/__init__.cpython-310.pyc differ diff --git a/netbox_excel/api/__pycache__/serializers.cpython-310.pyc b/netbox_excel/api/__pycache__/serializers.cpython-310.pyc new file mode 100644 index 0000000..42b6b8b Binary files /dev/null and b/netbox_excel/api/__pycache__/serializers.cpython-310.pyc differ diff --git a/netbox_excel/api/__pycache__/urls.cpython-310.pyc b/netbox_excel/api/__pycache__/urls.cpython-310.pyc new file mode 100644 index 0000000..5103a3a Binary files /dev/null and b/netbox_excel/api/__pycache__/urls.cpython-310.pyc differ diff --git a/netbox_excel/api/__pycache__/views.cpython-310.pyc b/netbox_excel/api/__pycache__/views.cpython-310.pyc new file mode 100644 index 0000000..a462094 Binary files /dev/null and b/netbox_excel/api/__pycache__/views.cpython-310.pyc differ diff --git a/netbox_excel/api/serializers.py b/netbox_excel/api/serializers.py new file mode 100644 index 0000000..0efdb8e --- /dev/null +++ b/netbox_excel/api/serializers.py @@ -0,0 +1,24 @@ +from rest_framework import serializers + +from netbox.api.serializers import NetBoxModelSerializer +from netbox_excel.models import ImportExcel + + +class ImportExcelSerializer(NetBoxModelSerializer): + display = serializers.SerializerMethodField() + + class Meta: + model = ImportExcel + fields = ( + "id", + "name", + "description", + "tags", + "custom_field_data", + "created", + "last_updated", + ) + brief_fields = ("id", "name", "description") + + def get_display(self, obj): + return f"{obj}" \ No newline at end of file diff --git a/netbox_excel/api/urls.py b/netbox_excel/api/urls.py new file mode 100644 index 0000000..1a3864b --- /dev/null +++ b/netbox_excel/api/urls.py @@ -0,0 +1,11 @@ +from netbox.api.routers import NetBoxRouter +from netbox_excel.api.views import ( + NetboxExcelInfoRootView, + ImportExcelViewSet, +) + +router = NetBoxRouter() +router.APIRootView = NetboxExcelInfoRootView + +router.register("import_excel", ImportExcelViewSet) +urlpatterns = router.urls diff --git a/netbox_excel/api/views.py b/netbox_excel/api/views.py new file mode 100644 index 0000000..c2b7e37 --- /dev/null +++ b/netbox_excel/api/views.py @@ -0,0 +1,20 @@ +from rest_framework.routers import APIRootView + +from netbox.api.viewsets import NetBoxModelViewSet +from netbox_excel.api.serializers import ( + ImportExcelSerializer, +) +from netbox_excel.models import ImportExcel + + +class NetboxExcelInfoRootView(APIRootView): + """ + Netbox Excel API root view + """ + + def get_view_name(self): + return "Netbox Excel" + +class ImportExcelViewSet(NetBoxModelViewSet): + queryset = ImportExcel.objects.all() + serializer_class = ImportExcelSerializer \ No newline at end of file diff --git a/netbox_excel/export/__init__.py b/netbox_excel/export/__init__.py new file mode 100644 index 0000000..cb63bd6 --- /dev/null +++ b/netbox_excel/export/__init__.py @@ -0,0 +1,3 @@ +from .devices import get_device +from .export import export_all_view_rack , export_only_device +from .rack import get_rack_have_device \ No newline at end of file diff --git a/netbox_excel/export/__pycache__/__init__.cpython-310.pyc b/netbox_excel/export/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..696dc0c Binary files /dev/null and b/netbox_excel/export/__pycache__/__init__.cpython-310.pyc differ diff --git a/netbox_excel/export/__pycache__/devices.cpython-310.pyc b/netbox_excel/export/__pycache__/devices.cpython-310.pyc new file mode 100644 index 0000000..757478f Binary files /dev/null and b/netbox_excel/export/__pycache__/devices.cpython-310.pyc differ diff --git a/netbox_excel/export/__pycache__/export.cpython-310.pyc b/netbox_excel/export/__pycache__/export.cpython-310.pyc new file mode 100644 index 0000000..3946a04 Binary files /dev/null and b/netbox_excel/export/__pycache__/export.cpython-310.pyc differ diff --git a/netbox_excel/export/devices.py b/netbox_excel/export/devices.py new file mode 100644 index 0000000..054634c --- /dev/null +++ b/netbox_excel/export/devices.py @@ -0,0 +1,6 @@ +from dcim.models import Device + +def get_device(): + devices = Device.objects.all() + devices = devices.order_by('rack', '-position') + return devices \ No newline at end of file diff --git a/netbox_excel/export/export.py b/netbox_excel/export/export.py new file mode 100644 index 0000000..92d6cd5 --- /dev/null +++ b/netbox_excel/export/export.py @@ -0,0 +1,201 @@ +import openpyxl +from netbox_excel.models import ExportExcel +from .devices import get_device +from .rack import get_rack_have_device +import pandas as pd +# from io import StringIO +# import xlsxwriter +from django.http import HttpResponse , HttpResponseRedirect + +def export_all_view_rack(): + # Create a new workbook and select the active worksheet + workbook = openpyxl.Workbook() + sheet = workbook.active + sheet.title = "Data Export" + + # create the headers + headers = ['Rack', 'U/Rack','Tên Thiết bị', 'Chủng loại', 'Quản lý', 'Số HĐ', 'Model', 'SN', 'Thời gian lắp đặt', 'Ghi Chú'] + sheet.append(headers) + + try: + # get device + devices_list = get_device() + racks_list = [] # danh sách rack có thiết bị + item_sheet_list = [] # danh sách item device đã xử lý dữ liệu + + # start loop for chuẩn bị dữ liệu export + for device in devices_list: + #Kiểm tra nếu thiết bị không nằm trong tủ rack hoặc không có position bỏ qua + if device.position is None: + continue + # get data custom feild + device_owner = "" + year_of_investment = "" + contract_number = "" + custom_fields = device.get_custom_fields_by_group() + for key, value in custom_fields[''].items(): + if str(key) == 'Device owner' and value != None: + device_owner = value + elif str(key) == 'Year of investment' and value != None: + year_of_investment = value + elif str(key) == 'Contract number' and value != None: + contract_number = value + + # create new item export + item_export = ExportExcel( + rack = str(device.rack), + device_role = str(device.role), + device_type = str(device.device_type), + device_name = str(device.name), + position = int(device.position), # U/Rack + serial_number = str(device.serial), + device_description = str(device.description), + owner_device = str(device_owner), + year_of_investment = str(year_of_investment), + contract_number = str(contract_number), + u_number = int(device.device_type.u_height), + ) + + # append data to item_sheet_list export + racks_list.append(str(device.rack)) + item_sheet_list.append(item_export) + # end loop for chuẩn bị dữ liệu export + + # lọc trùng rack + racks_list = sorted(list(set(racks_list))) + u_height_sheet = 2 # đếm dòng sheet dòng 1 là header nên bắt đầu từ 2 + # start add item into sheet + for rack in racks_list: + u_height_rack = 42 # mỗi 1 rack có 42 lần add item ( 1 item = 1 U) + for i in range(42): + # kiểm tra trong list item export + device = find_device_item(item_sheet_list, rack, u_height_rack) + if device: + # add item into sheet + item = [ + rack, + u_height_rack, + device.device_name, + device.device_role, + device.owner_device, + device.contract_number, + device.device_type, + device.serial_number, + device.year_of_investment, + device.device_description, + ] + sheet.append(item) + + # check height > 1 => merg cell + if device.u_number > 1: + # Từ cột thứ 3 đến cuối đều cần merg ô bằng chiều cao của thiết bị + height_device_in_sheet = u_height_sheet - device.u_number + 1 + # copy data từ row position sang ô đầu tiên + for col in range(3, 11): + sheet.cell(row=height_device_in_sheet, column=col).value = sheet.cell(row=u_height_sheet, column=col).value + + sheet.merge_cells(start_row=height_device_in_sheet, start_column=3, end_row=u_height_sheet, end_column=3) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=4, end_row=u_height_sheet, end_column=4) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=5, end_row=u_height_sheet, end_column=5) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=6, end_row=u_height_sheet, end_column=6) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=7, end_row=u_height_sheet, end_column=7) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=8, end_row=u_height_sheet, end_column=8) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=9, end_row=u_height_sheet, end_column=9) + sheet.merge_cells(start_row=height_device_in_sheet, start_column=10, end_row=u_height_sheet, end_column=10) + else: + # add item into sheet + empty_item = [rack,u_height_rack] + sheet.append(empty_item) + # print(f"add empty into rack {rack} and U{u_height_rack}") + # variable counter + + u_height_rack-= 1 + u_height_sheet+= 1 + + return workbook + except Exception as e: + print("error export all device") + return workbook + +# Tìm device với rack name và position +def find_device_item(devices_list, rack_name, position): + for device in devices_list: + if device.rack == rack_name and device.position == position: + return device + + return + + +def export_only_device(): + # Create a new workbook and select the active worksheet + workbook = openpyxl.Workbook() + sheet = workbook.active + sheet.title = "Data Export" + + # create the headers + headers = ['Rack', 'Số U','Vị trí bắt đầu','Vị trí kế thúc', 'Tên Thiết bị', 'Chủng loại', 'Quản lý', 'Số HĐ', 'Model', 'SN', 'Thời gian lắp đặt', 'Ghi Chú'] + sheet.append(headers) + + try: + + # check form data: 1. export all table + item_sheet_list = [] + # get all device + devices_list = get_device() + + # start loop for + for device in devices_list: + # get data custom feild + device_owner = "" + year_of_investment = "" + contract_number = "" + custom_fields = device.get_custom_fields_by_group() + for key, value in custom_fields[''].items(): + if str(key) == 'Device owner' and value != None: + device_owner = value + elif str(key) == 'Year of investment' and value != None: + year_of_investment = value + elif str(key) == 'Contract number' and value != None: + contract_number = value + # Tính start U - end U + end_u = int(device.position) + int(device.device_type.u_height) - 1 + # create new item export + item_export = ExportExcel( + rack = device.rack, + device_role = device.role, + device_type = device.device_type, + device_name = device.name, + position = int(device.position), + serial_number = device.serial, + device_description = device.description, + owner_device = device_owner, + year_of_investment = year_of_investment, + contract_number = contract_number, + u_number = int(device.device_type.u_height), + u_end = end_u, + ) + + # append data to item_sheet_list export + item_sheet_list.append(item_export) + + # create item in sheet + item_sheet = [ + str(item_export.rack), + str(item_export.u_number), + str(item_export.position), # U start + str(item_export.u_end), # U end + str(item_export.device_name), + str(item_export.device_role), + str(item_export.owner_device), + str(item_export.contract_number), + str(item_export.device_type), + str(item_export.serial_number), + str(item_export.year_of_investment), + str(item_export.device_description), + ] + sheet.append(item_sheet) + # end loop for + return workbook + except Exception as e: + print("return empty excel") + return workbook \ No newline at end of file diff --git a/netbox_excel/export/rack.py b/netbox_excel/export/rack.py new file mode 100644 index 0000000..16dacd1 --- /dev/null +++ b/netbox_excel/export/rack.py @@ -0,0 +1,6 @@ +from dcim.models import Rack + +def get_rack_have_device(): + racks = Rack.objects.all() + racks = racks.order_by('name') + return racks \ No newline at end of file diff --git a/netbox_excel/forms.py b/netbox_excel/forms.py new file mode 100644 index 0000000..6cf6e1d --- /dev/null +++ b/netbox_excel/forms.py @@ -0,0 +1,14 @@ +from django import forms +from netbox_excel.models import ImportExcel + + +class ImportExcelForm(forms.Form): + file = forms.FileField() + +class ExportExcelForm(forms.Form): + OPTIONS = [ + ('all', 'All'), + ('current_view', 'Current View'), + ] + type = forms.ChoiceField(choices=OPTIONS, label="Select an type") + # type = forms.CharField(label="type", max_length=100) \ No newline at end of file diff --git a/netbox_excel/migrations/0001_initial.py b/netbox_excel/migrations/0001_initial.py new file mode 100644 index 0000000..e924415 --- /dev/null +++ b/netbox_excel/migrations/0001_initial.py @@ -0,0 +1,37 @@ +# Generated by Django 5.0.9 on 2024-12-23 03:59 + +import taggit.managers +import utilities.json +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ('extras', '0121_customfield_related_object_filter'), + ] + + operations = [ + migrations.CreateModel( + name='ImportExcel', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)), + ('created', models.DateTimeField(auto_now_add=True, null=True)), + ('last_updated', models.DateTimeField(auto_now=True, null=True)), + ('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)), + ('name', models.CharField(max_length=128)), + ('deivce_error', models.CharField(blank=True, null=True)), + ('deivce_type_error', models.CharField(blank=True, null=True)), + ('deivce_role_error', models.CharField(blank=True, null=True)), + ('rack_error', models.CharField(blank=True, null=True)), + ('manufacturer_error', models.CharField(blank=True, null=True)), + ('description', models.CharField(blank=True, max_length=255, null=True)), + ('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/netbox_excel/migrations/__init__.py b/netbox_excel/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_excel/migrations/__pycache__/0001_initial.cpython-310.pyc b/netbox_excel/migrations/__pycache__/0001_initial.cpython-310.pyc new file mode 100644 index 0000000..281ac04 Binary files /dev/null and b/netbox_excel/migrations/__pycache__/0001_initial.cpython-310.pyc differ diff --git a/netbox_excel/migrations/__pycache__/__init__.cpython-310.pyc b/netbox_excel/migrations/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000..41a6d62 Binary files /dev/null and b/netbox_excel/migrations/__pycache__/__init__.cpython-310.pyc differ diff --git a/netbox_excel/models.py b/netbox_excel/models.py new file mode 100644 index 0000000..ee49271 --- /dev/null +++ b/netbox_excel/models.py @@ -0,0 +1,35 @@ +from django.db import models +from django.urls import reverse +from django.utils import safestring + +from netbox.models import NetBoxModel +from utilities.querysets import RestrictedQuerySet +from netbox.models.features import TagsMixin + +class ImportExcel(NetBoxModel,TagsMixin): + name = models.CharField(max_length=128) + file = models.FileField(upload_to='dcim/devices/import/excel') + deivce_error = models.CharField(null=True, blank=True) + deivce_type_error = models.CharField(null=True, blank=True) + deivce_role_error = models.CharField(null=True, blank=True) + rack_error = models.CharField(null=True, blank=True) + manufacturer_error = models.CharField(null=True, blank=True) + description = models.CharField(max_length=255, null=True, blank=True) + + def __str__(self): + return self.name + +class ExportExcel(models.Model): + rack = models.CharField(null=True, blank=True) + u_number = models.CharField(null=True, blank=True) + u_end = models.CharField(null=True, blank=True) + position = models.CharField(null=True, blank=True) + device_name = models.CharField(null=True, blank=True) + device_role = models.CharField(null=True, blank=True) # chủng loại + owner_device = models.CharField(null=True, blank=True) # Quản lý + contract_number = models.CharField(null=True, blank=True) # So HD + serial_number = models.CharField(null=True, blank=True) + device_type = models.CharField(null=True, blank=True) # Model + device_description = models.CharField(null=True, blank=True) + year_of_investment = models.CharField(null=True, blank=True) + \ No newline at end of file diff --git a/netbox_excel/navigation.py b/netbox_excel/navigation.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_excel/tables.py b/netbox_excel/tables.py new file mode 100644 index 0000000..e69de29 diff --git a/netbox_excel/template_content.py b/netbox_excel/template_content.py new file mode 100644 index 0000000..c66929f --- /dev/null +++ b/netbox_excel/template_content.py @@ -0,0 +1,12 @@ +from netbox.plugins import PluginTemplateExtension +class ImportExcelDevice(PluginTemplateExtension): + model = 'dcim.device' + def list_buttons(self): + return self.render('netbox_excel/import_excel.html') + +class ExportExcelDevice(PluginTemplateExtension): + model = 'dcim.device' + def list_buttons(self): + return self.render('netbox_excel/export_excel.html') + +template_extensions = [ExportExcelDevice] \ No newline at end of file diff --git a/netbox_excel/templates/netbox_excel/export_excel.html b/netbox_excel/templates/netbox_excel/export_excel.html new file mode 100644 index 0000000..47414b0 --- /dev/null +++ b/netbox_excel/templates/netbox_excel/export_excel.html @@ -0,0 +1,65 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/netbox_excel/templates/netbox_excel/import_excel.html b/netbox_excel/templates/netbox_excel/import_excel.html new file mode 100644 index 0000000..efa665c --- /dev/null +++ b/netbox_excel/templates/netbox_excel/import_excel.html @@ -0,0 +1,44 @@ + + + + + + + + \ No newline at end of file diff --git a/netbox_excel/templates/netbox_excel/import_excel_console_log.html b/netbox_excel/templates/netbox_excel/import_excel_console_log.html new file mode 100644 index 0000000..519427d --- /dev/null +++ b/netbox_excel/templates/netbox_excel/import_excel_console_log.html @@ -0,0 +1,2 @@ + +

This is console log

\ No newline at end of file diff --git a/netbox_excel/urls.py b/netbox_excel/urls.py new file mode 100644 index 0000000..4278d81 --- /dev/null +++ b/netbox_excel/urls.py @@ -0,0 +1,8 @@ +from django.urls import path +from netbox_excel import views + +urlpatterns = [ + path('import/excel', views.ImportExcelView, name='import_file'), + path('export/excel', views.ExportExcelView, name='export_file'), + # path('dcim/devices/import-excel', CustomDeviceBulkImportView.as_view(), name='import_excel'), +] diff --git a/netbox_excel/views.py b/netbox_excel/views.py new file mode 100644 index 0000000..40bdb8d --- /dev/null +++ b/netbox_excel/views.py @@ -0,0 +1,37 @@ +from django.shortcuts import render +from django.http import HttpResponse, HttpResponseRedirect +from .forms import ImportExcelForm, ExportExcelForm +from netbox_excel.models import ExportExcel +from django.views.decorators.csrf import requires_csrf_token +from netbox_excel.export import get_device, export_all_view_rack, export_only_device +import openpyxl + + +@requires_csrf_token +def ImportExcelView(request): + if request.method == 'POST': + form = ImportExcelForm(request.POST, request.FILES) + else: + form = ImportExcelForm() + return render(request, 'netbox_excel/import_excel_console_log.html', {'form': form}) + +@requires_csrf_token +def ExportExcelView(request): + if request.method == 'POST': + # quick_search = request.POST.get('quick_search') + type = request.POST.get('type') + + if type == "only_device": + workbook = export_only_device() + else: + workbook = export_all_view_rack() + # add header response + response = HttpResponse(content_type='application/vnd.ms-excel') + response['Content-Disposition'] = 'attachment;filename="device_export_excel.xlsx"' + + workbook.save(response) + return response + # return HttpResponseRedirect("/dcim/devices/") + else: + # form = ExportExcelForm() + return HttpResponseRedirect("/dcim/devices/") \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..5f8732f --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,62 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "netbox-excel" +dynamic = ["version"] +description = "Netbox Excel Netbox Plugin" +readme = "README.md" +requires-python = ">=3.10.12" +license = { text = "Apache-2.0" } +authors = [ + {name = "ducna", email = "ducna-hcd@gmail.com"}, +] +classifiers = [ + "Environment :: Web Environment", + "Framework :: Django", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "Operating System :: OS Independent", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content", +] +dependencies = [] + +[project.optional-dependencies] +build = [ + "build == 1.2.1", + "setuptools == 70.3.0", + "twine == 5.1.1", +] +tools = [ + "ruff == 0.5.1", +] + +[tool.setuptools.dynamic] +version = {attr = "netbox_excel.__version__"} + +[tool.setuptools.packages.find] +include = ["netbox_excel"] + +[tool.ruff] +line-length = 120 +target-version = "py311" +src = ["netbox_excel"] + +[tool.ruff.lint.per-file-ignores] +"__init__.py" = [ + "D104", # https://beta.ruff.rs/docs/rules/#pydocstyle-d - don't require doc strings in __init__.py files + "F401", # https://beta.ruff.rs/docs/rules/#pyflakes-f - don't complain about unused imports in __init__.py files +] +"netbox_excel/migrations/*.py" = [ + "E501", # https://beta.ruff.rs/docs/rules/line-too-long/ - don't check on Django generated migration files +] + +[tool.ruff.format] +exclude = ["netbox_excel/migrations/*.py"] diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..4927abe --- /dev/null +++ b/setup.cfg @@ -0,0 +1,4 @@ +[egg_info] +tag_build = +tag_date = 0 +