def upsert(manager, defaults=None, updates=None, **kwargs):
    """
    Performs an update on an object or an insert if the object does not exist.

    :type defaults: dict
    :param defaults: These values are set when the object is created, but are irrelevant
            when the object already exists. This field should only be used when values only need to
            be set during creation.

    :type updates: dict
    :param updates: These values are updated when the object is updated. They also override any
            values provided in the defaults when inserting the object.

    :param kwargs: These values provide the arguments used when checking for the existence of
            the object. They are used in a similar manner to Django's get_or_create function.

    :returns: A tuple of the upserted object and a Boolean that is True if it was created (False otherwise)

    Examples:

    .. code-block:: python

        # Upsert a test model with an int value of 1. Use default values that will be given to it when created
        model_obj, created = upsert(TestModel.objects, int_field=1, defaults={'float_field': 2.0})
        print(created)
        True
        print(model_obj.int_field, model_obj.float_field)
        1, 2.0

        # Do an upsert on that same model with different default fields. Since it already exists, the defaults
        # are not used
        model_obj, created = upsert(TestModel.objects, int_field=1, defaults={'float_field': 3.0})
        print(created)
        False
        print(model_obj.int_field, model_obj.float_field)
        1, 2.0

        # In order to update the float field in an existing object, use the updates dictionary
        model_obj, created = upsert(TestModel.objects, int_field=1, updates={'float_field': 3.0})
        print(created)
        False
        print(model_obj.int_field, model_obj.float_field)
        1, 3.0

        # You can use updates on a newly created object that will also be used as initial values.
        model_obj, created = upsert(TestModel.objects, int_field=2, updates={'float_field': 4.0})
        print(created)
        True
        print(model_obj.int_field, model_obj.float_field)
        2, 4.0

    """
    defaults = defaults or {}
    # Override any defaults with updates
    defaults.update(updates or {})

    # Do a get or create
    obj, created = manager.get_or_create(defaults=defaults, **kwargs)

    # Update any necessary fields
    if updates is not None and not created and any(getattr(obj, k) != updates[k] for k in updates):
        for k, v in updates.items():
            setattr(obj, k, v)
        obj.save(update_fields=updates)

    return obj, created
Performs an update on an object or an insert if the object does not exist.

    :type defaults: dict
    :param defaults: These values are set when the object is created, but are irrelevant
            when the object already exists. This field should only be used when values only need to
            be set during creation.

    :type updates: dict
    :param updates: These values are updated when the object is updated. They also override any
            values provided in the defaults when inserting the object.

    :param kwargs: These values provide the arguments used when checking for the existence of
            the object. They are used in a similar manner to Django's get_or_create function.

    :returns: A tuple of the upserted object and a Boolean that is True if it was created (False otherwise)

    Examples:

    .. code-block:: python

        # Upsert a test model with an int value of 1. Use default values that will be given to it when created
        model_obj, created = upsert(TestModel.objects, int_field=1, defaults={'float_field': 2.0})
        print(created)
        True
        print(model_obj.int_field, model_obj.float_field)
        1, 2.0

        # Do an upsert on that same model with different default fields. Since it already exists, the defaults
        # are not used
        model_obj, created = upsert(TestModel.objects, int_field=1, defaults={'float_field': 3.0})
        print(created)
        False
        print(model_obj.int_field, model_obj.float_field)
        1, 2.0

        # In order to update the float field in an existing object, use the updates dictionary
        model_obj, created = upsert(TestModel.objects, int_field=1, updates={'float_field': 3.0})
        print(created)
        False
        print(model_obj.int_field, model_obj.float_field)
        1, 3.0

        # You can use updates on a newly created object that will also be used as initial values.
        model_obj, created = upsert(TestModel.objects, int_field=2, updates={'float_field': 4.0})
        print(created)
        True
        print(model_obj.int_field, model_obj.float_field)
        2, 4.0