Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: bartTC/django-attachments
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: dtorres-sf/django-attachments
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Can’t automatically merge. Don’t worry, you can still create the pull request.
  • 7 commits
  • 7 files changed
  • 1 contributor

Commits on Oct 28, 2017

  1. Copy the full SHA
    ecb6b99 View commit details

Commits on Nov 1, 2017

  1. Set name by default

    dustingtorres committed Nov 1, 2017
    Copy the full SHA
    442515c View commit details

Commits on Nov 4, 2017

  1. Copy the full SHA
    79c4463 View commit details

Commits on Feb 27, 2018

  1. Allow for blank creator

    dustingtorres committed Feb 27, 2018
    Copy the full SHA
    70ad20a View commit details

Commits on Jun 4, 2019

  1. Copy the full SHA
    2d286f7 View commit details
  2. Add merge migration

    dustingtorres committed Jun 4, 2019
    Copy the full SHA
    d2375e6 View commit details

Commits on Aug 22, 2019

  1. Copy the full SHA
    2fd7665 View commit details
7 changes: 5 additions & 2 deletions attachments/forms.py
Original file line number Diff line number Diff line change
@@ -28,10 +28,13 @@ class AttachmentForm(forms.ModelForm):

class Meta:
model = Attachment
fields = ('attachment_file',)
fields = ('attachment_file', 'tags')
widgets = {
'tags': forms.HiddenInput(),
}

def save(self, request, obj, *args, **kwargs):
self.instance.creator = request.user
self.instance.content_type = ContentType.objects.get_for_model(obj)
self.instance.object_id = obj.pk
super(AttachmentForm, self).save(*args, **kwargs)
return super(AttachmentForm, self).save(*args, **kwargs)
27 changes: 27 additions & 0 deletions attachments/migrations/0002_auto_20171027_1700.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2017-10-28 00:00
from __future__ import unicode_literals

from django.db import migrations, models
import taggit.managers


class Migration(migrations.Migration):

dependencies = [
('taggit', '0002_auto_20150616_2121'),
('attachments', '0001_initial'),
]

operations = [
migrations.AddField(
model_name='attachment',
name='name',
field=models.CharField(blank=True, max_length=150),
),
migrations.AddField(
model_name='attachment',
name='tags',
field=taggit.managers.TaggableManager(blank=True, help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
),
]
22 changes: 22 additions & 0 deletions attachments/migrations/0003_auto_20180227_1424.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.8 on 2018-02-27 22:24
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('attachments', '0002_auto_20171027_1700'),
]

operations = [
migrations.AlterField(
model_name='attachment',
name='creator',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='created_attachments', to=settings.AUTH_USER_MODEL, verbose_name='creator'),
),
]
16 changes: 16 additions & 0 deletions attachments/migrations/0004_merge_20190604_1652.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.20 on 2019-06-04 23:52
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('attachments', '0003_auto_20180227_1424'),
('attachments', '0002_auto_20180104_1247'),
]

operations = [
]
16 changes: 15 additions & 1 deletion attachments/models.py
Original file line number Diff line number Diff line change
@@ -8,6 +8,7 @@
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from taggit.managers import TaggableManager


def attachment_upload(instance, filename):
@@ -37,13 +38,17 @@ class Attachment(models.Model):
settings.AUTH_USER_MODEL,
related_name="created_attachments",
verbose_name=_('creator'),
on_delete=models.CASCADE,
blank=True,
null=True,
on_delete=models.SET_NULL
)
attachment_file = models.FileField(
_('attachment'), upload_to=attachment_upload
)
name = models.CharField(max_length=150, blank=True)
created = models.DateTimeField(_('created'), auto_now_add=True)
modified = models.DateTimeField(_('modified'), auto_now=True)
tags = TaggableManager(blank=True)

class Meta:
verbose_name = _("attachment")
@@ -53,6 +58,11 @@ class Meta:
('delete_foreign_attachments', _('Can delete foreign attachments')),
)

def save(self, *args, **kwargs):
if(self.pk is None and not self.name):
self.name = self.filename.split(".")[0][:150]
return super(Attachment, self).save(*args, **kwargs)

