Home > Software design >  Mimic update_or_create with json fields and disregard elements not in model
Mimic update_or_create with json fields and disregard elements not in model

Time:06-24

I have this model:

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)

and this function:

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}
    )

and call it like this:

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

this basically does:

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

So far it works properly. But it throws an error if there are fields in the keys or elements in the json not in the model.

for example:

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

which does:

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

or:

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

which does:

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

which is wrong since the field isn't present in the model.

Is there a way to disregard this field?

CodePudding user response:

for every key in the json_values parameter that you're passing to the function, check first if the key exists in the model's attribute list before you assign the value to the model. like so:

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}
)

Get model's fields in Django

or u can also check the keys first before you pass it to the function

  • Related