Имитация update_or_create с json-полями и игнорирование элементов, отсутствующих в модели

У меня эта модель:

class SomeModel(models.Model):
    field_1 = models.CharField(max_length=200, blank=True, null=True)
    field_2 = models.CharField(max_length=200, blank=True, null=True)

и эта функция:

def upload_object_values(model, json_values, keys=None):
    model._base_manager.update_or_create(
        **{key: json_values[key] for key in keys},
        defaults={key: value for key, value in json_values.items() if key not in keys}
    )

и назовите его следующим образом:

upload_object_values(SomeModel, { \
    'field_1': 'val', \ 
    'field_2': 'val_2'}, \
    ['field_2'])

это в основном делает:

SomeModel.objects.update_or_create(field_2='val_2')
SomeModel.field_1 = 'val'
SomeModel.save()

Пока все работает правильно. Но он выдает ошибку, если в ключах есть поля или элементы в json не в модели.

например:

upload_object_values(SomeModel, { \
    'field_1': 'val', \
    'field_2': 'val_2', \
    'field_not_in_model': 'val_3'}, \
    ['field_2', 'field_not_in_model'])

что делает:

SomeModel.objects.update_or_create(field_2='val_2', field_not_in_model='val_3')
SomeModel.field_1 = 'val'
SomeModel.save()

или:

upload_object_values(SomeModel, { \
        'field_1': 'val', \
        'field_2': 'val_2', \
        'field_not_in_model': 'val_3'}, \
        ['field_2'])

что делает:

SomeModel.objects.update_or_create(field_2='val_2)
SomeModel.field_1 = 'val'
SomeModel.field_not_in_model = 'val_3'
SomeModel.save()

что неверно, поскольку поле не присутствует в модели.

Есть ли способ игнорировать это поле?

для каждого ключа в параметре json_values, который вы передаете в функцию, сначала проверьте, существует ли ключ в списке атрибутов модели, прежде чем присвоить значение модели. например:

def upload_object_values(model, json_values, keys=None):

     new_json_values = {}
     for key in json_values.keys():
         try:
             if model._meta.get_field(key):
                 new_json_values[key] = json_values[key]
         except:
             pass

     model._base_manager.update_or_create(
         **{key: new_json_values[key] for key in keys},
         defaults={key: value for key, value in 
         new_json_values.items() if key not in keys}
)

Получение полей модели в Django

или вы также можете сначала проверить ключи, прежде чем передать их в функцию

Вернуться на верх