Home > Software design >  Get queryset of related one to one fields
Get queryset of related one to one fields

Time:09-07

I have 3 models:

class BillingNumbering(models.Model):
    number = models.IntegerField()
    date = models.DateField(default=now)

class Invoice(models.Model):
    number = models.OneToOneField(BillingNumbering, on_delete=models.PROTECT)
    created_at = models.DateTimeField(auto_now_add=True,
                                      null=True, blank=True)

class DamageClaim(models.Model):
    number = models.OneToOneField(BillingNumbering, on_delete=models.PROTECT)
    created_at = models.DateTimeField(auto_now_add=True,
                                      null=True, blank=True)

I want to query only those BillingNumbering objects that is connected to either Invoice or DamageClaim.

So if I have

  • <BillingNumbering: 1> - connected to invoice
  • <BillingNumbering: 2> - connected to damage claim
  • <BillingNumbering: 3> - connected to None where instance.invoice or instance.damageclaim will result to ObjectDoesNotExist Error.

Then I only want to return <BillingNumbering: 1> and <BillingNumbering: 2> with BillingNumbering filter

UPDATED The answer of WoodyG below gave me an idea. I was able to solve it with below:

from django.db.models import Q

qs = BillingNumbering.objects.filter(Q(damageclaim__isnull=False) | Q(invoice__isnull=False))

CodePudding user response:

You can add a related_name field to both Invoice and DamageClaim

class Invoice(models.Model):
    number = models.OneToOneField(
        BillingNumbering,
        on_delete=models.PROTECT,
        related_name="invoice_billing_number",
    )
    created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)

class DamageClaim(models.Model):
    number = models.OneToOneField(
        BillingNumbering,
        on_delete=models.PROTECT,
        related_name="damageclaim_billing_number",
    )
    created_at = models.DateTimeField(auto_now_add=True, null=True, blank=True)

Then you should be able to query for the billing objects associated with Invoices and DamageClaims, respectivelly - like this:

invoice_billing = BillingNumbering.objects.values_list("invoice_billing_number")
damageclaim_billing = BillingNumbering.objects.values_list("damageclaim_billing_number")

CodePudding user response:

I think this is what you are looking for.

qs = BillingNumbering.objects.prefetch_related('invoice_set', 'demageclaim_set')

In case you are curious about where I'm getting invoice_set and demageclaim_set, these are the default name given by Django in case you don't provide any related_name in your ForeignKey or other relation fields. documentation link for more detail about related_name

  • Related