Through attribute in django-orm
This is the basic m2m relationship:
from django.db import models class Vessel(models.Model): name = models.CharField(max_length=255) stock = models.IntegerField(default=0) def __str__(self) -> str: return self.name class Deal(models.Model): collateral = models.ManyToManyField( Vessel, blank=True, ) register_date = models.DateTimeField( null=True, blank=True ) has_new = models.BooleanField( default=True, null=True ) def __str__(self) -> str: return f"#{self.pk}"
Query the above created table in Django shell like so:
In [9]: deal = Deal.objects.last() In [10]: collateral_vessels = deal.collateral.all() In [11]: print(collateral_vessels) <QuerySet [<Vessel: Two>, <Vessel: Three>]>
In the case above we CAN NOT control the app_deal_collateral
table. Which is
sad… let's say we want to control it, we then use the through
attribute.
We will inform Django not to use the default table like above, but in this case we want to use OUR OWN table.
We also infom that we WILL NOT want to control the collaterals over the DEAL model/admin page, but over the Collaterals page/admin page:
Will do that with through
attribute:
from django.db import models class Vessel(models.Model): name = models.CharField(max_length=255) stock = models.IntegerField(default=0) def __str__(self) -> str: return self.name class Deal(models.Model): collaterals = models.ManyToManyField( Vessel, blank=True, through='Collateral', ) register_date = models.DateTimeField( null=True, blank=True ) has_new = models.BooleanField( default=True, null=True ) def __str__(self) -> str: return f"#{self.pk}" class Collateral(models.Model): vessel = models.ForeignKey( Vessel, on_delete=models.DO_NOTHING, ) deal = models.ForeignKey( Deal, on_delete=models.DO_NOTHING, null=True ) quant = models.PositiveIntegerField( null=True, ) charfield = models.CharField(max_length=255) is_new = models.BooleanField( default=True, blank=True ) def __str__(self) -> str: return str(self.part)
Db structure then:
App_collateral then becomes like a control center from which you can control all the relationships, etc.
Deal admin page, we can not see the collaterals(vessels) here.
What we can see is another model in the admin called collaterals.
This is good if you actually want to separately create Deal and Vessel objects and then connect them in one in Collateral model.
Query like such(using shell_plus with print sql):
But what if you want to modify the collaterals from the Deal model?
Answer - inline
from django.contrib import admin from .models import * class CollateralInline(admin.TabularInline): model = Collateral extra = 1 class DealAdmin(admin.ModelAdmin): inlines = [CollateralInline] admin.site.register(Deal, DealAdmin) admin.site.register(Vessel) admin.site.register(Collateral)