Djagno запускает сервер, сканирует сеть и записывает данные в БД

Моя идея

Хранить данные о сетевых устройствах бросил Django Model (Device Model) в мою базу данных.

  1. Host configuration needs to be setup by User inside a View (Host Model)
  2. When the Host configuration is finished the Network should be scanned for devices (Device Model)
  3. The Data should be stored inside the DB

Фукция create_devices() вызывается до установки хоста, с migrate и makemigrations.

Как я могу это исправить? Правильно ли вообще хранить эти данные через представление в моей базе данных?

В лучшем случае данные в БД будут храниться асинхронно с моим приложением, есть ли способ?

Большое спасибо за помощь!!!

Модель хоста:

class Host(models.Model):

hostname = models.CharField(default="noads", max_length=6)
ipv4_address = models.GenericIPAddressField('IPv4')
ipv4_subnet = models.GenericIPAddressField('IPv4')
gateway = models.GenericIPAddressField('IPv4')

Модель устройства:

class Device(models.Model):

hostname = models.CharField(max_length=64)
mac_address = models.CharField(max_length=64)
ipv4_address = models.GenericIPAddressField('IPv4')

Мое мнение:


    def get_arp_table_linux():
    """
    Parse the host ARP table on a Linux machine

    :return: Machine readable ARP table
    :rtype: dict {'ip_address': 'mac_address'}
    """

    with open('/proc/net/arp') as proc_net_arp:
        arp_data_raw = proc_net_arp.read(-1).split("\n")[1:-1]

    parsed_arp_table = (dict(zip(('ip_address', 'type', 'flags', 'hw_address', 'mask', 'device'), v))
                        for v in (re.split('\s+', i) for i in arp_data_raw))

    return {d['ip_address']: d['hw_address'] for d in parsed_arp_table}

def get_devices_in_list():
    """
    Gets every device inside the subnet

    :return: List of devices
    :rtype: list ["ipv4", "ipv4", ...]
    """

    device_list = []
    device_list_str = []
    host = Host.objects.latest('pk')

    device_list = ipaddress.ip_network(host.ipv4_address + "/" + host.ipv4_subnet, strict=False).hosts()
    for dev in device_list:
        device_list_str.append(str(dev))
    return device_list_str

def get_available_devices_in_list():
    """
    Checks if hosts of get_hosts_in_list are available and removes localhost

    :return: List of available hosts
    :rtype: list ["ipv4", "ipv4", ...]
    """
    host = Host.objects.latest('pk')
    available_devices = []
    all_devices = get_devices_in_list()

    num_threads = 255   #One "big"subnet thread pool
    p = multiprocessing.dummy.Pool(num_threads)
    
    def ping(ip):
        success = os.system("ping -c 1 " + ip)
        if success == 0:
            available_devices.append(ip)

    p.map(ping, all_devices)

    
    
    #Deletes localhost from available list
    if host.ipv4_address in available_devices: available_devices.remove(host.ipv4_address)

    return available_devices

def create_devices():
    """
    Creates DB entry of devices if they dont already exist

    :return: List of mulitple devices stored in objects
    :rtype: list ["Device", "Device", ...]
    """

    available_devices = get_available_devices_in_list()
    arp_table_of_all_hosts = get_arp_table_linux()
    dev_list = []
        
    for deviceip in available_devices:
        #If device already exists in DB continue
        if arp_table_of_all_hosts.get(deviceip):
            if arp_table_of_all_hosts[deviceip] in Device.objects.filter(mac_address = arp_table_of_all_hosts[deviceip]):
                continue
            else:
                devmac = arp_table_of_all_hosts[deviceip]
                devname = "unknown"         #socket.gethostbyaddr(deviceip)
                dev = Device(hostname=devname, mac_address=devmac, ipv4_address=deviceip)
                dev.save()
                dev_list.append(dev)
        
    return dev_list

class DeviceGetAll(DetailView):
    if Host.objects.values():
        create_devices()
        model = Device
    pass

Ваше представление DeviceGetAll написано неправильно. Условие if должно быть помещено в некоторые методы представления, а не в определение класса.

Я не понимаю, что именно вы пытаетесь сделать, поэтому не могу знать, в какой метод вам нужно добавить код, но вы можете посмотреть на базовый код DetailView и посмотреть, может быть, некоторые из этих методов вам пригодятся. Я даже не знаю, является ли детальное представление лучшим местом для размещения кода, который создает экземпляры одной и той же модели; возможно, он также может идти после создания хоста.


Но если вы хотите использовать DetailView, то вы можете, например, переопределить метод get_object() из SingleObjectMixin (который является одним из родителей DetailView), ваш код может выглядеть так:

class DeviceGetAll(DetailView):
    model = Device

    def get_object(self, *args, **kwargs):
        if Host.objects.exists():
            create_devices()

        obj = super().get_object(*args, **kwargs)
        return obj

Также, вероятно, вы хотели использовать метод .exists() в условии if вместо .values().

К сожалению, все та же проблема. Я хочу проверить, есть ли данные в базе данных с моделью Host if Host.objects.exists(): Но данных нет, а с функцией exists() выкидывает ошибку. Может у @Ralf есть другая идея :). Спасибо за помощь

(В этом представлении он должен создавать устройства, только если существует Host)

class DeviceGetAll(DetailView):
    if Host.objects.exists():
        create_devices()
        model = Device

Ошибка

File "/home/X/NoAds/DjangoWebApp/webapp/urls.py", line 2, in <module>
  from . import views
File "/home/X/NoAds/DjangoWebApp/webapp/views.py", line 37, in <module>
  class DeviceGetAll(DetailView):
File "/home/X/NoAds/DjangoWebApp/webapp/views.py", line 38, in DeviceGetAll
  if Host.objects.exists():
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
  return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/query.py", line 808, in exists
  return self.query.has_results(using=self.db)
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/query.py", line 552, in has_results
  return compiler.has_results()
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1145, in has_results
  return bool(self.execute_sql(SINGLE))
File "/home/X/noads/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1175, in execute_sql
  cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 98, in execute
  return super().execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 66, in execute
  return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 75, in _execute_with_wrappers
  return executor(sql, params, many, context)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
  return self.cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/utils.py", line 90, in __exit__
  raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/utils.py", line 84, in _execute
  return self.cursor.execute(sql, params)
File "/home/X/noads/lib/python3.8/site-packages/django/db/backends/sqlite3/base.py", line 423, in execute
  return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: webapp_host
Вернуться на верх