def __str__(self):
return _('{username} attached {filename}').format(
username=self.creator.get_username(),
@@ -62,3 +72,7 @@ def __str__(self):
@property
def filename(self):
return os.path.split(self.attachment_file.name)[1]

def get_absolute_url(self):
if(self.content_object and hasattr(self.content_object, "get_absolute_url")):
return "{}{}/".format(self.content_object.get_absolute_url(), "attachments")
14 changes: 9 additions & 5 deletions attachments/templatetags/attachments_tags.py
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@


@register.inclusion_tag('attachments/add_form.html', takes_context=True)
def attachment_form(context, obj):
def attachment_form(context, obj, tags=None):
"""
Renders a "upload attachment" form.
@@ -18,7 +18,7 @@ def attachment_form(context, obj):
"""
if context['user'].has_perm('attachments.add_attachment'):
return {
'form': AttachmentForm(),
'form': AttachmentForm(initial={"tags":tags}),
'form_url': add_url_for_obj(obj),
'next': context.request.build_absolute_uri(),
}
@@ -61,14 +61,18 @@ def attachments_count(obj):


@register.simple_tag
def get_attachments_for(obj, *args, **kwargs):
def get_attachments_for(obj, tags=None):
"""
Resolves attachments that are attached to a given object. You can specify
the variable name in the context the attachments are stored using the `as`
argument.
argument. Default context variable name is `attachments`. If tags are
provided, the attchments will be filter to only those with the tags.
Syntax::
{% get_attachments_for obj as "my_attachments" %}
"""
return Attachment.objects.attachments_for_object(obj)
if(tags):
return Attachment.objects.attachments_for_object(obj).filter(tags__name=tags)
else:
return Attachment.objects.attachments_for_object(obj)
55 changes: 35 additions & 20 deletions attachments/views.py
Original file line number Diff line number Diff line change
@@ -12,10 +12,14 @@
from django.urls import reverse
from django.utils.translation import ugettext
from django.views.decorators.http import require_POST

from annoying.decorators import ajax_request
from .forms import AttachmentForm
from .models import Attachment
from django.template.loader import render_to_string
from settings.models import AttachmentGroup
import logging

logger = logging.getLogger(__name__)

def add_url_for_obj(obj):
return reverse(
@@ -40,6 +44,7 @@ def remove_file_from_disk(f):

@require_POST
@login_required
@ajax_request
def add_attachment(
request,
app_label,
@@ -51,38 +56,48 @@ def add_attachment(
next_ = request.POST.get('next', '/')

if not request.user.has_perm('attachments.add_attachment'):
return HttpResponseRedirect(next_)
return {"success": False, "reason": "insufficient permissions"}

model = apps.get_model(app_label, model_name)
obj = get_object_or_404(model, pk=pk)
form = AttachmentForm(request.POST, request.FILES)

if form.is_valid():
form.save(request, obj)
messages.success(request, ugettext('Your attachment was uploaded.'))
return HttpResponseRedirect(next_)

attachment = form.save(request, obj)
name = form.cleaned_data["tags"] or None
fa_icon = "fa-paperclip"
if(name):
# Get the first tag (there should really only ever be one tag)
ag = AttachmentGroup.objects.filter(name=name[0]).first()
fa_icon = ag.icon if ag else "fa-paperclip"

context = {
"attachment": attachment,
"fa_icon": fa_icon,
}
html = render_to_string("attachments/attachment.html", context, request)
return {"success": True, "html": html}
logger.error("Error adding attachment {}".format(form.errors))
template_context = {
'form': form,
'form_url': add_url_for_obj(obj),
'next': next_,
'next': next,
}
template_context.update(extra_context or {})

return render_to_response(
template_name, template_context, RequestContext(request)
)

if(extra_context):
template_context.update(extra_context)
return {"success": False, "reason": "invalid form"}

@login_required
@ajax_request
def delete_attachment(request, attachment_pk):
g = get_object_or_404(Attachment, pk=attachment_pk)
success = False
if (
request.user.has_perm('attachments.delete_attachment')
and request.user == g.creator
) or request.user.has_perm('attachments.delete_foreign_attachments'):
remove_file_from_disk(g.attachment_file)
(request.user.has_perm('attachments.delete_attachment') and
request.user == g.creator)
or
request.user.has_perm('attachments.delete_foreign_attachments')
):
g.delete()
messages.success(request, ugettext('Your attachment was deleted.'))
next_ = request.GET.get('next') or '/'
return HttpResponseRedirect(next_)
success = True
return {"success": success}