@register.filter()<EOL>def attachments(value, obj, width = WIDTH):
match = ATTACHMENT_REGEX.search(value)<EOL>safe = isinstance(value, (SafeString, SafeUnicode))<EOL>while not match is None and match.end() <= len(value):<EOL><INDENT>start = match.start()<EOL>end = match.end()<EOL>groups = match.groups()<EOL>if len(groups) > <NUM_LIT:0>:<EOL><INDENT>index = groups[<NUM_LIT:0>]<EOL>options = None<EOL>if len(groups) > <NUM_LIT:1>:<EOL><INDENT>options = groups[<NUM_LIT:1>]<EOL>if options:<EOL><INDENT>options = options.strip()<EOL>if options:<EOL><INDENT>try:<EOL><INDENT>options = split(smart_str(options))<EOL><DEDENT>except:<EOL><INDENT>options = None<EOL><DEDENT><DEDENT><DEDENT><DEDENT>args = []<EOL>kwargs = {<EOL>'<STR_LIT:width>': width<EOL>}<EOL>if options:<EOL><INDENT>for option in options:<EOL><INDENT>key, equals, val = option.partition('<STR_LIT:=>')<EOL>if equals != '<STR_LIT:=>':<EOL><INDENT>if key and not val:<EOL><INDENT>args.append(key)<EOL><DEDENT>continue<EOL><DEDENT>kwargs[key] = val<EOL><DEDENT><DEDENT>try:<EOL><INDENT>if isinstance(obj, dict):<EOL><INDENT>inner = Attachment(<EOL>**obj['<STR_LIT>'][int(index) - <NUM_LIT:1>]<EOL>).render(*args, **kwargs)<EOL><DEDENT>else:<EOL><INDENT>inner = obj.attachments.all()[int(index) - <NUM_LIT:1>].render(*args, **kwargs)<EOL><DEDENT><DEDENT>except:<EOL><INDENT>inner = '<STR_LIT>'<EOL><DEDENT><DEDENT>else:<EOL><INDENT>inner = '<STR_LIT>'<EOL><DEDENT>value = value[:start] + inner + value[end:]<EOL>match = ATTACHMENT_REGEX.search(value, start + len(inner))<EOL><DEDENT>if safe:<EOL><INDENT>return mark_safe(value)<EOL><DEDENT>else:<EOL><INDENT>return value<EOL><DEDENT>
Parse the copy inside ``value`` and look for shortcodes in this format::

    <p>Here's an attachment</p>
    <p>[attachment 1]</p>

Replace the shortcode with a full image, video or audio element, or download link

:param obj: The object against which attachments are saved
:param width: The width of images or audio/video tags (defaults to the ``ATTACHMENT_WIDTH`` SETTING)