0

I've been sketching out a new Django app with the runserver dev server running in a background window to tracking network wiring, and briefly had this in my model:

class Interface(models.Model):
    name = models.CharField(max_length=200)
    # (blah)

class Connection(models.Model):
    interface_from = models.ForeignKey(Interface, related_name="connections")
    interface_to = models.ForeignKey(Interface, related_name="connections")
    source = models.CharField(max_length=32)

Before I realised I couldn't have the same related_name for two fields. I guess I will need to write something special to find all connections related to an interface, since they might be the 'to' or 'from' end of the connection (be interested in any insight on a nicer way to do that - like a "Set" field)

At this point, I hadn't done a makemigrations, but on stopping the server, and making my migrations, I get:

ERRORS:
autodoc.Connection.interface_from: (fields.E304) Reverse accessor for 'Connection.interface_from' clashes with reverse accessor for 'Connection.interface_to'.
HINT: Add or change a related_name argument to the definition for 'Connection.interface_from' or 'Connection.interface_to'.

Even though there isn't a clash anymore. I don't see a migrations directory anywhere - this was the initial pass at the models - so where is the memory of this error coming from after a restart of the dev server?

Edit: To make it clearer, my Connection model now looks like:

class Connection(models.Model):
    interface_from = models.ForeignKey(Interface)
    interface_to = models.ForeignKey(Interface)
    source = models.CharField(max_length=32)
AnotherHowie
  • 818
  • 1
  • 11
  • 28

2 Answers2

2

In case you don't need a backwards relation add related_name='+' to your field definition. From the doc:

user = models.ForeignKey(User, related_name='+')
Ivan
  • 5,803
  • 2
  • 29
  • 46
  • Without this, I'll get (mostly useless but not harmful) Interface.interface_from_set and Interface.interface_to_set right? Good to know that can be disabled, once the original problem is resolved... – AnotherHowie Sep 24 '15 at 15:15
1

In your first example:

class Connection(models.Model):
    interface_from = models.ForeignKey(Interface, related_name="connections")
    interface_to = models.ForeignKey(Interface, related_name="connections")

You're telling Django to create two different connections attributes on Interface for the backwards relationships back to Connection, which obviously doesn't work.

In your second example:

class Connection(models.Model):
    interface_from = models.ForeignKey(Interface)
    interface_to = models.ForeignKey(Interface)

You're telling Django to use its default connections_set name for two different attributes for the backwards relationships back to Connection, which also doesn't work.

The fix is to use related_name='+' (as @Ivan said) to disable the backwards relationships completely or two explicitly provide two different related_name attributes so that the backwards relationship attributes' names don't clash.

Community
  • 1
  • 1
Josh Kelley
  • 56,064
  • 19
  • 146
  • 246
  • D'oh - I was thinking it would use the field name not the model name for the backwards relationship for some reason. Thanks for the explanation! – AnotherHowie Sep 24 '15 at 15:37