【问题标题】:Django ignore extra arguments on constructing modelDjango 忽略构建模型的额外参数
【发布时间】:2020-03-13 23:52:03
【问题描述】:

我有一个小型 Django 项目,我从外部源获取一些信息并使用它来构建模型实例。问题是源返回了很多(我的意思是很多!)我不需要的额外信息。

目前,我必须找出其中有哪些额外记录,然后手动检查并删除每条记录。但这不是很好,因为

  1. 这使得代码非常难看,并且
  2. 如果外部源发生变化,例如它添加了一个新字段,我的代码在构建模型时会抛出错误

    myModel = MyModel(**argDict)
    

有没有办法可以将过度完整的argDict 传递给我的模型,让它抑制有关额外信息的任何错误并丢弃它?我在想我可以使用pre_init 信号,但我仍然不知道如何阻止该错误被返回。

【问题讨论】:

    标签: python django django-models constructor


    【解决方案1】:

    meta API 通过get_fields() 提供所有可用字段实例的列表。您可以编写一个实用函数来过滤 init 的 kwargs:

    def init_kwargs(model, arg_dict):
        model_fields = [f.name for f in model._meta.get_fields()]
        return {k: v for k, v in arg_dict.iteritems() if k in model_fields}
    

    那么,

    kwars = init_kwargs(myModel, arg_dict)
    myModel = MyModel(**kwargs)
    

    适用于所有型号。

    【讨论】:

    • 使用元 API 是个好主意,但我会避免覆盖模型的 __init__ 方法。有几个选择是定义一个函数,例如create_model_from_external_data(**argDict) 或管理器方法,例如MyModel.objects.create_from_external_data(**argDict).
    • 同意,有多种方法可以实现。但是,只要您调用原始的__init__,为什么要避免覆盖__init__
    • Django docs 鼓励替代覆盖__init__。在这种情况下,我认为最好调用一个明确表明您正在丢弃数据的方法,而不是更改应用程序中各处的行为,这可能会隐藏一些细微的错误。
    • 我假设这里的 init_kwargs 是一个类方法?还是需要传递一个实例?
    • @Alasdair 我必须同意。客户可能会依赖为多余的 kwargs 引发错误,而覆盖 __init__ 会改变这种行为。编辑了我的答案,谢谢澄清!
    【解决方案2】:

    创建一个没有任何参数的空白实例。然后使用setattr 设置值。对于模型上不存在的字段,您应该不会收到任何错误。

    my_model = MyModel()
    for key, value in argDict.items():
        setattr(my_model, key, value)
    my_model.save()
    

    您可以将上述代码包装在一个函数中以实现可重用性,也许是自定义管理器上的一个方法。

    【讨论】:

      【解决方案3】:

      我需要更改接受的答案才能使其正常工作(Python 3.6.3):

      def init_kwargs(model, arg_dict):
      return {
          k: v for k, v in arg_dict.items() if k in [
             f.name for f in model._meta.get_fields()
          ]
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多