How to create right relations between models in Django project - django

I am developing Django progect with following models:
class Aircraft_fleet(models.Model):
Aircraft_type = models.CharField(max_length=16)
Aircraft_Serial_Number = models.CharField(max_length=16)
Engine_1_Ser_Num = models.ForeignKey('Engine', related_name='Engine_1', on_delete=models.PROTECT)
Engine_2_Ser_Num = models.ForeignKey('Engine', related_name='Engine_2', on_delete=models.PROTECT)
class Engine(models.Model):
Ser_Num = models.PositiveIntegerField()
Flight_Num = models.CharField(max_length=80)
Flight_Date = models.DateField()
Oil_Quantity_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Quantity_Arrival = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Arrival = models.DecimalField(max_digits=5, decimal_places=2)
One Aircraft (Aircraft_fleet model) have two Engine Ser_Num (different of course). Particular Engine Ser_Num (Engine model) is fitted only on one partucular Aircraft.
The thing is that in database, "Engine" table has multiple records for each Engine "Ser_Num".
See picture below:
Engine Model in database look like:
I can't determine how to create the proper relations between these two models.
Currently, relation is one to many, but it doesn't work. Following error apears:
django.db.utils.IntegrityError: The row in table 'oilcons_aircraft_fleet' with primary key '1' has an invalid foreign key: oilcons_aircraft_fleet.Engine
_2_Ser_Num_id contains a value '193262' that does not have a corresponding value in oilcons_engine.id.

Okay if I understand you correctly the engine_ser_num does not belong to the Aircraft_fleet but to the Engine.
Go with this:
class Aircraft_fleet(models.Model):
Aircraft_type = models.CharField(max_length=16)
Aircraft_Serial_Number = models.CharField(max_length=16)
class Engine(models.Model):
aircraft = models.ForeignKey('Aircraft_fleet', on_delete=models.CASCADE)
Ser_Num = models.PositiveIntegerField()
Flight_Num = models.CharField(max_length=80)
Flight_Date = models.DateField()
Oil_Quantity_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Quantity_Arrival = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Arrival = models.DecimalField(max_digits=5, decimal_places=2)
Now one Engine can be related to one Aircraft_fleet
e = Engine.objects.all().first()
print(e.aircraft.Aircraft_type)
And one Aircraft_fleet can be related to multiple Engines
af = Aircraft_fleet.objects.all().first()
for engine in af.engine_set.all():
print(engine.Ser_num)
Let me know how it goes.
important edit:
For sure you need to do the migrations correctly and migrate it. Because that IntegrityError could also be caused by "old" data inside the database that still have "old" relationships.

possible structure:
class Aircraft(models.Model):
Aircraft_type = models.CharField(max_length=16)
Aircraft_Serial_Number = models.CharField(max_length=16)
aircraft may have 2/3/4 ... engines:
class Engine(models.Model):
Ser_Num = models.PositiveIntegerField()
aircraft = models.ForeignKey('Aircraft', ....) # engine belongs to an aircraft
...
class Flight(models.Model):
Flight_Num = models.CharField(max_length=80)
Flight_Date = models.DateField()
class EngineDataRecord(models.Model):
flight = models.ForeignKey('Flight', ....) # Engine Data record is for a certain flight
engine = models.ForeignKey('Engine', ....) # and a certain engine
Oil_Quantity_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Quantity_Arrival = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Departure = models.DecimalField(max_digits=5, decimal_places=2)
Oil_Temperature_Arrival = models.DecimalField(max_digits=5, decimal_places=2)

Related

Group By Django queryset by a foreignkey related field

I have a model Allotment
class Kit(models.Model):
kit_types = (('FLC', 'FLC'), ('FSC', 'FSC'), ('Crate', 'Crate'), ('PP Box', 'PP Box'))
kit_name = models.CharField(max_length=500, default=0)
kit_type = models.CharField(max_length=50, default=0, choices=kit_types, blank=True, null=True)
class AllotmentFlow(models.Model):
flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
kit = models.ForeignKey(Kit, on_delete=models.CASCADE)
asked_quantity = models.IntegerField(default=0)
alloted_quantity = models.IntegerField(default=0)
class Allotment(models.Model):
transaction_no = models.IntegerField(default=0)
dispatch_date = models.DateTimeField(default=datetime.now)
send_from_warehouse = models.ForeignKey(Warehouse, on_delete=models.CASCADE)
flows = models.ManyToManyField(AllotmentFlow)
For a stacked graph I am trying to get the data of different kit_type alloted in different months.
For that I have tried annotate but it isn't getting the desired results
dataset = Allotment.objects.all().annotate(
month=TruncMonth('dispatch_date')).values(
'month').annotate(dcount=Count('flows__kit__kit_type')).values('month', 'dcount')
Expected Output:
[{'month':xyz, 'kit_type':foo, count:123},...]
I am getting the month and count of kit type from above but how do I segregate it by kit_type?
having a field that represents your choice field names in this query is difficult
instead how about use the Count filter argument and annotate to get what you want
dataset = Allotment.objects.all().annotate(month=TruncMonth('dispatch_date')).values('month').annotate(
FLC_count=Count('flows__kit__kit_type', filter=Q(flows__kit__kit_type="FLC")),
FSC_count=Count('flows__kit__kit_type', filter=Q(flows__kit__kit_type="FSC")),
Crate_count=Count('flows__kit__kit_type', filter=Q(flows__kit__kit_type="Crate")),
PP_Box_count=Count('flows__kit__kit_type', filter=Q(flows__kit__kit_type="PP_Box")),
).values('month', 'FLC_count', 'FSC_count', 'Crate_count', 'PP_Box_count')

