diff --git a/core/admin.py b/core/admin.py index 3d1d86c7..5742d460 100644 --- a/core/admin.py +++ b/core/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin +from ajax_select import make_ajax_form from core.models import User, Page, RealGroup, SithFile from django.contrib.auth.models import Group as AuthGroup @@ -7,5 +8,9 @@ admin.site.register(User) admin.site.unregister(AuthGroup) admin.site.register(RealGroup) admin.site.register(Page) -admin.site.register(SithFile) +@admin.register(SithFile) +class SithFileAdmin(admin.ModelAdmin): + form = make_ajax_form(SithFile, { + 'parent': 'files', # ManyToManyField + }) diff --git a/core/lookups.py b/core/lookups.py index dc62eb0a..20dd7113 100644 --- a/core/lookups.py +++ b/core/lookups.py @@ -2,7 +2,7 @@ from django.core.exceptions import PermissionDenied from ajax_select import register, LookupChannel from core.views.site import search_user -from core.models import User, Group +from core.models import User, Group, SithFile from club.models import Club from counter.models import Product, Counter from accounting.models import ClubAccount, Company @@ -77,6 +77,13 @@ class ProductsLookup(RightManagedLookupChannel): def format_item_display(self, item): return "%s (%s)" % (item.name, item.code) +@register('files') +class SithFileLookup(RightManagedLookupChannel): + model = SithFile + + def get_query(self, q, request): + return self.model.objects.filter(name__icontains=q)[:50] + @register('club_accounts') class ClubAccountLookup(RightManagedLookupChannel): model = ClubAccount diff --git a/core/migrations/0011_auto_20161124_0848.py b/core/migrations/0011_auto_20161124_0848.py new file mode 100644 index 00000000..8baba108 --- /dev/null +++ b/core/migrations/0011_auto_20161124_0848.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone +import core.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0010_sithfile_is_in_sas'), + ] + + operations = [ + migrations.AlterField( + model_name='sithfile', + name='compressed', + field=models.FileField(verbose_name='compressed file', upload_to=core.models.get_compressed_directory, null=True, blank=True, max_length=256), + ), + migrations.AlterField( + model_name='sithfile', + name='date', + field=models.DateTimeField(verbose_name='date', default=django.utils.timezone.now), + ), + migrations.AlterField( + model_name='sithfile', + name='file', + field=models.FileField(verbose_name='file', upload_to=core.models.get_directory, null=True, blank=True, max_length=256), + ), + migrations.AlterField( + model_name='sithfile', + name='thumbnail', + field=models.FileField(verbose_name='thumbnail', upload_to=core.models.get_thumbnail_directory, null=True, blank=True, max_length=256), + ), + ] diff --git a/core/models.py b/core/models.py index 57e0aa09..c13c57f3 100644 --- a/core/models.py +++ b/core/models.py @@ -317,7 +317,9 @@ class User(AbstractBaseUser): def get_short_name(self): "Returns the short name for the user." - return self.first_name + if self.nick_name: + return self.nick_name + return self.first_name + " " + self.last_name def get_display_name(self): """ @@ -501,16 +503,16 @@ def get_thumbnail_directory(instance, filename): class SithFile(models.Model): name = models.CharField(_('file name'), max_length=256, blank=False) parent = models.ForeignKey('self', related_name="children", verbose_name=_("parent"), null=True, blank=True) - file = models.FileField(upload_to=get_directory, verbose_name=_("file"), null=True, blank=True) - compressed = models.FileField(upload_to=get_compressed_directory, verbose_name=_("compressed file"), null=True, blank=True) - thumbnail = models.FileField(upload_to=get_thumbnail_directory, verbose_name=_("thumbnail"), null=True, blank=True) + file = models.FileField(upload_to=get_directory, verbose_name=_("file"), max_length=256, null=True, blank=True) + compressed = models.FileField(upload_to=get_compressed_directory, verbose_name=_("compressed file"), max_length=256, null=True, blank=True) + thumbnail = models.FileField(upload_to=get_thumbnail_directory, verbose_name=_("thumbnail"), max_length=256, null=True, blank=True) owner = models.ForeignKey(User, related_name="owned_files", verbose_name=_("owner")) edit_groups = models.ManyToManyField(Group, related_name="editable_files", verbose_name=_("edit group"), blank=True) view_groups = models.ManyToManyField(Group, related_name="viewable_files", verbose_name=_("view group"), blank=True) is_folder = models.BooleanField(_("is folder"), default=True) mime_type = models.CharField(_('mime type'), max_length=30) size = models.IntegerField(_("size"), default=0) - date = models.DateTimeField(_('date'), auto_now=True) + date = models.DateTimeField(_('date'), default=timezone.now) is_moderated = models.BooleanField(_("is moderated"), default=False) asked_for_removal = models.BooleanField(_("asked for removal"), default=False) is_in_sas = models.BooleanField(_("is in the SAS"), default=False) @@ -629,6 +631,9 @@ class SithFile(models.Model): def get_download_url(self): return reverse('core:download', kwargs={'file_id': self.id}) + def __str__(self): + return self.get_parent_path() + "/" + self.name + class LockError(Exception): """There was a lock error on the object""" pass diff --git a/core/static/core/style.css b/core/static/core/style.css index e09009c0..187664b7 100644 --- a/core/static/core/style.css +++ b/core/static/core/style.css @@ -314,10 +314,11 @@ textarea { text-align: center; padding: 5px; width: 200px; - height: 133px; + height: 140px; background: #eee; box-shadow: black 2px 2px 10px; margin: 10px; + vertical-align: top; } .album img { diff --git a/core/templates/core/user_pictures.jinja b/core/templates/core/user_pictures.jinja index df54dd0c..5ee4a51e 100644 --- a/core/templates/core/user_pictures.jinja +++ b/core/templates/core/user_pictures.jinja @@ -6,12 +6,12 @@ {% endblock %} {% block content %} -{% for r in user.pictures.exclude(picture=None).values('user__pictures__picture__parent').distinct() %} +{% for r in profile.pictures.exclude(picture=None).values('user__pictures__picture__parent').distinct() %}
- {% set album = user.pictures.filter(picture__parent=r['user__pictures__picture__parent']).first().picture.parent %} + {% set album = profile.pictures.filter(picture__parent=r['user__pictures__picture__parent']).first().picture.parent %}

{{ album.name }}


- {% for r in user.pictures.exclude(picture=None).filter(picture__parent=album) %} + {% for r in profile.pictures.exclude(picture=None).filter(picture__parent=album).order_by('id') %}
{{ r.picture.get_display_name() }} diff --git a/migrate.py b/migrate.py index f5976322..97d952bf 100644 --- a/migrate.py +++ b/migrate.py @@ -25,7 +25,7 @@ from counter.models import Customer, Counter, Selling, Refilling, Product, Produ from subscription.models import Subscription, Subscriber from eboutic.models import Invoice, InvoiceItem from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label -from sas.models import Album, Picture +from sas.models import Album, Picture, PeoplePictureRelation db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS) start = datetime.datetime.now() @@ -1029,7 +1029,7 @@ def migrate_sas(): album_link = {} picture_link = {} FILE_ROOT = "/data/sas/" - Album.objects.filter(is_in_sas=True).delete() + SithFile.objects.filter(id__gt=18886).delete() print("Album/Pictures deleted") cur = db.cursor(MySQLdb.cursors.SSDictCursor) cur.execute(""" @@ -1044,44 +1044,74 @@ def migrate_sas(): album_link[str(r['id_catph'])] = a.id except Exception as e: print("FAIL to migrate Album: %s" % (repr(e))) + print("Album moved, need to make the tree") cur.execute(""" SELECT * FROM sas_cat_photos """) for r in cur: try: - p = Album.objects.filter(id=album_link[r['id_catph_parent']]).first() - a = Album.objects.filter(id=album_link[r['id_catph']]).first() + p = Album.objects.filter(id=album_link[str(r['id_catph_parent'])]).first() + a = Album.objects.filter(id=album_link[str(r['id_catph'])]).first() a.parent = p a.save() except: pass print("Album migrated at %s" % datetime.datetime.now()) print("Running time: %s" % (datetime.datetime.now()-start)) - # cur.execute(""" - # SELECT * - # FROM sas_photos - # """) - # for r in cur: - # try: - # user = User.objects.filter(id=r['id_utilisateur']).first() or root - # parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first() + cur.execute(""" + SELECT * + FROM sas_photos + """) + for r in cur: + try: + user = User.objects.filter(id=r['id_utilisateur']).first() or root + parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first() - # p = Picture( - # name=to_unicode(str(r['id_photo'])), - # owner=user, - # is_moderated=True, - # is_folder=False, - # mime_type="image/jpeg", - # parent=parent - # ) - # for f in p._meta.local_fields: - # if f.name == "date": - # f.auto_now = False - # p.date = r['date_ajout_ph'].replace(tzinfo=timezone('Europe/Paris')) - # p.save() - # picture_link[str(r['id_photo'])] = p.id - # except Exception as e: - # print("FAIL to migrate Picture: %s" % (repr(e))) + file_name = FILE_ROOT + if r['date_prise_vue']: + file_name += r['date_prise_vue'].strftime("%Y/%m/%d") + else: + file_name += '/'.join(["1970", "01", "01"]) + file_name += "/" + str(r['id_photo']) + ".jpg" + + file = File(open(file_name, "rb")) + file.name = str(r['id_photo']) + ".jpg" + + p = Picture( + name=to_unicode(str(r['id_photo'])) + ".jpg", + owner=user, + is_moderated=True, + is_folder=False, + mime_type="image/jpeg", + parent=parent, + file=file, + ) + if r['date_prise_vue']: + p.date = r['date_prise_vue'].replace(tzinfo=timezone('Europe/Paris')) + else: + p.date = r['date_ajout_ph'].replace(tzinfo=timezone('Europe/Paris')) + for f in p._meta.local_fields: + if f.name == "date": + f.auto_now = False + p.generate_thumbnails() + db2 = MySQLdb.connect(**settings.OLD_MYSQL_INFOS) + cur2 = db2.cursor(MySQLdb.cursors.SSDictCursor) + cur2.execute(""" + SELECT * + FROM sas_personnes_photos + WHERE id_photo = %s + """, (r['id_photo'], )) + for r2 in cur2: + try: + u = User.objects.filter(id=r2['id_utilisateur']).first() + if u: + PeoplePictureRelation(user=u, picture=p).save() + except: + print("Fail to associate user %d to picture %d" % (r2['id_utilisateur'], p.id)) + picture_link[str(r['id_photo'])] = p.id + except Exception as e: + pass + print("FAIL to migrate Picture: %s" % (repr(e))) cur.close() print("SAS migrated at %s" % datetime.datetime.now()) print("Running time: %s" % (datetime.datetime.now()-start)) diff --git a/sas/admin.py b/sas/admin.py index aec06f37..c49ee007 100644 --- a/sas/admin.py +++ b/sas/admin.py @@ -4,5 +4,7 @@ from sas.models import * admin.site.register(Album) -admin.site.register(Picture) +# admin.site.register(Picture) +admin.site.register(PeoplePictureRelation) + diff --git a/sas/models.py b/sas/models.py index 64c49543..18483e61 100644 --- a/sas/models.py +++ b/sas/models.py @@ -1,4 +1,5 @@ from django.db import models +from django.core.urlresolvers import reverse_lazy, reverse from django.conf import settings from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ @@ -36,6 +37,9 @@ class Picture(SithFile): def get_download_thumb_url(self): return reverse('sas:download_thumb', kwargs={'picture_id': self.id}) + def get_absolute_url(self): + return reverse('sas:picture', kwargs={'picture_id': self.id}) + def generate_thumbnails(self): im = Image.open(BytesIO(self.file.read())) try: @@ -94,3 +98,6 @@ class PeoplePictureRelation(models.Model): class Meta: unique_together = ['user', 'picture'] + + def __str__(self): + return self.user.get_display_name() + " - " + str(self.picture) diff --git a/sas/templates/sas/album.jinja b/sas/templates/sas/album.jinja index 38aa67c9..2bf2f48a 100644 --- a/sas/templates/sas/album.jinja +++ b/sas/templates/sas/album.jinja @@ -15,6 +15,7 @@ {% block content %} SAS > {{ print_path(album.parent) }} {{ album.get_display_name() }}

{{ album.get_display_name() }}

+{% trans %}Edit{% endtrans %}

{% for a in album.children.filter(is_folder=True, is_moderated=True).all() %} @@ -33,7 +34,7 @@ {% endfor %}
- {% for p in album.children.filter(is_folder=False, is_moderated=True).all() %} + {% for p in album.children.filter(is_folder=False, is_moderated=True).order_by('id') %} {% if p.as_picture.can_be_viewed_by(user) %}
diff --git a/sas/templates/sas/picture.jinja b/sas/templates/sas/picture.jinja index 1877928d..cc2eed9c 100644 --- a/sas/templates/sas/picture.jinja +++ b/sas/templates/sas/picture.jinja @@ -35,7 +35,8 @@ {% block content %} SAS > {{ print_path(picture.parent) }} {{ picture.get_display_name() }} -

{{ picture.get_display_name() }}

+({{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }}) +

{{ picture.get_display_name() }}

+
+
{% trans %}Infos{% endtrans %}
+

{% trans %}Date: {% endtrans %}{{ picture.date|date(DATETIME_FORMAT) }}

+

{{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }}

+
{% trans %}Tools{% endtrans %}

{% trans %}HD version{% endtrans %}

+ {% trans %}Edit{% endtrans %}
{% trans %}Rotate left{% endtrans %}
{% trans %}Rotate right{% endtrans %}
{% trans %}Ask for removal{% endtrans %}
diff --git a/sas/urls.py b/sas/urls.py index 23464227..ac90d432 100644 --- a/sas/urls.py +++ b/sas/urls.py @@ -6,7 +6,9 @@ urlpatterns = [ url(r'^$', SASMainView.as_view(), name='main'), url(r'^moderation$', ModerationView.as_view(), name='moderation'), url(r'^album/(?P[0-9]+)$', AlbumView.as_view(), name='album'), + url(r'^album/(?P[0-9]+)/edit$', AlbumEditView.as_view(), name='album_edit'), url(r'^picture/(?P[0-9]+)$', PictureView.as_view(), name='picture'), + url(r'^picture/(?P[0-9]+)/edit$', PictureEditView.as_view(), name='picture_edit'), url(r'^picture/(?P[0-9]+)/download$', send_pict, name='download'), url(r'^picture/(?P[0-9]+)/download/compressed$', send_compressed, name='download_compressed'), url(r'^picture/(?P[0-9]+)/download/thumb$', send_thumb, name='download_thumb'), diff --git a/sas/views.py b/sas/views.py index 33b74fba..6ad04439 100644 --- a/sas/views.py +++ b/sas/views.py @@ -5,6 +5,7 @@ from django.views.generic.edit import UpdateView, CreateView, DeleteView, Proces from django.utils.translation import ugettext as _ from django.utils import timezone from django.conf import settings +from django.forms.models import modelform_factory from django import forms from django.core.exceptions import PermissionDenied @@ -192,4 +193,27 @@ class ModerationView(TemplateView): kwargs['pictures'] = Picture.objects.filter(is_moderated=False, is_in_sas=True).order_by('id') return kwargs +class PictureEditForm(forms.ModelForm): + class Meta: + model = Picture + fields=['name', 'parent'] + parent = make_ajax_field(Picture, 'parent', 'files', help_text="") + +class AlbumEditForm(forms.ModelForm): + class Meta: + model = Album + fields=['name', 'parent'] + parent = make_ajax_field(Album, 'parent', 'files', help_text="") + +class PictureEditView(UpdateView): + model=Picture + form_class=PictureEditForm + template_name='core/edit.jinja' + pk_url_kwarg = "picture_id" + +class AlbumEditView(UpdateView): + model=Album + form_class=AlbumEditForm + template_name='core/edit.jinja' + pk_url_kwarg = "album_id"