Suresh
Suresh

Reputation: 967

Django Model : How to combine the reverse access sets from two foreignkey fields?

In my django models file, I have:

class Node(models.Model):
   name = models.CharField(max_length=16)

class Segment(models.Model):
   start = models.ForeignKey(Node, related_name='start_segments')
   end = models.ForeignKey(Node, related_name='end_segments')

From the Node object, I would like to access all segment objects, that have either start or end pointing to the node, from a single attribute name, like:

node_x.segment_set

However this is not possible as far as I could see. I have provided two different related_name-s only to avoid the error thrown otherwise. Otherwise, I would like to create a single set combining the two.

I can create a utility method which will return the combined set. However, it would not be available for queries. In my application, I often need to search considering all segments connected to the node.

Upvotes: 3

Views: 669

Answers (2)

sthzg
sthzg

Reputation: 5554

To retrieve a QuerySet you can make use of Q objects (see Complex lookups with Q objects).

from django.db.models import Q
results = Segment.objects.filter(Q(start=node_x) | Q(end=node_x))

To access that more quickly you can define it as a property:

from django.db import models
from django.db.models import Q

class Node(models.Model):
    name = models.CharField(max_length=16)

    @property
    def segments(self):
        return Segment.objects.filter(Q(start=self) | Q(end=self))

Now in your code you can retrieve the segments by accessing the property:

In [1]: print node_x.segments  # or print(node_x.segments) in Python 3
Out[1]: [<Segment: Segment object>, <Segment: Segment object>, ...]

Upvotes: 1

RemcoGerlich
RemcoGerlich

Reputation: 31270

I think you should either use

Segment.objects.filter(start=node_x) | Segment.objects.filter(end=node_x)

or

node_x.start_segments.all() | node_x.end_segments.all()

Upvotes: 1

Related Questions