How to change field value dynamically depended on dropdown selection in django

I've been searching Google, but couldn't find a simple answer to this problem:
I have a django models that stores students information and three other models like this:
class Level(models.Model):
name = models.CharField(max_length=50)
class Pricing(models.Model):
level = models.ForeignKey(Level, on_delete=models.PROTECT)
price = models.PositiveSmallIntegerField(default=0)
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
price = models.PositiveSmallIntegerField(default=0)
I want the Enrollment.price field to be populated dynamically depending on Enrollment.level field value. In javascript, it amounts to setting an event listener to Enrollement.level, but I can't find the equivalent in django.
hi you can modify your save method to fill automatically field price from Level model
Enrollment.level
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
price = models.PositiveSmallIntegerField()
def save(self,*args,**kwargs):
self.price = Pricing.objects.get(level=self.level).price
super().save(*args,*kwargs)
but I recommend to rewrite your model like above example because its simple and you can access to price of every level directly
like Enrollment.level.price
class Level(models.Model):
level = models.CharField(max_length=50,unique=True)
price = models.PositiveSmallIntegerField(default=0)
class Enrollment(models.Model):
student = models.ForeignKey(Student, on_delete=models.PROTECT)
level = models.ForeignKey(Level, on_delete=models.CASCADE)
date_enrolled = models.DateField()
I hope it helped you

How to annotate a field from a related model to queryset?

