<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _get_or_update_or_create_related_instance( self, ModelClass, fieldname, field_data ):
 """ Handle lookup, update, or creation of related instances based on the field data provided and the field's `writable_related_fields` settings as defined on the serializer's `Meta`. This method will: - fail immediately if the field does not have `writable_related_fields` settings defined, or if these settings are not valid `WritableRelatedFieldSettings` objects - look up an existing instance using the defined `lookup_field` if a value is provided for the lookup field: - if no lookup field value is provided, fail unless `can_create` is set on the field since we cannot find any existing instance - if no existing instance is found, fail unless `can_create` - find the matching existing instance - if there is an existing instance: - if other data is provided, fail unless `can_update` is set - update existing instance based on other data provided if `can_update is set` - return the existing instance - if there is not an existing instance and `can_create` is set: - create a new instance with provided data - return the new instance """

        writable_related_fields = getattr(
            self.Meta, 'writable_related_fields', {})

        # Get settings for writable related field
        if fieldname not in writable_related_fields:
            raise TypeError(
                "Cannot write related model field '%s' for %s on %s"
                " without corresponding 'writable_related_fields' settings"
                " in the Meta class"
                % (fieldname, ModelClass.__name__,
                   self.Meta.model.__name__)
            )
        field_settings = writable_related_fields[fieldname]
        if not isinstance(field_settings, WritableRelatedFieldSettings):
            raise TypeError(
                "Settings for related model field '%s' in"
                " '%s.Meta.writable_related_fields' must be of type"
                " 'WritableRelatedFieldSettings': %s"
                % (fieldname, ModelClass.__name__, type(field_settings))
            )

        # Get settings for lookup field; may be a string or a strings list
        lookup_fields = field_settings.lookup_field
        if not isinstance(lookup_fields, (list, tuple)):
            lookup_fields = [lookup_fields]

        # We use the first of potentially multiple lookup field values for
        # which we have been given field data.
        lookup_value = None
        for lookup_field in lookup_fields:
            if lookup_field in field_data:
                lookup_value = field_data.pop(lookup_field)
                break

        # Fail if we have no lookup value and we cannot create an instance
        if lookup_value is None and not field_settings.can_create:
            raise TypeError(
                "Cannot look up related model field '%s' for %s on %s"
                " using the lookup field(s) %r because no value"
                " was provided for the lookup field(s) in %s"
                % (fieldname, ModelClass.__name__,
                    self.Meta.model.__name__, lookup_fields, field_data)
            )

        related_instance = None

        # Fetch existing instance using lookup field
        try:
            related_instance = ModelClass.objects.get(
                **{lookup_field: lookup_value})

            # Update existing related instance with values provided in
            # parent's create/update operation, if such updates are
            # permitted. If updates are not permitted, raise an exception
            # only if submitted values differ from existing ones.
            is_updated = False
            for name, value in field_data.items():
                original_value = getattr(related_instance, name)
                if value != original_value:
                    if not field_settings.can_update:
                        raise TypeError(
                            u"Cannot update instance for related model"
                            u" field '%s' for %s on %s because"
                            u" 'can_update' is not set for this field in"
                            u" 'writable_related_fields' but submitted"
                            u" value `%s=%s` does not match existing"
                            u" instance value `%s`"
                            % (fieldname, ModelClass.__name__,
                               self.Meta.model.__name__, name, value,
                               original_value)
                        )
                    setattr(related_instance, name, value)
                    is_updated = True
            if is_updated:
                related_instance.save()
        except ModelClass.MultipleObjectsReturned, ex:
            raise TypeError(
                "Cannot look up related model field '%s' for %s on %s"
                " using '%s' as the lookup field because it returns"
                " multiple results for value '%s': %s"
                % (fieldname, ModelClass.__name__,
                   self.Meta.model.__name__, lookup_field, lookup_value, ex)
            )
        # If a related instance does not yet exist, optionally create one
        except ModelClass.DoesNotExist:
            if not field_settings.can_create:
                raise TypeError(
                    "Cannot create instance for related model field '%s'"
                    " for %s on %s because 'can_create' is not set for"
                    " this field in 'writable_related_fields'"
                    % (fieldname, ModelClass.__name__,
                       self.Meta.model.__name__)
                )

            field_data.update({lookup_field: lookup_value})
            related_instance = ModelClass.objects.create(**field_data)

        return related_instance