| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104 |
- import logging
- import os
- from django.conf import settings
- from django.core.exceptions import ValidationError
- from django.db import models
- from django.urls import reverse
- from django.utils.translation import gettext as _
- from ..choices import ManagedFileRootPathChoices
- from netbox.models.features import SyncedDataMixin
- from utilities.querysets import RestrictedQuerySet
- __all__ = (
- 'ManagedFile',
- )
- logger = logging.getLogger('netbox.core.files')
- class ManagedFile(SyncedDataMixin, models.Model):
- """
- Database representation for a file on disk. This class is typically wrapped by a proxy class (e.g. ScriptModule)
- to provide additional functionality.
- """
- created = models.DateTimeField(
- verbose_name=_('created'),
- auto_now_add=True
- )
- last_updated = models.DateTimeField(
- verbose_name=_('last updated'),
- editable=False,
- blank=True,
- null=True
- )
- file_root = models.CharField(
- verbose_name=_('file root'),
- max_length=1000,
- choices=ManagedFileRootPathChoices
- )
- file_path = models.FilePathField(
- verbose_name=_('file path'),
- editable=False,
- help_text=_('File path relative to the designated root path')
- )
- objects = RestrictedQuerySet.as_manager()
- _netbox_private = True
- class Meta:
- ordering = ('file_root', 'file_path')
- constraints = (
- models.UniqueConstraint(
- fields=('file_root', 'file_path'),
- name='%(app_label)s_%(class)s_unique_root_path'
- ),
- )
- indexes = [
- models.Index(fields=('file_root', 'file_path'), name='core_managedfile_root_path'),
- ]
- verbose_name = _('managed file')
- verbose_name_plural = _('managed files')
- def __str__(self):
- return self.name
- def get_absolute_url(self):
- return reverse('core:managedfile', args=[self.pk])
- @property
- def name(self):
- return self.file_path
- @property
- def full_path(self):
- return os.path.join(self._resolve_root_path(), self.file_path)
- def _resolve_root_path(self):
- return {
- 'scripts': settings.SCRIPTS_ROOT,
- 'reports': settings.REPORTS_ROOT,
- }[self.file_root]
- def sync_data(self):
- if self.data_file:
- self.file_path = os.path.basename(self.data_path)
- self.data_file.write_to_disk(self.full_path, overwrite=True)
- def clean(self):
- super().clean()
- # Ensure that the file root and path make a unique pair
- if self._meta.model.objects.filter(file_root=self.file_root, file_path=self.file_path).exclude(pk=self.pk).exists():
- raise ValidationError(
- f"A {self._meta.verbose_name.lower()} with this file path already exists ({self.file_root}/{self.file_path}).")
- def delete(self, *args, **kwargs):
- # Delete file from disk
- try:
- os.remove(self.full_path)
- except FileNotFoundError:
- pass
- return super().delete(*args, **kwargs)
|