Created
January 31, 2018 13:24
-
-
Save efimerdlerkravitz/52855b8a0e9f35b9bf66f48fdc7dfc2d 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