| | 30 | class Author(models.Model): |
| | 31 | name = models.CharField(max_length=30) |
| | 32 | |
| | 33 | # Missing unique_together in the intermediate model: |
| | 34 | |
| | 35 | class Book(models.Model): |
| | 36 | name = models.CharField(max_length=20) |
| | 37 | authors = models.ManyToManyField(Author, through='AuthorsBooks') |
| | 38 | |
| | 39 | class AuthorsBooks(models.Model): |
| | 40 | author = models.ForeignKey(Author) |
| | 41 | book = models.ForeignKey(Book) |
| | 42 | |
| | 43 | # Extra data in the intermediate model: |
| | 44 | |
| | 45 | class Ballad(models.Model): |
| | 46 | name = models.CharField(max_length=20) |
| | 47 | authors = models.ManyToManyField(Author, through='AuthorsBallads') |
| | 48 | |
| | 49 | class AuthorsBallads(models.Model): |
| | 50 | author = models.ForeignKey(Author) |
| | 51 | ballad = models.ForeignKey(Ballad) |
| | 52 | extra_data = models.IntegerField() |
| | 53 | |
| | 54 | class Meta: |
| | 55 | unique_together = ('author', 'ballad') |
| | 56 | |
| | 57 | # Intermediate model PK field isn't an independent one: |
| | 58 | |
| | 59 | class Act(models.Model): |
| | 60 | name = models.CharField(max_length=20) |
| | 61 | authors = models.ManyToManyField(Author, through='AuthorsActs') |
| | 62 | |
| | 63 | class AuthorsActs(models.Model): |
| | 64 | author = models.ForeignKey(Author, primary_key=True) |
| | 65 | act = models.ForeignKey(Act) |
| | 66 | |
| | 67 | # This through-using m2m complies with all the requirements needed to be |
| | 68 | # listed in ModelAdmin.fields, should validate succesfully: |
| | 69 | |
| | 70 | class Paper(models.Model): |
| | 71 | name = models.CharField(max_length=20) |
| | 72 | authors = models.ManyToManyField(Author, through='AuthorsPapers') |
| | 73 | |
| | 74 | |
| | 75 | class AuthorsPapers(models.Model): |
| | 76 | author = models.ForeignKey(Author) |
| | 77 | paper = models.ForeignKey(Paper) |
| | 78 | |
| | 79 | class Meta: |
| | 80 | unique_together = ('author', 'paper') |
| | 81 | |
| | 82 | # Intermediate model has a manually set PK, should work too: |
| | 83 | |
| | 84 | class Post(models.Model): |
| | 85 | name = models.CharField(max_length=20) |
| | 86 | authors = models.ManyToManyField(Author, through='AuthorsPosts') |
| | 87 | |
| | 88 | |
| | 89 | class AuthorsPosts(models.Model): |
| | 90 | mypk = models.AutoField(primary_key=True) |
| | 91 | author = models.ForeignKey(Author) |
| | 92 | post = models.ForeignKey(Post) |
| | 93 | |
| | 94 | class Meta: |
| | 95 | unique_together = ('author', 'post') |
| | 96 | |
| | 97 | # Recursive m2m with through, should work too: |
| | 98 | |
| | 99 | class Writer(models.Model): |
| | 100 | name = models.CharField(max_length=30) |
| | 101 | similar = models.ManyToManyField('self', through='Influence', symmetrical=False) |
| | 102 | |
| | 103 | |
| | 104 | class Influence(models.Model): |
| | 105 | inspirator = models.ForeignKey(Writer, related_name='influenced_by') |
| | 106 | inspired = models.ForeignKey(Writer, related_name='influenced') |
| | 176 | # Regression test for #12203 - Fail more gracefully when a M2M field that |
| | 177 | # specifies the 'through' option is included in the 'fields' ModelAdmin option. |
| | 178 | |
| | 179 | >>> class BookAdmin(admin.ModelAdmin): |
| | 180 | ... fields = ['authors'] |
| | 181 | |
| | 182 | >>> validate(BookAdmin, Book) |
| | 183 | Traceback (most recent call last): |
| | 184 | ... |
| | 185 | ImproperlyConfigured: BookAdmin.fields: Included 'authors' ManyToManyField field uses 'through' option but specifies a non suitable intermediate model (AuthorsBooks). |
| | 186 | |
| | 187 | >>> class BalladAdmin(admin.ModelAdmin): |
| | 188 | ... fields = ['authors'] |
| | 189 | |
| | 190 | >>> validate(BalladAdmin, Ballad) |
| | 191 | Traceback (most recent call last): |
| | 192 | ... |
| | 193 | ImproperlyConfigured: BalladAdmin.fields: Included 'authors' ManyToManyField field uses 'through' option but specifies a non suitable intermediate model (AuthorsBallads). |
| | 194 | |
| | 195 | >>> class ActAdmin(admin.ModelAdmin): |
| | 196 | ... fields = ['authors'] |
| | 197 | |
| | 198 | >>> validate(ActAdmin, Act) |
| | 199 | Traceback (most recent call last): |
| | 200 | ... |
| | 201 | ImproperlyConfigured: ActAdmin.fields: Included 'authors' ManyToManyField field uses 'through' option but specifies a non suitable intermediate model (AuthorsActs). |
| | 202 | |
| | 203 | >>> class PaperAdmin(admin.ModelAdmin): |
| | 204 | ... fields = ['authors'] |
| | 205 | |
| | 206 | >>> validate(PaperAdmin, Paper) |
| | 207 | |
| | 208 | >>> class PostAdmin(admin.ModelAdmin): |
| | 209 | ... fields = ['authors'] |
| | 210 | |
| | 211 | >>> validate(PostAdmin, Post) |
| | 212 | |