DEV Community

DoriDoro
DoriDoro

Posted on

Django: several ForeignKey relationships in models

I have multiple models in my project, namely: Home, Payment, and PaymentPlan. The Payment model includes a ForeignKey relationship both to the Home model and to the PaymentPlan model. I need to find a way to access the name attribute of the PaymentPlan model, starting from an instance of the Home model.

from django.db import models

class Home(models.Model):
    # Fields for Home
    address = models.CharField(max_length=255)

class PaymentPlan(models.Model):
    # Fields for PaymentPlan
    name = models.CharField(max_length=255)

class Payment(models.Model):
    # Fields for Payment
    home = models.ForeignKey(Home, related_name='payments', on_delete=models.CASCADE)
    payment_plan = models.ForeignKey(PaymentPlan, related_name='payments', on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=10, decimal_places=2)
Enter fullscreen mode Exit fullscreen mode
# Get the Home instance (modify the filter to match your needs)
home_instance = Home.objects.get(id=1)

# Access related payments
payments = home_instance.payments.all()

# Get the payment plans through payments
for payment in payments:
    payment_plan_name = payment.payment_plan.name
    print(f"Payment Plan Name: {payment_plan_name}")
Enter fullscreen mode Exit fullscreen mode

Explanation:

  1. Get the Home instance:
  • home_instance = Home.objects.get(id=1): Retrieves a specific Home instance using its primary key.
  1. Access related Payment instances:
  • payments = home_instance.payments.all(): Uses the related_name (payments) defined in the Payment model’s ForeignKey to Home to retrieve all associated Payment instances.
  1. Access the PaymentPlan through Payment:
  • For each Payment instance, access the related PaymentPlan and print its name.

Using Django Shell for Ad-hoc Queries:

You can also work interactively in the Django shell:

python manage.py shell
Enter fullscreen mode Exit fullscreen mode

Inside the shell:

from yourapp.models import Home

# Get the Home instance
home_instance = Home.objects.get(id=1)

# Access related payments and their plans
for payment in home_instance.payments.all():
    payment_plan_name = payment.payment_plan.name
    print(f"Payment Plan Name: {payment_plan_name}")

Enter fullscreen mode Exit fullscreen mode

Utilizing Django Queryset Across Relationships:

If you prefer using queryset chaining to fetch and display payment plan names:

from yourapp.models import Home

# Get the Home instance 
home_instance = Home.objects.get(id=1)

# Fetch payment plans directly
payment_plans = PaymentPlan.objects.filter(payments__home=home_instance).distinct()

# Print payment plan names
for plan in payment_plans:
    print(f"Payment Plan Name: {plan.name}")

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • payments__home=home_instance: This filters PaymentPlan instances through the relationship chain Payment -> related to Home.

  • .distinct(): Ensures unique PaymentPlan instances, avoiding duplicates if there are multiple Payments for the same PaymentPlan.

By following this method, you can easily navigate the relationships and extract the PaymentPlan.name attribute starting from a Home instance using Django's powerful ORM capabilities.

Top comments (0)