Django Bi-directional ManyToMany - How to prevent table creation on second model?

前端 未结 4 654
情书的邮戳
情书的邮戳 2021-01-31 05:51

I have two models, each has a shared ManyToMany, using the db_table field. But how do I prevent syncdb from attempting to create the shared table, for the second model?

相关标签:
4条回答
  • 2021-01-31 06:11
    class Awesome(models.Model):
     one = models.TextField()
     class Meta:
      # Prevent table creation. 
      abstract = True
    

    http://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes

    It's not what you're looking for, but it's the closest they have I belive. Would it not be simpler to make a view?

    Maybe:

    class Awesome(models.Model):
      one = models.CharField(max_length = 255)
      two = models.CharField(max_length = 255)
    
    class AwesomeOne(Awesome):
      fieldOne = models.ForeignKey(User, related_name = 'one')
      class Meta:
       abstract = True
    class AwesomeTwo(Awesome):
      fieldTwo = models.ForeignKey(User, related_name = 'two')
      class Meta:
       abstract = True
    

    Then, you can have one table created and override the __getattr__ to block access to the original fields.

    0 讨论(0)
  • 2021-01-31 06:12

    You don't need to put a ManyToManyField on both sides of the relation. Django will do that for you.

    You probably want something more like this:

    class Model1(models.Model):
        name = models.CharField(max_length=128)
        ...
    
    class Model2(models.Model):
        name = models.CharField(max_length=128)
        othermodels = models.ManyToManyField(Model1, through='Model1Model2')
        ...        
    
    class Membership(models.Model):
        class Meta:
            db_table = 'model1_model2'
        model1 = models.ForeignKey(Model1)        
        model2 = models.ForeignKey(Model2)
    

    When you're working with your models, an instance of Model1 will have a othermodels_set field which is automatically added by django. Instances of Model2 will have othermodels.

    0 讨论(0)
  • 2021-01-31 06:14

    I also found this solution, which worked perfectly for me :

    class Test1(models.Model):
        tests2 = models.ManyToManyField('Test2', blank=True)
    
    class Test2(models.Model):
        tests1 = models.ManyToManyField('Test1', through=Test1.tests2.through, blank=True)
    
    0 讨论(0)
  • 2021-01-31 06:15

    In Django ManyToMany are bi-directional by default. The think is that you only have to define it on one model, not on both (and usually you don't need to give a name to the table):

    class Model1(models.Model):
        othermodels = ManyToManyField('Model2')
    
    class Model2(models.model):
        ...
    

    That's it. Now syncdb will be happy. For more info: Django docs

    The only drawback is, if you use the admin, you will have access to othermodels only in Model1.

    Edit

    So, if you want to have access to the ManyToMany in both models in the Admin, currently the official solution is to use inlinemodel for the second model. I had also this same problem/need just a few days ago. And I was not really satisfied with the inlinemodel solution (heavy in DB queries if you have a lot of entries, cannot use the *filter_horizontal* widget, etc.).

    The solution I found (that's working with Django 1.2+ and syncdb) is this:

    class Model1(models.Model):
        othermodels = models.ManyToManyField('Model2', through='Model1Model2')
    
    class Model2(models.Model):
        othermodels = models.ManyToManyField('Model1', through='Model1Model2')
    
    class Model1Model2(models.Model):
        model1 = models.ForeignKey(Model1)
        model2 = models.ForeignKey(Model2)
    
        class Meta:
            db_table = 'app_model1_model2'
            auto_created = Model1
    

    See ticket 897 for more info.

    Unfortunately, if you're using South you will have to remove the creation of the app_model1_model2 table in every migration file created automatically.

    0 讨论(0)
提交回复
热议问题