Package: django-attachments
django-attachmentsdjango-attachments is a generic set of template tags to attach any kind of
files to models.Installation:Putattachmentsto yourINSTALLED_APPSin yoursettings.pywithin your django project:INSTALLED_APPS=(...'attachments',)Add the attachments urlpattern to yoururls.py:url(r'^attachments/',include('attachments.urls',namespace='attachments')),Migrate your database:./manage.pymigrateGrant the user some permissions:Foradding attachmentsgrant the user (or group) the permissionattachments.add_attachment.Fordeleting attachmentsgrant the user (or group) the permissionattachments.delete_attachment. This allows the user to delete their
attachments only.Fordeleting foreign attachments(attachments by other users) grant
the user the permissionattachments.delete_foreign_attachments.SetDELETE_ATTACHMENTS_FROM_DISKtoTrueif you want to remove
files from disk when Attachment objects are removed!ConfigureFILE_UPLOAD_MAX_SIZE(optional). This is the maximum size in
bytes before raising form validation errors. If not set there is no restriction
on file size.Mind that you serve files!django-attachments stores the files in your site_media directory and does not modify
them. For example, if an user uploads a .html file your webserver will probably display
it in HTML. It’s a good idea to serve such files as plain text. In a Apache2
configuration this would look like:<Location/site_media/attachments>AddTypetext/plain.html.htm.shtml.php.php5.php4.pl.cgi</Location>House-keepingdjango-attachments provides thedelete_stale_attachmentsmanagement command.
It will remove all attachments for which the related objects don’t exist anymore!
Sys-admins could then:./manage.pydelete_stale_attachmentsYou may also want to execute this via cron.Local developmentInstalling a local devel environment withpipenv.
It creates a virtualenv for you with the right ENV variables loaded from.env.# pip install pipenv$pipenvinstallLoading.envenvironmentvariables...InstallingdependenciesfromPipfile.lock(a053bc)...Toactivatethisproject'svirtualenv,runpipenvshell.Alternatively,runacommandinsidethevirtualenvwithpipenvrun.TestsRun the testsuite in your local environment usingpipenv:$cddjango-attachments/$pipenvinstall--dev$pipenvrunpytestattachments/Or use tox to test against various Django and Python versions:$tox-rYou can also invoke the test suite or other ‘manage.py’ commands by calling
thedjango-admintool with the test app settings:$cddjango-attachments/$pipenvinstall--dev$pipenvruntest$pipenvrundjango-admin.pyrunserver$pipenvrundjango-adminmakemigrations--dry-runBuilding a new release$gittag$changeversioninsetup.cfg$pipinstall-Usetuptools$pythonsetup.pysdist&&pythonsetup.pybdist_wheel--universal$twineupload--signdist/*Usage:In contrib.admin:django-attachments provides a inline object to add a list of attachments to
any kind of model in your admin app.Simply addAttachmentInlinesto the admin options of your model. Example:fromdjango.contribimportadminfromattachments.adminimportAttachmentInlinesclassMyEntryOptions(admin.ModelAdmin):inlines=(AttachmentInlines,)In your frontend templates:First of all, load the attachments_tags in every template you want to use it:{%loadattachments_tags%}django-attachments comes with some templatetags to add or delete attachments
for your model objects in your frontend.get_attachments_for [object]: Fetches the attachments for the given
model instance. You can optionally define a variable name in which the attachment
list is stored in the template context (this is required in Django 1.8). If
you do not define a variable name, the result is printed instead.{%get_attachments_forentryasattachments_list%}attachments_count [object]: Counts the attachments for the given
model instance and returns an int:{%attachments_countentry%}attachment_form: Renders a upload form to add attachments for the given
model instance. Example:{%attachment_form[object]%}It returns an empty string if the current user is not logged in.attachment_delete_link: Renders a link to the delete view for the givenattachment. Example:{%forattinattachments_list%}{{att}}{%attachment_delete_linkatt%}{%endfor%}This tag automatically checks for permission. It returns only a html link if the
give n attachment’s creator is the current logged in user or the user has thedelete_foreign_attachmentspermission.Quick Example:{%loadattachments_tags%}{%get_attachments_forentryasmy_entry_attachments%}<span>Object has{%attachments_countentry%}attachments</span>{%ifmy_entry_attachments%}<ul>{%forattachmentinmy_entry_attachments%}<li><ahref="{{attachment.attachment_file.url}}">{{attachment.filename}}</a>{%attachment_delete_linkattachment%}</li>{%endfor%}</ul>{%endif%}{%attachment_formentry%}{%ifmessages%}<ulclass="messages">{%formessageinmessages%}<li{%ifmessage.tags%}class="{{message.tags}}"{%endif%}>{{message}}</li>{%endfor%}</ul>{%endif%}SettingsDELETE_ATTACHMENTS_FROM_DISKwill delete attachment files when the
attachment model is deleted.Default False!FILE_UPLOAD_MAX_SIZEin bytes. Deny file uploads exceeding this value.Undefined by default.AppConfig.attachment_validators- a list of custom form validator functions
which will be executed against uploaded files. If any of them raisesValidationErrorthe upload will be denied.Empty by default. Seeattachments/tests/testapp/apps.pyfor an example.Changelog:v1.11 (2023-04-20)Return form errors as JSON fromadd_attachment()view
when theX-Return-Form-Errorsrequest header is present.
Response code is 400 - BAD REQUEST because this is a client
error.v1.10 (2023-04-14)Support custom form validators viaAppConfig.attachment_validatorsRemove quotes from “attachment_list” (Aaron C. de Bruyn)Add a URL for matching objects with a UUID4 primary key. FixIssue #94(Aaron C. de Bruyn)Document settings supported by django-attachmentsDocument how to make a new release. ClosesIssue #78Start testing with GitHub ActionsDrop testing with end-of-life versions of DjangoAdd testing with Django 4.0 and 4.1, Python 3.9 and 3.10
and switch the default Python version used to 3.10Add testing w/ Python 3.11 - supported only on Django 4.1 for nowv1.9.1 (2021-04-30)Rebuild the previous version but don’t ship a left-over migration filev1.9 (2021-04-29) – removed from PyPIConfigure PK explicitly to AutoField for Django 3.2+, seehttps://docs.djangoproject.com/en/3.2/releases/3.2/#customizing-type-of-auto-created-primary-keysStart testing with Django 3.2Fix typo in README (Jesaja Everling)Enable syntax highlighting in README (Basil S)v1.8 (2020-09-03)Alterobject_idfromTextField()toCharField(max_length=64),
and keep the db_index argument. This resolves the issues on MariaDB/MySQL.v1.7 (2020-08-31) -broken on MariaDB/MySQLAdd DB index toobject_id,createdandmodifiedfields.Adddelete_stale_attachmentscommand to remove attachments for which
the corresponding object has been deleted.AddAttachment.attach_to()method for moving attachments between
different objects.Django 3.1 compatibility and tests.v1.6 (2020-08-17)Primary keys of related objects other than Integers (such as UUIDs)
are now supported.v1.5 (2019-12-08)Dropped support for Python 3.4.Added suport for Python 3.8.Django 3.0 compatibility and tests.Django 2.2 compatibility and tests.v1.4.1 (2019-07-22)The templatetags now allow an optionalnextparameter.v1.4 (2019-02-14)Dropped Support for Django <=1.10.Fixed ‘next’ URL argument redirect.v1.3.1 (2019-01-24):Django 2.1 and Python 3.7 support.General code cleanup.v1.3 (2018-01-09):Added a missing database migration.New templatetagattachments_count.New settingDELETE_ATTACHMENTS_FROM_DISKto delete attachment files
if the attachment model is deleted.New settingFILE_UPLOAD_MAX_SIZEto deny file uploads exceeding this
value.v1.2 (2017-12-15):Django 1.11 and 2.0 compatibility and tests.v1.1 (2017-03-18):Django 1.10 compatibility and tests.Python 3.6 compatibility and tests.Fixes problems where models have a foreign key named something other
than “id”.v1.0.1 (2016-06-12):Added finnish translation.Minor test suite improvements.v1.0 (2016-03-19):General code cleanup to keep compatibility with the latest Django
(currently 1.8 upwards) as well as Python3. Introduced full testsuite.Backwards incompatible: The attachment views now use a urlpatternnamespaceso you need to adjust the urlpattern:url(r'^attachments/', include('attachments.urls', namespace='attachments')),Backwards incompatible: The quotes around theasvariable namemust be removed:{% get_attachments_for entry as "my_entry_attachments" %}

becomes

{% get_attachments_for entry as my_entry_attachments %}Possibly backwards incompatible: The old version had bugs aroundpermissions and were not enforcing it in all places. From now on the
related permissionsadd_attachmentanddelete_attachmentmust
been applied to all related users.v0.3.1 (2009-07-29):Added a note to the README that you should secure your static files.v0.3 (2009-07-22):This version adds more granular control about user permissons. You need
to explicitly add permissions to users who should been able to upload,
delete or delete foreign attachments.This might bebackwards incompatibleas you did not need to assign
add/delete permissions before!