如何让django-admin-sortable与django-parler协同工作?多对多模型求助
我来帮你搞定django-admin-sortable和django-parler的协同工作问题,结合你给出的多对多关联模型,咱们一步步来解决:
第一步:修正Parler模型定义(关键前提)
首先,你的TranslatableModel用法有点小问题——Parler要求翻译字段必须通过TranslatedFields来声明,而不是直接在模型类里定义普通字段。咱们先修正模型代码:
# models.py from django.db import models from parler.models import TranslatableModel, TranslatedFields from adminsortable.models import Sortable, SortableForeignKey class Item(TranslatableModel): # 用TranslatedFields包裹需要翻译的字段 translations = TranslatedFields( name=models.CharField(max_length=100) ) def __str__(self): # Parler会自动返回当前语言的翻译值 return self.name class Person(TranslatableModel): translations = TranslatedFields( name=models.CharField(max_length=100) ) items = models.ManyToManyField( 'Item', through='PersonItem', ) def __str__(self): return self.name class PersonItem(Sortable): class Meta(Sortable.Meta): ordering = ['order'] verbose_name = "人物-物品关联" verbose_name_plural = "人物-物品关联列表" person = models.ForeignKey('Person', on_delete=models.CASCADE) item = SortableForeignKey('Item', on_delete=models.CASCADE) def __str__(self): return f"{self.person.name} → {self.item.name}"
第二步:配置Admin类,实现排序与翻译协同
接下来编写Admin代码,让两个插件的功能完美结合:
# admin.py from django.contrib import admin from parler.admin import TranslatableAdmin from adminsortable.admin import SortableAdmin, SortableTabularInline from .models import Item, Person, PersonItem # 自定义Inline,用于在Person页面直接拖拽排序关联的Item class PersonItemInline(SortableTabularInline): model = PersonItem extra = 1 fields = ('item', 'order') readonly_fields = ('order',) # 排序值由插件自动维护,无需手动输入 # Item的Admin,支持多语言编辑 @admin.register(Item) class ItemAdmin(TranslatableAdmin): list_display = ('name',) parler_tabbed = True # 启用标签页式的语言切换界面 # Person的Admin,同时支持多语言和关联Item的排序 @admin.register(Person) class PersonAdmin(TranslatableAdmin): list_display = ('name',) inlines = [PersonItemInline] parler_tabbed = True # 单独的关联表Admin,也支持排序操作 @admin.register(PersonItem) class PersonItemAdmin(SortableAdmin): list_display = ('person', 'item', 'order') list_filter = ('person', 'item') def get_queryset(self, request): # 预加载翻译数据,避免N+1查询,提升页面加载速度 qs = super().get_queryset(request) return qs.select_related('person', 'item').prefetch_related( 'person__translations', 'item__translations' )
第三步:关键配置与测试
- 确认Settings配置:确保你的
INSTALLED_APPS包含两个插件,并且配置了Parler的语言支持:
# settings.py INSTALLED_APPS = [ # ... 其他内置/第三方APP 'parler', 'adminsortable', ] # Parler多语言配置示例 PARLER_LANGUAGES = { None: ( {'code': 'en',}, {'code': 'zh-hans',}, ), 'default': { 'fallbacks': ['en'], 'hide_untranslated': False, } }
- 执行迁移:因为修改了模型结构,需要生成并执行迁移:
python manage.py makemigrations python manage.py migrate
- 测试功能:
- 登录Django Admin,进入「人物」页面,添加关联的物品,你会看到Inline区域有拖拽手柄,直接拖动就能调整排序,
order字段会自动保存。 - 切换语言标签页(比如从英文切到中文),人物和物品的名称会自动显示对应语言的翻译,排序功能不受影响。
- 登录Django Admin,进入「人物」页面,添加关联的物品,你会看到Inline区域有拖拽手柄,直接拖动就能调整排序,
注意事项
- 如果Admin页面看不到拖拽手柄,检查是否有自定义Admin模板覆盖了默认样式,确保
django-admin-sortable的静态资源被正确加载。 - 预加载翻译数据的步骤很重要,否则当关联对象很多时,页面加载会非常慢。
内容的提问来源于stack exchange,提问作者Most Wanted
相关产品推荐
相关产品推荐

