Created
January 31, 2018 13:25
-
-
Save efimerdlerkravitz/6177b656563e86f57f1fb81c1a18bf85 to your computer and use it in GitHub Desktop.
Edit a many-to-many relationship (ManyToManyField) on the Django Admin change list page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BookChangeList(ChangeList): | |
def __init__(self, request, model, list_display, list_display_links, | |
list_filter, date_hierarchy, search_fields, list_select_related, | |
list_per_page, list_max_show_all, list_editable, model_admin): | |
super().__init__(request, model, list_display, list_display_links, | |
list_filter, date_hierarchy, search_fields, list_select_related, | |
list_per_page, list_max_show_all, list_editable, model_admin) | |
# these need to be defined here, and not in BookAdmin | |
self.list_display = ('name', 'categories') | |
self.list_display_links = ['name'] | |
self.list_editable = ['categories'] | |
class BookForm(ModelForm): | |
# this the bit of custom CSS we want to add | |
style_text = f'columns: {int(BookCategory.objects.count()/5)}' | |
# here we only need to define the field we want to be editable | |
categories = ModelMultipleChoiceField(queryset=BookCategory.objects.all(), | |
widget=StyleableCheckboxSelectMultiple(ul_attrs={"style": style_text}), | |
required=False) | |
@admin.register(Book) | |
class BookAdmin(admin.ModelAdmin): | |
ordering = ('id',) | |
def get_changelist(self, request, **kwargs): | |
return BookChangeList | |
def get_changelist_form(self, request, **kwargs): | |
return BookForm | |
@admin.register(BookCategory) | |
class BookCategoryAdmin(admin.ModelAdmin): | |
list_display = ['id', 'name'] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# this subclass allows us to add a bit of our own CSS at the <ul> level | |
from django import forms | |
from django.forms.utils import flatatt | |
from django.utils.safestring import mark_safe | |
class StyleableCheckboxSelectMultiple(forms.CheckboxSelectMultiple): | |
def __init__(self, attrs=None, ul_attrs=None): | |
self.ul_attrs = ul_attrs | |
super().__init__(attrs) | |
def render(self, name, value, attrs=None, choices=None): | |
html = super().render(name, value, attrs, choices) | |
final_attrs = self.build_attrs(self.ul_attrs) | |
return mark_safe(html.replace('<ul', f'<ul {flatatt(final_attrs)}')) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class BookCategory(models.Model): | |
name = models.CharField(max_length=255) | |
def __str__(self): | |
return self.name | |
class Book(models.Model): | |
name = models.CharField(max_length=255) | |
categories = models.ManyToManyField('BookCategory', blank=True, null=True) | |
def __str__(self): | |
return self.name |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Based on https://gist.github.com/jdklub/9261959 with fixes for python 3 and Django 1.11