Fixed: #12203 ManyToManyField with explicit through model can't be used ...#2843
Fixed: #12203 ManyToManyField with explicit through model can't be used ...#2843vin-ai wants to merge 10 commits intodjango:masterfrom vin-ai:master
Conversation
…ed as an admin field
Fixed: #12203 ManyToManyField with explicit through model can't be used as an admin field
|
@Vinaykrsharma |
|
Added test
|
tests/admin_checks/models.py
Outdated
There was a problem hiding this comment.
Please use the @python_2_unicode_compatible technique that the other models use, although I don't think this change is needed for the tests.
|
Hi, you may be interested in our patch review checklist. Let me know if you have any questions as to how to update the patch and thanks for your efforts. |
|
Also checked with |
|
The widget display now, but can you actually use it? When I tried with the models in this example, I get an error when I try to save a By the way, this is what I meant about putting the models inline to the test: http://dpaste.com/1ZATEC8 |
|
I don't changed that because I thought |
…ts.py. Both model classes are testing purposes only.
|
And do you plan to respond to my question about whether the widget actually works? Not much point if removing the check if not. |
|
Now when trying to add a Book via |
|
Yes, because the M2M through model class don't know what value to save for that. # ...
priority = models.IntegerField(default=0, blank=True)
#...or any best solution/patch do you have! |
|
Also we should create a new method or property under Because there are tons of checks for Property to be add in For e.g. let say: try command line search: |
|
re: "Yes, because the M2M through model class don't know what value to save for that." That's the point of the validation -- in general, we can't remove the check in this case. I believe the correct fix is described in this comment: "The fancy solution would be to loosen this condition slightly and allow an m2m field to be in the fields list (and therefore allow an m2m widget be used) iff the through model is just 2 foreign keys with a unique_together pairing (i.e., if the through model is exactly the same as the m2m model that is be automatically generated for the non-explicit through case)." |
|
@timgraham it's already done. I think nothing to do anything more. How? M2M Model having only two Example: (try by creating a new app, put both separated code below to # models.py
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
@python_2_unicode_compatible
class Book(models.Model):
title = models.CharField(max_length=120)
cover_story = models.TextField(blank=True, null=True)
authors = models.ManyToManyField(Author, through='AuthorsBooks', through_fields=('book', 'author'))
def __str__(self):
return self.title
@python_2_unicode_compatible
class AuthorsBooks(models.Model):
author = models.ForeignKey(Author)
book = models.ForeignKey(Book)
priority = models.IntegerField()
class Meta:
verbose_name = 'Authors of Book'
verbose_name_plural = 'Authors of Book'
def __str__(self):
return '%s by %s [%d]' % (self.book.title, self.author.name, self.priority)
# admin.py
from django.contrib import admin
from .models import Author, Book, AuthorsBooks
class AdminAuthorsBooksInline(admin.TabularInline):
model = AuthorsBooks
fields = ['book', 'priority']
class AdminAuthorsBooksInline2(admin.TabularInline):
model = AuthorsBooks
fields = ['author', 'priority']
extra = 1
class Meta:
proxy = True
@admin.register(Author)
class AdminAuthor(admin.ModelAdmin):
list_display = ['name']
fields = ['name']
inlines = [AdminAuthorsBooksInline]
# Both different example here
# try by changing True to False for below decision maker
if True:
@admin.register(Book)
class AdminBookInline(admin.ModelAdmin):
"""Book Admin with Inline example"""
list_display = ['title', 'cover_story']
fields = ['title', 'cover_story']
inlines = [AdminAuthorsBooksInline2]
else:
@admin.register(Book)
class AdminBookSelectMultiple(admin.ModelAdmin):
"""Book Admin with SelectMultiple widget example"""
list_display = ['title', 'cover_story']
fields = ['title', 'cover_story', 'authors'] |
|
I'm not sure what you're saying. In your example code, If the |
|
You should apply my commit in this pull request first. then try with that framework. In short, download my patch which is in this pull request! |
|
Yes, I did. Before: Validation error with After: No validation error but Expected behavior: Validation error still occurs because |
|
I'm bit confused why you're getting those type of error. |
|
Steps to reproduce using your branch using the models/admins from your comment above (with AdminBookSelectMultiple): Add a book: /admin/<app_label>/book/add/ IntegrityError at /admin/test12203/book/add/ |
|
Ahh, missed one thing to mention in above example. So, sorry. Just add default value to # models.py
class AuthorsBooks(models.Model):
author = models.ForeignKey(Author)
book = models.ForeignKey(Book)
# This is extra field, if using SelectMultiple widget set a default value
# to prevent IntegrityError, also allow blank.
priority = models.IntegerField(default=0, blank=True) |
|
As I tried to say above, the purpose of the validation is that, in general, when there are extra fields on the M2M model, there's no way to set them in the UI. We can't require users to put defaults on all the other fields just so this works. Once again, I'll restate the expected solution: "The fancy solution would be to loosen this condition slightly and allow an m2m field to be in the fields list (and therefore allow an m2m widget be used) if and only if the through model is just 2 foreign keys with a unique_together pairing (i.e., if the through model is exactly the same as the m2m model that is be automatically generated for the non-explicit through case)." |
|
Please send a new PR if you can fix it, thanks. |
...as an admin field
If user has defined through fields then return with no error