I have two models:
Lot:
class Lot(models.Model):
name = models.CharField(max_length=150, db_index=True, unique=True)
step = models.DecimalField(max_digits=2, decimal_places=2)
and Bid:
class Bid(models.Model):
auction = models.ForeignKey('Lot', on_delete=models.CASCADE)
user_id = models.ForeignKey(User, on_delete=models.CASCADE, to_field='username')
value = models.DecimalField(max_digits=5, decimal_places=2)
Every instance of Lot can have a few Bids, however any instance of Bid is only related to a particular Lot.
I have a working annotation for Lot that gives me the max_bid and next_bid values:
self.auc_set = Lot.objects.annotate(max_bid=Max('bid__value'), next_bid=(Max('bid__value') + F('step')))
And what i can't achieve is getting 3 annotated fields: max_bid, next_bid and last_bidder.
Something like:
self.auc_set = Lot.objects.annotate(max_bid=Max('bid__value'), next_bid=(Max('bid__value') + F('step')), last_bidder=F(bid_set).get('auction_id'= F('id'), 'value'=max_bid)['user_id'])
but working.
Update:
The problem would be solved if i knew how to pass the 'id' from Lot.objects.annotate to the Bid.objects.get part:
auc_set = Lot.objects.annotate(last_bidder=Bid.objects.get(auction_id__exact='need_to_put_something_here', value=Max('value').user_id)

Get all objects from severall models that share the same foreign key - Is it possible?

I am facing a problem designing a database with Django framework that i can't seem to solve. Say i have the following models:
class Report(models.Models):
equipment = models.ForeignKey(Equipament)
category = models.ForeignKey(Category)
date = models.DateField()
user = models.CharField(max_length=100)
class TestA(models.Model):
report = models.ForeignKey(Report)
lasers = models.FloatField()
table = models.FloatField()
dose = models.FloatField()
pass_fail = models.NullBooleanField()
class TestB(models.Model):
report = models.ForeignKey(Report)
ctdi = models.FloatField()
pass_fail = models.NullBooleanField()
class TestC(models.Model):
report = models.ForeignKey(Report)
pass_fail = models.NullBooleanField()
My question is: Is it possible to get all objects from Tests B, C and D that share the same oject from Report? I do not wish to query each model (TestB, TestC or TestD) individually because in reality i have many more Test models.
Any help is much apreciated.
Why do you have three different models that are essentially the same thing? Try this:
class Report(models.Models):
equipment = models.ForeignKey(Equipment)
category = models.ForeignKey(Category)
date = models.DateField()
user = models.CharField(max_length=100)
class Result(model.Model):
report = models.ForeignKey(Report)
status = models.BooleanField(default=False)
lasers = models.FloatField(blank=True, null=True)
table = models.FloatField(blank=True, null=True)
ctdi = models.FloatField(blank=True, null=True)
dose = models.FloatField(blank=True, null=True)
title = models.CharField(max_length=200)
Just give each report a title, such as 'TestA' / 'TestB' instead of creating an entirely new model.
To get all results for a report:
r = Result.objects.filter(report=Report.objects.get(pk=1))

Querying from child of model given django inheritance and m2m link to parent

Among my models, I have Exercise which has a m2m link to Workout. I also have WorkoutPlan and LogBook which are types of Workouts. WorkoutPlan is where ideal workouts are stored. LogBook is where a user stores the workout they actually completed. They can also link a LogBook to a WorkoutPlan to indicate that the actual performance was connected to an original ideal plan.
class Exercise(NameDescModel):
muscles = models.ManyToManyField(Muscle, blank=True)
groups = models.ManyToManyField(Group, blank=True)
priority_score = models.DecimalField(max_digits=5, decimal_places=3, editable=False, default = 0)
frequency = models.IntegerField()
time_period = models.CharField(max_length=2, choices=TIME_PERIOD_CHOICES,default=WEEK)
last_p_calc_date = models.DateField("Date of Last Priority Recalculation", blank=True, null=True, default=datetime.now)
class Workout(NameDescModel):
exericises = models.ManyToManyField(Exercise, through='Measurement')
class WorkoutPlan(Workout):
priority_score = models.DecimalField(max_digits=5, decimal_places=3, editable=False, default = 0)
frequency = models.IntegerField()
time_period = models.CharField(max_length=2, choices=TIME_PERIOD_CHOICES,default=WEEK)
time_estimate = models.IntegerField()
last_p_calc_date = models.DateField("Date of Last Priority Recalculation", blank=True, null=True, default=datetime.now)
class LogBook(Workout):
workout_date = models.DateField(default=datetime.now)
notes = models.TextField(blank=True)
workout_plan = models.ForeignKey(WorkoutPlan, blank=True, null=True)
For a given exercise, I want to pull all of the WorkoutPlans that the exercise is in.
exercise_list = Exercise.objects.order_by('-last_p_calc_date')
for exercise in exercise_list:
print exercise
workout_list = []
for workout in exercise.workout_set.all():
workout_list.append(workout)
print list(set(workout_list))
print ""
I'm realizing that the list of workouts include both WorkoutPlans and LogBooks because exercise is attached to Workout, not to WorkoutPlans or LogBooks specifically.
How might I pull Workouts that are affiliated only to WorkoutPlans?
I think you've over-used inheritance here.
I guess you wanted to put the exercises field into a base model because WorkoutPlan and LogBook both have that field. But it seems like in reality WorkoutPlan and LogBook are different types of thing, rather than sub-types of Workout.
Possibly don't you need the exercises field on the LogBook model at all, since it has a foreign key to WorkoutPlan which seems a sensible place to record the exercises... unless you want to record the difference between the plan and exercises actually performed?
I would model it like this:
class Exercise(NameDescModel):
muscles = models.ManyToManyField(Muscle, blank=True)
groups = models.ManyToManyField(Group, blank=True)
priority_score = models.DecimalField(max_digits=5, decimal_places=3, editable=False, default = 0)
frequency = models.IntegerField()
time_period = models.CharField(max_length=2, choices=TIME_PERIOD_CHOICES,default=WEEK)
last_p_calc_date = models.DateField("Date of Last Priority Recalculation", blank=True, null=True, default=datetime.now)
class WorkoutPlan(Workout):
exercises = models.ManyToManyField(Exercise, through='Measurement')
priority_score = models.DecimalField(max_digits=5, decimal_places=3, editable=False, default = 0)
frequency = models.IntegerField()
time_period = models.CharField(max_length=2, choices=TIME_PERIOD_CHOICES,default=WEEK)
time_estimate = models.IntegerField()
last_p_calc_date = models.DateField("Date of Last Priority Recalculation", blank=True, null=True, default=datetime.now)
class LogBook(Workout):
exercises = models.ManyToManyField(Exercise, through='Measurement')
workout_date = models.DateField(default=datetime.now)
notes = models.TextField(blank=True)
workout_plan = models.ForeignKey(WorkoutPlan, blank=True, null=True)
You can then query either WorkoutPlans or LogBooks from an Exercise instance:
exercise_list = Exercise.objects.order_by('-last_p_calc_date')
for exercise in exercise_list:
print exercise
workout_list = exercise.workoutplan_set.all()
print ""