Django多次查找** kwargs

时间:2015-12-04 19:30:35

标签: python django

我在django中有以下功能,只需基于单个查找参数(unique_id)查找就可以正常工作。但是,我尝试使用多个查找参数(例如,具有unique_together约束的表,需要两个字段才能检索唯一结果)。

以前的工作功能是:

def create_or_update_if_diff(unique_id, defaults, model):
    """Helper function which is similar to update_or_create(), but will compare defaults to database entry
     and only update when there is any difference"""
    try:
        instance = model.objects.get(unique_id=unique_id)
    except model.DoesNotExist:
        instance = model.objects.create(unique_id=unique_id, **defaults)
        sys.stdout.write('New {} created: {}\n'.format(instance.__class__.__name__, instance.unique_id))
        return instance
    else:
        for key, value in defaults.items():
            attr = getattr(instance, key)
            if attr != value:
                # If any change detected update all for efficiency
                model.objects.filter(unique_id=unique_id).update(**defaults)
                instance.refresh_from_db()
                sys.stdout.write('{}: {} updated \n'.format(instance.__class__.__name__, instance.unique_id))
                return instance
        return instance

用例如

prices = create_or_update_if_diff(unique_id=till_detail['Id'], defaults=defaults,
                                             model=Price)

修改后的功能是:

def create_or_update_if_diff(model, defaults=None, **lookup):
    """Helper function which is similar to update_or_create(), but will compare defaults to database entry
     and only update when there is any difference"""
    defaults = defaults or {}
    try:
        instance = model.objects.get(**lookup)
    except model.DoesNotExist:
        instance = model.objects.create(**lookup, **defaults)
        sys.stdout.write('New {} created: {}\n'.format(instance.__class__.__name__, instance.unique_id))
        return instance
    else:
        for key, value in defaults.items():
            attr = getattr(instance, key)
            if attr != value:
                # If any change detected update all for efficiency
                model.objects.filter(**lookup).update(**defaults)
                instance.refresh_from_db()
                sys.stdout.write('{}: {} updated \n'.format(instance.__class__.__name__, instance.unique_id))
                return instance
        return instance

我试图用例如

lookup = {'name': default_product_string, 'supplier': supplier}
    default_product_instance = create_or_update_if_diff(lookup=lookup, defaults={'payment_method': payment_method_instance},
                                                           model=Product)

但是我得到了以下错误,大概是因为我已经非正式地构建了这个函数: django.core.exceptions.FieldError: Cannot resolve keyword 'lookup' into field.

3 个答案:

答案 0 :(得分:1)

发送kwargs时出错了,这就是它的工作方式......

让我们创建一个样本lookup dict ..

>>> lookup = {'a': 1, 'b': 2}

模拟create_or_update_if_diff方法......

>>> def create_or_update_if_diff(model, defaults=None, **lookup):
...     print lookup

如果您在调用方法时分配lookup=lookup ....这意味着您正在创建一个名为key word argument的{​​{1}},理想情况下您只发送一个关键字参数

lookup
  
    
      

由于您的模型没有>>> create_or_update_if_diff('model', lookup=lookup) {'lookup': {'a': 1, 'b': 2}} 字段,因此您将获得lookup例外。

    
  

如果您传递FieldError dict,如下所示...您正在向方法发送两个关键字参数lookup ..

a and b

所以,这里的逻辑是>>> create_or_update_if_diff('model', **lookup) {'a': 1, 'b': 2} dict lookup有两个键{'a':1, 'b':2}将被视为如下所示。

a and b

希望这可以帮助您了解>>> create_or_update_if_diff('model', a=1, b=2) {'a': 1, 'b': 2} 的工作原理......

答案 1 :(得分:0)

如果您将lookup=lookup作为参数,则会在函数中获得{'lookup': {<your original dict>}}。我认为你应该在你的函数中create_or_update_if_diff

lookup_params = lookup['lookup']
instance = model.objects.get(lookup_params)

答案 2 :(得分:0)

您没有正确传递lookup,以下是它的假设:

lookup = {'name': default_product_string, 'supplier': supplier}
defaults = {'payment_method': payment_method_instance}
create_or_update_if_diff(defaults=defaults, model=Product, **lookup)