Django Admin:根据相关的多个模型的级联字符字段进行自定义排序 [英] Django Admin: Custom ordering according to concatenated charfields of a related manytomany model

查看:362
本文介绍了Django Admin:根据相关的多个模型的级联字符字段进行自定义排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的简化模型:

class MasterFood(models.Model):
    class Meta:
        verbose_name_plural = 'Master Foods'

    FOOD_TYPE_CHOICES = (
        ('F', 'Fats'),
        ('C', 'Carbohydrates'),
        ('P', 'Proteins'),
        ('O', 'Others'),
    )

    food_name = models.CharField(max_length=255)
    food_type = models.CharField(max_length=20,choices=FOOD_TYPE_CHOICES)
    def __str__(self):
        return self.food_name

class MasterMeal(models.Model):
    class Meta:
        verbose_name_plural = 'Master Meal Plan Meals'

    proteins = models.ManyToManyField(to="MasterFood", limit_choices_to={'food_type': 'P'},blank=True,related_name='food_proteins')
    carbohydrates = models.ManyToManyField(to="MasterFood", limit_choices_to={'food_type': 'C'}, blank=True, related_name='food_carbohydrates')
    fats = models.ManyToManyField(to="MasterFood",  limit_choices_to={'food_type': 'F'}, blank=True, related_name='food_fats')

    def all_foods(self):
       return list(self.proteins.all())+list(self.carbohydrates.all())+list(self.fats.all())

    def __str__(self):
        return ', '.join(map(lambda x: x.food_name, self.all_foods()))+f' ({len(self.all_foods())})'

和我在admin.py中的modelAdmin对象:

and my modelAdmin object in admin.py:

class MealAdmin(admin.ModelAdmin):
    model = MasterMeal
    save_as = True

    ordering = ('proteins__food_name','carbohydrates__food_name','fats__food_name',)

我想要的是Django管理页面中的MasterMeals,是让每个对象都以命名我的MasterMeal模型中提供了__str __ 方法,但顺序与默认顺序不同。
具体来说,我希望对象根据 __ str __ 方法定义按字母顺序排序,并且如果可能的话,我也不想修改我的MasterMeal模型中添加另一个字段来实现此目的。我在MealAdmin对象中尝试了几种方法,例如 ordering =('proteins__food_name','carbohydrates__food_name','fats__food_name')顺序=(蛋白质,碳水化合物,脂肪,)。我还尝试使用带注释功能覆盖ModelAdmin的queryset:

What I would like is in the Django admin page for MasterMeals is to have each object named after the __str__ method given in my MasterMeal model, but in a different ordering than the default. Specifically, I would like the objects to be sorted in alphabetical order according to the __str__ method definition, and if possible, I don't want to modify my MasterMeal model to add another field to achieve this. I have tried several things such as the ordering = ('proteins__food_name','carbohydrates__food_name','fats__food_name',) in my MealAdmin object as well as ordering = ('proteins','carbohydrates','fats',). I have also tried overwriting the queryset of the ModelAdmin with an annotate function like:

class MealAdmin(admin.ModelAdmin):
    model = MasterMeal
    save_as = True

def get_queryset(self,request):
        qs = super(MealAdmin,self).get_queryset(request) 

        return qs.distinct() \
        .annotate(protein_order=F('proteins__food_name'),carb_order = F('carbohydrates__food_name'),fat_order = F('fats__food_name')) \
        .order_by('protein_order', 'carb_order','fat_order')

但是我显然不是按照获得我想要的顺序所需的方式来注释对象。所有这三个示例都产生完全相同的顺序:

but I am clearly not annotating the objects in the way that they need to be in order to get the ordering that I am after. All 3 of these examples produce this exact same ordering:

排序不正确

您可以看到名称完全相同的对象之间还有其他几个条目。对象不是根据 __ str __ 方法按字母顺序排序的,而是(我相信吗?)是根据为每个组生成的键排序的(我相信吗?)蛋白质/碳水化合物/脂肪。

You can see an object with the exact same name has several other entries in between it. The objects are not sorted in alphabetical order according to the __str__ method, and are instead, (I believe?) being sorted on keys that have been generated for each of the groups of proteins/carbs/fats.

我确实读过此处
'为确保确定性的结果排序,更改列表将pk添加到排序(如果有)无法找到提供总排序的单个或唯一的字段集。但是我不知道如何修改代码以使其按我想要的顺序对这些对象进行排序。

I did read here in the Django docs in regard to ModelAdmin.ordering that: 'To ensure a deterministic ordering of results, the changelist adds pk to the ordering if it can’t find a single or unique together set of fields that provide total ordering.' But I do not know how to modify my code to get it to order these objects in the order I DO want.

我相信我可以在我的MasterMeal模型中添加一个不可编辑的字段,并覆盖模型的save()方法,如下所示:此处,以便使用我想要的字符串,我相信我可以随后订购,但是我不想更改模型并不必更新所有服务器上的所有对象来添加此字段。

I believe I could add a non-editable field to my MasterMeal model, and overwrite the save() method for the model as shown here, in order to auto-populate the field with my desired string, which I believe I could then order on, but I don't want to have to change my model and have to update all of my objects on all of my servers to add this field.

有人可以告诉我是否有一种方法可以实现此订购吗?

Can anyone tell me if there is a way I can achieve this ordering?

我是Django的新手,对Python的经验有限,所以非常感谢您提供的任何帮助。

I am very new to Django, and have limited experience with Python, so thank you very much for any help you can provide.

推荐答案

我发现无法执行所需的操作,因为我没有要订购的字段,而且我无法使用查询表达式做我需要的。我选择在模型中创建一个新的CharField,即 name ,该模型在离开时会自动使用 __ str __ 方法进行填充空白。请参阅解决方案此处

I found that it wasn't possible to do what I wanted since I did not have a field to order on and I was not able to use a query expression to do what I needed. I chose instead to create a new CharField in my model, name, which I auto populated with my __str__ method when left blank. See the solution here.

这篇关于Django Admin:根据相关的多个模型的级联字符字段进行自定义排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