0

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?

  • A foreign key associates one model with another. What is the "Binary" model? Shouldn't it be ref_a = models.ForeignKey(Vertices, ...)? Also, use the singlar of anything for a model name i.e. Edge, Vertex, etc. – pilotandy Jan 19 '18 at 19:09
  • Yep. My bad. The 'Binary" reference was left over from a draft of the post. – Prendergast Jan 19 '18 at 19:11
  • Unfortunately "allowing for parallel edges", "express a lot of common logic", "both vertices to be shared within the same database" & "querying of all the edges incident to a vertex" are so vague they don't mean anything. Please say what you mean in terms of your graph (nodes & edges) or the binary relation/association that it corresponds to. Beware that "relationship" gets used for two different notions--relations/associations on values/entities (in the relational & ER models) (represented by tables) and for FKs (in pseudo-ER methods). – philipxy Jan 19 '18 at 21:44
  • Updated to hopefully clarify. – Prendergast Jan 19 '18 at 22:09
  • Your question is improved enough that I can tell you this is a faq, google (my comments re) sql/database subtypes/inheritance/polymorphism and also re (an antipattern for that) multiple/many FKs to multiple/many tables. You have two *(sub)types* of vertex. PS You still use words & phrases that, although they may mean something to someone knowing what's going on, do not explain what is going on, so are unclear. Adding "essentially" does not clarify. Clarifying clarifies. To be clear we must use enough words, phrases & sentences to say what we mean. – philipxy Jan 20 '18 at 21:29
  • Possible duplicate of [How can you represent inheritance in a database?](https://stackoverflow.com/questions/3579079/how-can-you-represent-inheritance-in-a-database) – philipxy Jan 20 '18 at 21:32
  • Your response was helpful, even if it was pithy. – Prendergast Jan 26 '18 at 15:14

1 Answers1

1

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
pilotandy
  • 89
  • 4