Django:帮助覆盖模型的save()方法,以基于对象创建函数自动填充CharField [英] Django: Help overwriting a model's save() method to auto populate a CharField based on a function on object creation

查看:74
本文介绍了Django:帮助覆盖模型的save()方法,以基于对象创建函数自动填充CharField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个模型(餐),其中包含多个字段(蛋白质,碳水化合物和脂肪),最近我在其中添加了名称 CharField。我想允许用户输入一餐的名称,但是如果他们不输入名称,我希望根据我在模型中具有的功能定义自动填充该名称,该函数定义只是将食物的名称串联在一起。一弦。我试图遵循此



当前,我仅通过django admin ui创建便餐对象。这是我的MealAdmin在admin.py中的代码:

  class MealAdmin(admin.ModelAdmin):
model =膳食
save_as =真
#搜索栏-按食品名称搜索
search_fields = ['名称','蛋白质__食品名称','碳水化合物__食品名称','脂肪__食品名称',]
字段集= (
(无,{
'fields':('name','proteins','carbohydrates','fats',),
'description':注意:不要为您的餐点选择名称,餐点将根据餐点中的所有食物来命名。例如:鸡胸肉,米饭(白色)(煮熟的),鳄梨
}),

和图片供参考:





因此,如果有人有任何想法如何使save函数自动在cr上填充名称字段基于我的 __ str __ 函数-或其他解决方法,将不胜感激!

解决方案

如果您希望通过 admin 界面创建新实例时会发生某些事情,则该方法不同于仅覆盖模型 save 方法:您必须在 admin 声明中覆盖 save_model 方法。



您可以尝试以下操作:

 #admin.py 
class MealAdmin(admin.ModelAdmin):

def save_model(self,request,obj,form,change):
obj.save()
form.save_m2m()
#您的自定义内容会在这里
如果不是obj.name:
obj.name = obj .__ str __()
obj.save( )


I have a model (Meal) with several many to many fields (proteins, carbohydrates and fats), which I recently added a 'name' CharField to. I wanted to allow the user to enter a name for a meal, but if they do not enter a name, I want the name to be populated automatically based on the function definitions I have in the model which just concatenate the names of the foods in one string. I was trying to follow this guide.

Now, if the Meal already exists, what I have actually works fine. However, if it does not exist, the food_name for each item appears not to have saved yet because they are empty. I put the super(Meal,self).save() statement before my if not self.name: statement in the hopes that this would save the object to the database so that the food_names could then be retrieved, but it does not work and instead when I do save the name is saved as '(0)'. What I am looking for the name to populate via the __str__ function as 'Pork Tenderloin, Spinach (steamed/boiled), Potato (Red, medium) (3)', for example.

Also, if I don't call super(Meal,self).save() before the if statement, I actually get a 'maximum recursion depth exceeded' error.

Can anyone tell me if there is a way to auto populate this name field based on my function definition on object creation as I've described?

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

Here is my model:

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

    name = models.CharField(max_length=255,blank=True,null=True)
    proteins = models.ManyToManyField(to="Food", limit_choices_to={'food_type': 'P'},blank=True,related_name='food_proteins')
    carbohydrates = models.ManyToManyField(to="Food", limit_choices_to={'food_type': 'C'}, blank=True, related_name='food_carbohydrates')
    fats = models.ManyToManyField(to="Food",  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())})'

    def save(self):
        super(Meal,self).save()
        if not self.name:
            self.name = self.__str__()
            self.save()

Edit:

The main reason I am trying to do this is because I need to be able to sort on the string returned by the __str__ method in my Meal model, but after posting another question on stack overflow here I found out that I believe this is not possible. It seems you can only sort on fields in your model, and so I chose instead to add a name field (where I additionally decided that I could allow the user to name the meal something if they wanted to instead of letting it be auto populated). Currently when there are many meals it is impossible to find any single one because the ordering is based on pk's which appears totally random in terms of the names of the items and makes it virtually unusable. Here is a picture for reference:

Currently, I create meal objects through the django admin ui only. Here is the code for my MealAdmin in admin.py:

class MealAdmin(admin.ModelAdmin):
    model = Meal
    save_as = True
    #search bar - search by food name
    search_fields = ['name','proteins__food_name','carbohydrates__food_name','fats__food_name',]
    fieldsets = (
        (None, {
            'fields': ('name', 'proteins', 'carbohydrates', 'fats',),
            'description': "Note: If you do not choose a name for your meal the meal will be named according to all of the foods it contains. Ex: 'Chicken Breast,Rice (white) (cooked),Avocado'"
        }),
    )

and a picture for reference:

So, if anyone has any idea how to cause the save function to auto-populate the name field on creation based on my __str__ function - or any other work around, it would be greatly appreciated!

解决方案

If you want something to happen when creating a new instance through admin interface, the way to do is different than just overriding your model save method: you have to override the save_model method in your admin declaration.

You could try something like below:

# admin.py
class MealAdmin(admin.ModelAdmin):

    def save_model(self, request, obj, form, change):        
        obj.save()
        form.save_m2m()
        # your custom stuff goes here
        if not obj.name:
            obj.name = obj.__str__()
            obj.save()

这篇关于Django:帮助覆盖模型的save()方法,以基于对象创建函数自动填充CharField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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