You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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'
        )

第三步:关键配置与测试

  1. 确认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,
    }
}
  1. 执行迁移:因为修改了模型结构,需要生成并执行迁移:
python manage.py makemigrations
python manage.py migrate
  1. 测试功能:
    • 登录Django Admin,进入「人物」页面,添加关联的物品,你会看到Inline区域有拖拽手柄,直接拖动就能调整排序,order字段会自动保存。
    • 切换语言标签页(比如从英文切到中文),人物和物品的名称会自动显示对应语言的翻译,排序功能不受影响。

注意事项

  • 如果Admin页面看不到拖拽手柄,检查是否有自定义Admin模板覆盖了默认样式,确保django-admin-sortable的静态资源被正确加载。
  • 预加载翻译数据的步骤很重要,否则当关联对象很多时,页面加载会非常慢。

内容的提问来源于stack exchange,提问作者Most Wanted

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:13:29