AnthonyB
AnthonyB

Reputation: 74

Django Many-to-Many relionships

I'm trying to use Django for the time and plug it on an excisting PostgreSQL database. I use python manage.py inspectdb to extract my database's models but when I want to sync my database I have this error :

CommandError: One or more models did not validate:
api.subdomain: Accessor for field 'sub_domain' clashes with related field 'Domain.subdomain_set'. Add a related_name argument to the definition for 'sub_domain'.
api.subdomain: Accessor for field 'domain' clashes with related field 'Domain.subdomain_set'. Add a related_name argument to the definition for 'domain'.

Here are the classes that pose problem :

class Domain(models.Model):
    id = models.IntegerField(primary_key=True)
    extra_data = models.CharField(max_length=127, blank=True)
    class Meta:
        managed = False
        db_table = 'domain'

class SubDomain(models.Model):
    sub_domain = models.ForeignKey(Domain)
    domain = models.ForeignKey(Domain)
    extra_data = models.CharField(max_length=127, blank=True)
    class Meta:
        managed = False
        db_table = 'sub_domain'

I did the creation with sqlAlchemy and this is what I did to make it worked:

class Domain(Base):                                                                                                               
    __tablename__ = 'domain'                                                                                                        
    id = Column(Integer,                                                                                     
                primary_key=True,                                                                            
                autoincrement=True)                                                                     
    extra_data = Column(String(127))                                                                    
    sub_domains = relationship("SubDomain",                                                                           
                               backref="domain",                                                                      
                               primaryjoin="Domain.id == SubDomain.domain_id")

class SubDomain(Base):
    __tablename__ = 'sub_domain'                                                                                                                                                                                                           
    sub_domain_id = Column(Integer,                                                                                   
                           ForeignKey('domain.id'),                                                                   
                           primary_key=True)                                                                          
    domain_id = Column(Integer,                                                                                   
                       ForeignKey('domain.id'),                                                                   
                       primary_key=True)                                                                                 
    sub_domain = relationship("Domain",                                                                            
                              foreign_keys=[sub_domain_id],                                                        
                              backref="sub_domains_assocs")
    extra_data = Column(String(127)) 

To explain my relationship :

Each Domain has multiple SubDomain and each SubDomain is itself a Domain, their relations is qualify by the field extra_data of SubDomain. Each SubDomain can have multiple parents. Each Domain has their own specifications defined in his field extra_data.

I tried multiple answer found on StackOverflow but none of them were working for my case.

Thanks for your help !

Upvotes: 0

Views: 91

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599490

In your SQLAlchemy example you've explicitly set the backref to avoid a conflict: you need to do the same in the Django version using related_name.

class SubDomain(models.Model):
    sub_domain = models.ForeignKey(Domain)
    domain = models.ForeignKey(Domain, related_name='sub_domains_assocs')
    extra_data = models.CharField(max_length=127, blank=True)

This does seem a slightly strange model though; you might be better off with an explicit hierarchy provided by something like MPTT.

Upvotes: 1

Related Questions