10

我有一个名为 StaffSettings 的 Django 模型,其中包含我的 Django 应用程序中用户的各种配置选项。每个用户在 StaffSettings 表中最多有一个条目。

假设一个设置是 default_year_level,我有我的用户对象的代码,例如:

def set_default_year_level(u, year_level):
    obj, _created = StaffSettings.objects.get_or_create(user=u)
    obj.default_year_level = year_level
    obj.save()

我希望函数的主体适合一行,因为它似乎是一个常见的用例,但如果我将它定义为

def set_default_year_level(u, year_level):
    StaffSettings.objects.filter(user=u).update(default_year_level=year_level)

如果有问题的用户在 StaffSettings 表中已经有一行,那么它工作正常,但如果它不存在,它将不会创建相关行。

编写此代码的惯用/最佳方式是什么?(例如,是否有某种filter_or_create功能?或者其他人是否编写装饰器/辅助功能来处理这个习语?)

4

2 回答 2

6

我看不出你的第一个函数有任何问题,我会为这个用例写同样的。

但是,如果您在模型的许多字段上需要相同的功能并且您不想重复自己,则可以将该字段作为参数传递:

def set_default_value(u, field, value):
  obj, _created = StaffSettings.objects.get_or_create(user=u)
  setattr(obj, field, value)
  obj.save()

无论如何我都会远离update()函数,因为该函数旨在一次更新多个对象,并且不会触发 save() 方法或模型上的信号(请参阅https://docs.djangoproject.com/en /dev/topics/db/queries/#updating-multiple-objects-at-once

于 2013-03-18T09:20:44.057 回答
6

从 Django 1.7 开始,您可以使用update_or_create()

def set_default_year_level(u, year_level):
    obj, _created = StaffSettings.objects.update_or_create(
        user=u,
        default_year_level=year_level
    )

或者,对于上一个答案中解释的更通用的情况:

def set_default_values(u, **kwargs):
    obj, _created = StaffSettings.objects.update_or_create(user=u, defaults=kwargs)

这也满足您的额外要求

我希望函数的主体适合一行

于 2016-10-17T10:33:18.643 回答