def model_to_dict(instance, **options):
    "Takes a model instance and converts it into a dict."
    options = _defaults(options)
    attrs = {}
    if options['prehook']:
        if isinstance(options['prehook'], collections.Callable):
            instance = options['prehook'](instance)
            if instance is None:
                return attrs
    for alias in options['fields']:
        accessor = options['aliases'].get(alias, alias)
        key = options['prefix'] + alias
        if options['camelcase']:
            key = convert_to_camel(key)
        value = get_field_value(instance, accessor,
                                allow_missing=options['allow_missing'])
        if isinstance(value, (models.Model, QuerySet)):
            _options = _defaults(options['related'].get(accessor, {}))
            if '%(accessor)s' in _options['prefix']:
                _options['prefix'] = _options['prefix'] % {'accessor': alias}
            if isinstance(value, models.Model):
                if len(_options['fields']) == 1 and _options['flat'] \
                        and not _options['merge']:
                    value = list(serialize(value, **_options).values())[0]
                else:
                    _attrs = serialize(value, **_options)
                    if _options['merge']:
                        attrs.update(_attrs)
                        continue
                    value = _attrs
            else:
                value = serialize(value, **_options)
        attrs[key] = value
    if options['posthook']:
        attrs = options['posthook'](instance, attrs)
    return attrs