Search code examples
pythondjangosqlitedjango-modelsbackend

Create Model for 4-D kind of array in Django


I have some logic constructed for my Database for a Django webapp but I am quite unable to convert it into Model form that can be used in Models.py :

User : U
Transaction-ID : T
Datetime : D
Transaction-ID Status-1 for a today : A[0]
Transaction-ID Status-2 for a today : A[1]
Transaction-ID Status-3 for a today : A[2]

For above a logic can be constructed with N users : U[N] where U[i] -> T[i][] transaction, and each transaction has 3 transactional attributes T[j] -> A[j][3]. How should I proceed with constructing a model for the given details. Also if possible how can I store date wise Model for the three A[k] statuses of Transaction and add them for a week wise and month wise average and proceed with making the db.

Use Case :

A particular user could have done variable number of Transactions, and for each transaction there is a key provided used to get the status of that particular transaction. Like the power points earned, bonus points earned and fame points earned. For periodically updating the 3 points earned daily, weekly and monthly across all transactions done by that user and storing them in the Database for each and every user what should be done.

Since my project is based on SQLite that runs inbuilt with Django framework which I am unfamiliar with, I need to understand how models should be used and how to implement this use case.

Calling it 4 dimensional because entry = U[N][M][3][D]


Solution

  • I put some part of my project for this purpose and apologize for not summarizing the code in this answer (because I think summarizing it maybe would have mistakes without test so I decided used copy-paste a tested code).


    When I want to read four nested Django admin model (4D) and use them in the code, I did the following procedures:

    models.py:

    from __future__ import unicode_literals
    from django.db import models
    from django.db.models.deletion import CASCADE
    
    MODBUS_TYPES = (('tcp', 'Tcp'), ('udp', 'Udp'), ('ascii', 'Ascii'), ('rtu', 'Rtu'))
    
    
    class BatteryMonitoringServer(models.Model):
        enable = models.BooleanField(default=True)
        name = models.CharField(max_length=150)
        server_ip = models.GenericIPAddressField(default='0.0.0.0', null=True)
    
        def __str__(self):
            return self.name
    
    class BatteryMonitoringDevice(models.Model):
        bm_id = models.ForeignKey(BatteryMonitoringServer, on_delete=CASCADE)
        enable = models.BooleanField(default=True)
        name = models.CharField(max_length=100, null=True)
        method = models.CharField(max_length=5, choices=MODBUS_TYPES)
        bm_device_ip = models.GenericIPAddressField(default='127.0.0.1', null=True)
        bm_device_port = models.IntegerField(default=5558, null=True)
        baud_rate = models.IntegerField(null=True, default=9600)
    
    class BatteryMonitoringSubDevice(models.Model):
        enable = models.BooleanField(default=True)
        name = models.CharField(max_length=100)
        unit = models.IntegerField(default=1)
        sub_bm_count = models.IntegerField(default=4, null=True, blank=True, name='bm')
        fk = models.ForeignKey(BatteryMonitoringDevice, on_delete=CASCADE)
    
    class BatteryMonitoringMeta(models.Model):
        key = models.CharField(max_length=100)
        value = models.CharField(max_length=100)
        module = models.ForeignKey(BatteryMonitoringSubDevice, on_delete=CASCADE)
    

    conf_reader.py

    from battery_monitoring.models import BatteryMonitoringServer
    from delta_device.utility import DictEncoder
    
    class BMSubDeviceConf(object):
        def __init__(
                self,
                start,
                name,
                unit,
                bm,
                meta_data):
    
            self._start = start
            self._name = name
            self._unit = unit
            self._bm = bm
            self._meta_data = meta_data
    
        @property
        def start(self):
            return self._start
    
        @property
        def name(self):
            return self._name
    
        @property
        def unit(self):
            return self._unit
    
        @property
        def bm(self):
            return self._bm
    
        @property
        def meta_data(self):
            return self._meta_data
    
    class BMDeviceConf(object):
        def __init__(
                self,
                bm_id,
                start,
                name,
                method,
                bm_device_ip,
                bm_device_port,
                baud_rate,
                sub_devices=None):
    
            self._id = bm_id
            self._start = start
            self._name = name
            self._method = method
            self._bm_device_ip = bm_device_ip
            self._bm_device_port = bm_device_port
            self._baud_rate = baud_rate
            self._sub_devices = sub_devices or []
    
        def add_sub_device(self, sub_device):
            self._sub_devices.append(sub_device)
    
        def get_sub_devices(self):
            return self._sub_devices
    
        @property
        def start(self):
            return self._start
    
        @property
        def id(self):
            return self._id
    
        @property
        def name(self):
            return self._name
    
        @property
        def bm_device_ip(self):
            return self._bm_device_ip
    
        @property
        def bm_device_port(self):
            return self._bm_device_port
    
        @property
        def baud_rate(self):
            return self._baud_rate
    
    class BMConf(object):
        def __init__(
                self,
                start,
                name,
                server_ip,
                devices=None,
        ):  # :( :| :) (: :p
    
            self._start = 'ON' if start else 'OFF'
            self._name = name
            self._server_ip = server_ip
            self._devices = devices or []
    
        def add_device(self, device):
            self._devices.append(device)
    
        def get_devices(self):
            return self._devices
    
        @property
        def start(self):
            return self._start
    
        @property
        def name(self):
            return self._name
    
        @property
        def server_ip(self):
            return self._server_ip
    
    def get_server():
        """Using list method to make a fast sql reading."""
        return list(BatteryMonitoringServer.objects.all())
    
    def get_devices(dev):
        return list(dev.batterymonitoringdevice_set.all())
    
    def get_sub_devices(sub_dev):
        return list(sub_dev.batterymonitoringsubdevice_set.all())
    
    def get_metadata(metric):
        return list(metric.batterymonitoringmeta_set.all())
    
    class BMReadConf(object):
        """BM configuration Reader"""
        def __init__(self):
            pass
    
        @classmethod
        def get_bm_config(cls):
            """Read BM metrics and return it on a object list"""
            result = list()
    
            for srv in get_server():
                data = BMConf(srv.enable,
                              srv.name,
                              srv.server_ip,)
    
                for dev in get_devices(srv):
                    device = BMDeviceConf(
                        dev.bm_id,
                        dev.enable,
                        dev.name,
                        dev.method,
                        dev.bm_device_ip,
                        dev.bm_device_port,
                        dev.baud_rate,
                    )
    
                    for sub_dev in get_sub_devices(dev):
                        meta_data = {}
    
                        for meta in get_metadata(sub_dev):
                            meta_data[meta.key] = meta.value
    
                        sub_device = BMSubDeviceConf(
                            sub_dev.enable,
                            sub_dev.name,
                            sub_dev.unit,
                            sub_dev.bm,
                            meta_data,
                            )
    
                        device.add_sub_device(sub_device)
    
                    data.add_device(device)
    
                result.append(data)
    
            return result
    

    Usage (test.py)

    from battery_monitoring.conf_reader import BMReadConf
    
    conf_obj = BMReadConf()
    configs = conf_obj.get_bm_config()
    
    for cnf in configs:
        print(cnf.name)  # This is name field in BatteryMonitoringServer Table.
        devices = cnf.get_devices()
        
        for dev in devices:
            print(dev.baud_rate)  # This is baud_rate field in second nested table.
            sub_devices = dev.get_sub_devices()
        
            for sub_dev in sub_devices:
                print(sub_dev.unit)  # This is unit field in third nested table. 
                print(sub_dev.meta_data)  # This is meta_data table (fourth nested table).   
    

    I hope this would be useful.


    [NOTE]:

    Fourth nested table (meta_data) has a incremented key/value fields.