Prendergast
Prendergast

Reputation: 9

How can I formulate this ForeignKey scheme?

I'm finding some difficulty resolving this problem in designing my Django models.

The essential setup is a bipartite graph allowing for parallel edges. Trying our hardest to keep vertices in a single class, what is the most succinct means we have for querying all the edges incident to a vertex?

The instruction to keep vertices encoded by a single class comes from a (possibly misguided) urgency I have to consolidate vertices within a signle database.

I considered using an inheritance scheme, wherein vertices in a partition inherit from a polymorphic parent Vertex class, but I kept tripping up, and really started worrying about whether Django had some (unkown to me) native and concise means of doing this.

The current setup is about:

class Vertex(models.Model):
    PARTITION_CHOICES = (
        ('a': 'type a'),
        ('b': 'type b')
    )
    partition = models.CharField(choices=PARTITION_CHOICES)
    # A bunch of other attributes...

class Edge(models.Model):
    vertex_a = models.ForeignKey(Vertex, limit_choices_to={'partition': 'a'}, related_name='edges')
    vertex_b = models.ForeignKey(Vertex, limit_choices_to={'partition': 'b'}, related_name='edges')
    # More attributes...

The obvious issue here is that both these foreign keys have the same related name, therefore clash. Otherwise, I would be able to quite neatly ask for vertex.edges.all().

Tips from the wise?

Upvotes: 0

Views: 47

Answers (1)

pilotandy
pilotandy

Reputation: 87

You ask for tips from the wise, I'm not too wise, but I'll do my best.

For your related names, just make them the same as the field name, or dispense with them altogether. What is `related_name` used for in Django?

I think there maybe easier ways to query where the vertices are used, but the only way I can think of is something like this:

for edge in Edge.objects.all():
   vertex_a = edge.vertex_a
   vertex_b = edge.vertex_b

If you want to have more than two vertices per edge (or just two with one field name), you can use the ManyToManyField. https://docs.djangoproject.com/en/2.0/topics/db/examples/many_to_many/

class Vertex(models.Model):
    PARTITION_CHOICES = (
        ('a': 'type a'),
        ('b': 'type b')
    )
    partition = models.CharField(choices=PARTITION_CHOICES)
    # A bunch of other logic...

class Edge(models.Model):
    vertcies = models.ManyToManyField(Vertex, related_name='vertices')


for edge in Edge.objects.all():
   for vertex in edge.vertices.all():
      # some logic

Upvotes: 1

Related Questions