I believe what you want is a filter_horizontal widget used in the Admin template. This should help: Django Admin ManyToManyField
I believe what you want is a filter_horizontal widget used in the Admin template. This should help: Django Admin ManyToManyField
Currently I am able to display many-to-many fields in admin panel with the following configuration:
models.py
class Abc(models.Model):
course = models.ManyToManyField(Course, blank=True)
admin.py
class AbcsAdmin(admin.ModelAdmin):
"""
Admin panel management for Alumni
"""
list_display = ["id","get_course"]
def get_course(self,obj):
return [course.name for course in obj.course.all()]
Django Admin Form for Many to many relationship - Stack Overflow
Django Admin ManyToManyField - Stack Overflow
A Better Django Admin ManyToMany Field Widget
Read fields from ManyToMany field via InlineModel
Videos
I know that this is an older thread, but this was the first result that came up on google and I thought a better answer was necessary.
Via this django bug report I found the best way to have your ManyToManyField show up on both models:
class Test1(models.Model):
tests2 = models.ManyToManyField('Test2', blank=True)
class Test2(models.Model):
tests1 = models.ManyToManyField(Test1, through=Test1.tests2.through, blank=True)
I have tested it myself and was very pleased with the results.
The only built-in way is via an InlineModelAdmin, but you can use a custom ModelForm with your User ModelAdmin to create field for this purpose. See the code below for simplified setup (assumes users = ManyToManyField(related_name='domains')).
### yourapp/admin.py ###
from django import forms
from django.contrib import admin
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.contrib.admin.widgets import FilteredSelectMultiple
from .models import Domain
class DomainAdmin(admin.ModelAdmin):
filter_horizonal = ('users',)
class UserAdminForm(forms.ModelForm):
domains = forms.ModelMultipleChoiceField(
queryset=Domain.objects.all(),
required=False,
widget=FilteredSelectMultiple(
verbose_name=_('Domains'),
is_stacked=False
)
)
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserAdminForm, self).__init__(*args, **kwargs)
if self.instance:
self.fields['domains'].initial = self.instance.domains.all()
def save(self, commit=True):
user = super(UserAdminForm, self).save(commit=False)
user.domains = self.cleaned_data['domains']
if commit:
user.save()
user.save_m2m()
return user
class UserAdmin(admin.ModelAdmin):
form = UserAdminForm
admin.site.register(Domain, DomainAdmin)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Try using the filter_horizontal attribute on your admin class, for example:
class SomeModelAdmin(admin.ModelAdmin):
filter_horizontal = ('users',)
As mentioned in the documentation, "adding a ManyToManyField to this list will instead use a nifty unobtrusive JavaScript "filter" interface that allows searching within the options". filter_vertical does the same thing with a slightly different layout.
you could try using a raw id in the admin. and the django docs: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.raw_id_fields
if you are looking for something with auto-complete you might want to look at this as a starting point http://code.djangoproject.com/wiki/AutoCompleteSolutions
and finally a very simplistic inline Example:
models.py
class SomeModel(models.Model):
users = models.ManyToMany(User)
admin.py:
class SomeModelAdmin(admin.ModelAdmin):
raw_id_fields = ("users",)
The default widget for Many-to-many field in admin or widgets with filter_vertical or filter_horizontal property allows you to add new item. There is a green "+" sign near the field to open a popup window and add new Director instance.
But if you need the inline style admin you should reference to the through-model. If you don't specify the custom model Django creates a simple model with 2 foreign keys to Director and Film.
So you can try to create inline like
class DirectorInline(admin.TabularInline):
model = Film.director.through
extra = 3
This will not raise an exception and will generate an inline form, but you will have to select directors from drop-down list. I think you can overwrite this by using custom form.
The simplest way to add a "+" button next to a ManyToManyField is to make sure that both objects are registered in your admin.py file. Otherwise Django won't create a form for the second type of object
admin.py
admin.site.register(Film)
admin.site.register(Director)
I spent several hours yesterday trying to get the prefetch_related set up correctly, but opening up an item in the Django Admin is taking approximately 10-20 seconds, and according to the debug toolbar, running around 550 queries
I have the following relation of models:
class Card(models.Model):
id = models.UUIDField(primary_key=True)
name = models.CharField(max_length=200)
def __str__(self):
return self.name
class MagicSet(models.Model):
id = models.UUIDField(primary_key=True)
name = models.CharField(max_length=100)
printings = models.ManyToManyField(Card, through='Printing')
def __str__(self):
return self.name
class Printing(models.Model):
magic_set = models.ForeignKey(MagicSet, on_delete=models.CASCADE)
card = models.ForeignKey(Card, related_name='printings', on_delete=models.CASCADE)and my admin.py contains the following:
class PrintingInline(admin.TabularInline):
model = MagicSet.printings.through
extra = 0
@admin.register(MagicSet)
class MagicSetAdmin(admin.ModelAdmin):
inlines = [
PrintingInline,
]
def get_queryset(self, request):
queryset = super().get_queryset(request)
queryset = queryset.prefetch_related('printings')
return querysetMost of the documentation that I saw about using M2M w/ a through model and the admin seemed to imply that this should just work, can someone tell me what I've done wrong?
Update 2/18: I just wanted to drop an update in case someone came across this later. Unfortunately, I haven't found a good solution to this issue, but everything works just fine in a regular Django view. Since I just intend to use the admin during development, I created a custom view to accomplish what I needed to (which is mostly just inspecting the data), and it works just fine using a prefetch_related query. Sorry if this wasn't more helpful
