Reputation: 5654
I'm working on a project using Python(3.7) and Django(3) in which I have to create some models to store reports. There are 4 different models to represents each type of report with only 2 common fields(RequestId
, InstCode
) but the rest of the fields are different. In the end, I have to display the 10 recent reports (mixed from all models) on the home page.
Here's how I have implemented my models at the moment:
From models.py
:
class DistributionReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
Currency = models.CharField(max_length=3, blank=False)
Denomination = models.IntegerField(blank=False, default=0)decimal_places=2)
date = models.DateField(default=datetime.date.today)
class Meta:
verbose_name = 'Distribution Report'
def __str__(self):
return self.RequestId
class ExpenditureReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
StaffExpenditure = models.DecimalField(max_digits=12, decimal_places=2)
Month = models.IntegerField(blank=False, default=0)
Quarter = models.IntegerField(blank=False, default=0)
Year = models.IntegerField(blank=False, default=0)
class Meta:
verbose_name = 'Expenditure Report'
def __str__(self):
return self.RequestId
class StorageReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
Currency = models.CharField(max_length=5, blank=False)
Denomination = models.IntegerField(blank=False, default=0)
date = models.DateField(default=datetime.date.today)
class Meta:
verbose_name = 'Processing Report'
def __str__(self):
return self.RequestId
class AssetsReport(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
AssetClassificationId = models.IntegerField(blank=False, default=0)
VaultCapacity = models.DecimalField(max_digits=10, decimal_places=2)
Year = models.IntegerField(blank=False, default=0)
HalfOftheYear = models.IntegerField(blank=False, default=0)
class Meta:
verbose_name = 'Assets Report'
def __str__(self):
return self.RequestId
What is the best way to structure these models, so I can query the recent reports ( It can be of any type)?
Upvotes: 0
Views: 95
Reputation: 21807
Look into how normalization works, since all models have 2 common fields lets say you have a table called Report and it has the fields RequestId
and InstCode
. Now all your other models can be said to be in a XYZReport is a Report
kind of relationship.
You can achieve this using a OneToOne Field like so:
class Report(models.Model):
RequestId = models.CharField(max_length=256, blank=False, default=0)
InstCode = models.CharField(max_length=3, blank=False)
DISTRIBUTION = 'DI'
EXPENDITURE = 'EX'
STORAGE = 'ST'
ASSETS = 'AS'
REPORT_TYPE_CHOICES = [
(DISTRIBUTION, 'Distribution Report'),
(EXPENDITURE, 'Expenditure Report'),
(STORAGE, 'Storage Report'),
(ASSETS, 'Assets Report'),
]
report_type = models.CharField(
max_length=2,
choices=REPORT_TYPE_CHOICES,
default=DISTRIBUTION,
)
# Any more common fields
class DistributionReport(models.Model):
report = models.OneToOneField(
Report,
on_delete=models.CASCADE,
related_name = 'distribution_report'
)
# Other fields
# Other Report models in similar fashion
Now whenever making an object of any kind of report also make an object of Report
and assign it to report attribute of the models. Save both the models, also to figure out what kind of report an instance of Report is add the relevant report_type to the report instance like so:
report.report_type = Report.DISTRIBUTION # In case of Distribution Report
To figure out whether an instance of Report is of a particular type:
report.report_type == report.DISTRIBUTION # will get whether Report is a DistributionReport
To get the specific types object use the related_name set in the OneToOne Field:
distribution_report = report.distribution_report
Upvotes: 2