Lot of small improvement in SAS

This commit is contained in:
Skia 2016-11-25 13:47:09 +01:00
parent 0b23d39e15
commit cfbb6f4e1f
13 changed files with 170 additions and 43 deletions

View File

@ -1,4 +1,5 @@
from django.contrib import admin from django.contrib import admin
from ajax_select import make_ajax_form
from core.models import User, Page, RealGroup, SithFile from core.models import User, Page, RealGroup, SithFile
from django.contrib.auth.models import Group as AuthGroup from django.contrib.auth.models import Group as AuthGroup
@ -7,5 +8,9 @@ admin.site.register(User)
admin.site.unregister(AuthGroup) admin.site.unregister(AuthGroup)
admin.site.register(RealGroup) admin.site.register(RealGroup)
admin.site.register(Page) admin.site.register(Page)
admin.site.register(SithFile)
@admin.register(SithFile)
class SithFileAdmin(admin.ModelAdmin):
form = make_ajax_form(SithFile, {
'parent': 'files', # ManyToManyField
})

View File

@ -2,7 +2,7 @@ from django.core.exceptions import PermissionDenied
from ajax_select import register, LookupChannel from ajax_select import register, LookupChannel
from core.views.site import search_user 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 club.models import Club
from counter.models import Product, Counter from counter.models import Product, Counter
from accounting.models import ClubAccount, Company from accounting.models import ClubAccount, Company
@ -77,6 +77,13 @@ class ProductsLookup(RightManagedLookupChannel):
def format_item_display(self, item): def format_item_display(self, item):
return "%s (%s)" % (item.name, item.code) 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') @register('club_accounts')
class ClubAccountLookup(RightManagedLookupChannel): class ClubAccountLookup(RightManagedLookupChannel):
model = ClubAccount model = ClubAccount

View File

@ -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),
),
]

View File

@ -317,7 +317,9 @@ class User(AbstractBaseUser):
def get_short_name(self): def get_short_name(self):
"Returns the short name for the user." "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): def get_display_name(self):
""" """
@ -501,16 +503,16 @@ def get_thumbnail_directory(instance, filename):
class SithFile(models.Model): class SithFile(models.Model):
name = models.CharField(_('file name'), max_length=256, blank=False) name = models.CharField(_('file name'), max_length=256, blank=False)
parent = models.ForeignKey('self', related_name="children", verbose_name=_("parent"), null=True, blank=True) 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) 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"), 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"), 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")) 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) 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) view_groups = models.ManyToManyField(Group, related_name="viewable_files", verbose_name=_("view group"), blank=True)
is_folder = models.BooleanField(_("is folder"), default=True) is_folder = models.BooleanField(_("is folder"), default=True)
mime_type = models.CharField(_('mime type'), max_length=30) mime_type = models.CharField(_('mime type'), max_length=30)
size = models.IntegerField(_("size"), default=0) 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) is_moderated = models.BooleanField(_("is moderated"), default=False)
asked_for_removal = models.BooleanField(_("asked for removal"), default=False) asked_for_removal = models.BooleanField(_("asked for removal"), default=False)
is_in_sas = models.BooleanField(_("is in the SAS"), 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): def get_download_url(self):
return reverse('core:download', kwargs={'file_id': self.id}) return reverse('core:download', kwargs={'file_id': self.id})
def __str__(self):
return self.get_parent_path() + "/" + self.name
class LockError(Exception): class LockError(Exception):
"""There was a lock error on the object""" """There was a lock error on the object"""
pass pass

View File

@ -314,10 +314,11 @@ textarea {
text-align: center; text-align: center;
padding: 5px; padding: 5px;
width: 200px; width: 200px;
height: 133px; height: 140px;
background: #eee; background: #eee;
box-shadow: black 2px 2px 10px; box-shadow: black 2px 2px 10px;
margin: 10px; margin: 10px;
vertical-align: top;
} }
.album img { .album img {

View File

@ -6,12 +6,12 @@
{% endblock %} {% endblock %}
{% block content %} {% 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() %}
<div style="padding: 10px"> <div style="padding: 10px">
{% 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 %}
<h4>{{ album.name }}</h4> <h4>{{ album.name }}</h4>
<hr> <hr>
{% 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') %}
<div class="picture"> <div class="picture">
<a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict"> <a href="{{ url("sas:picture", picture_id=r.picture.id) }}#pict">
<img src="{{ r.picture.as_picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/> <img src="{{ r.picture.as_picture.get_download_thumb_url() }}" alt="{{ r.picture.get_display_name() }}" style="max-width: 100%"/>

View File

@ -25,7 +25,7 @@ from counter.models import Customer, Counter, Selling, Refilling, Product, Produ
from subscription.models import Subscription, Subscriber from subscription.models import Subscription, Subscriber
from eboutic.models import Invoice, InvoiceItem from eboutic.models import Invoice, InvoiceItem
from accounting.models import BankAccount, ClubAccount, GeneralJournal, Operation, AccountingType, Company, SimplifiedAccountingType, Label 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) db = MySQLdb.connect(**settings.OLD_MYSQL_INFOS)
start = datetime.datetime.now() start = datetime.datetime.now()
@ -1029,7 +1029,7 @@ def migrate_sas():
album_link = {} album_link = {}
picture_link = {} picture_link = {}
FILE_ROOT = "/data/sas/" FILE_ROOT = "/data/sas/"
Album.objects.filter(is_in_sas=True).delete() SithFile.objects.filter(id__gt=18886).delete()
print("Album/Pictures deleted") print("Album/Pictures deleted")
cur = db.cursor(MySQLdb.cursors.SSDictCursor) cur = db.cursor(MySQLdb.cursors.SSDictCursor)
cur.execute(""" cur.execute("""
@ -1044,44 +1044,74 @@ def migrate_sas():
album_link[str(r['id_catph'])] = a.id album_link[str(r['id_catph'])] = a.id
except Exception as e: except Exception as e:
print("FAIL to migrate Album: %s" % (repr(e))) print("FAIL to migrate Album: %s" % (repr(e)))
print("Album moved, need to make the tree")
cur.execute(""" cur.execute("""
SELECT * SELECT *
FROM sas_cat_photos FROM sas_cat_photos
""") """)
for r in cur: for r in cur:
try: try:
p = Album.objects.filter(id=album_link[r['id_catph_parent']]).first() p = Album.objects.filter(id=album_link[str(r['id_catph_parent'])]).first()
a = Album.objects.filter(id=album_link[r['id_catph']]).first() a = Album.objects.filter(id=album_link[str(r['id_catph'])]).first()
a.parent = p a.parent = p
a.save() a.save()
except: pass except: pass
print("Album migrated at %s" % datetime.datetime.now()) print("Album migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start)) print("Running time: %s" % (datetime.datetime.now()-start))
# cur.execute(""" cur.execute("""
# SELECT * SELECT *
# FROM sas_photos FROM sas_photos
# """) """)
# for r in cur: for r in cur:
# try: try:
# user = User.objects.filter(id=r['id_utilisateur']).first() or root user = User.objects.filter(id=r['id_utilisateur']).first() or root
# parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first() parent = Album.objects.filter(id=album_link[str(r['id_catph'])]).first()
# p = Picture( file_name = FILE_ROOT
# name=to_unicode(str(r['id_photo'])), if r['date_prise_vue']:
# owner=user, file_name += r['date_prise_vue'].strftime("%Y/%m/%d")
# is_moderated=True, else:
# is_folder=False, file_name += '/'.join(["1970", "01", "01"])
# mime_type="image/jpeg", file_name += "/" + str(r['id_photo']) + ".jpg"
# parent=parent
# ) file = File(open(file_name, "rb"))
# for f in p._meta.local_fields: file.name = str(r['id_photo']) + ".jpg"
# if f.name == "date":
# f.auto_now = False p = Picture(
# p.date = r['date_ajout_ph'].replace(tzinfo=timezone('Europe/Paris')) name=to_unicode(str(r['id_photo'])) + ".jpg",
# p.save() owner=user,
# picture_link[str(r['id_photo'])] = p.id is_moderated=True,
# except Exception as e: is_folder=False,
# print("FAIL to migrate Picture: %s" % (repr(e))) 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() cur.close()
print("SAS migrated at %s" % datetime.datetime.now()) print("SAS migrated at %s" % datetime.datetime.now())
print("Running time: %s" % (datetime.datetime.now()-start)) print("Running time: %s" % (datetime.datetime.now()-start))

View File

@ -4,5 +4,7 @@ from sas.models import *
admin.site.register(Album) admin.site.register(Album)
admin.site.register(Picture) # admin.site.register(Picture)
admin.site.register(PeoplePictureRelation)

View File

@ -1,4 +1,5 @@
from django.db import models from django.db import models
from django.core.urlresolvers import reverse_lazy, reverse
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -36,6 +37,9 @@ class Picture(SithFile):
def get_download_thumb_url(self): def get_download_thumb_url(self):
return reverse('sas:download_thumb', kwargs={'picture_id': self.id}) 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): def generate_thumbnails(self):
im = Image.open(BytesIO(self.file.read())) im = Image.open(BytesIO(self.file.read()))
try: try:
@ -94,3 +98,6 @@ class PeoplePictureRelation(models.Model):
class Meta: class Meta:
unique_together = ['user', 'picture'] unique_together = ['user', 'picture']
def __str__(self):
return self.user.get_display_name() + " - " + str(self.picture)

View File

@ -15,6 +15,7 @@
{% block content %} {% block content %}
<a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(album.parent) }} {{ album.get_display_name() }} <a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(album.parent) }} {{ album.get_display_name() }}
<h3>{{ album.get_display_name() }}</h3> <h3>{{ album.get_display_name() }}</h3>
<a href="{{ url('sas:album_edit', album_id=album.id) }}">{% trans %}Edit{% endtrans %}</a><br>
<hr> <hr>
<div> <div>
{% for a in album.children.filter(is_folder=True, is_moderated=True).all() %} {% for a in album.children.filter(is_folder=True, is_moderated=True).all() %}
@ -33,7 +34,7 @@
{% endfor %} {% endfor %}
</div> </div>
<div> <div>
{% 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) %} {% if p.as_picture.can_be_viewed_by(user) %}
<div class="picture"> <div class="picture">
<a href="{{ url("sas:picture", picture_id=p.id) }}#pict"> <a href="{{ url("sas:picture", picture_id=p.id) }}#pict">

View File

@ -35,6 +35,7 @@
{% block content %} {% block content %}
<a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(picture.parent) }} {{ picture.get_display_name() }} <a href="{{ url('sas:main') }}">SAS</a> > {{ print_path(picture.parent) }} {{ picture.get_display_name() }}
({{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }})
<h3> {{ picture.get_display_name() }}</h3> <h3> {{ picture.get_display_name() }}</h3>
<div style="display: inline-block; width: 19%; vertical-align: top; overflow: hidden; float: right"> <div style="display: inline-block; width: 19%; vertical-align: top; overflow: hidden; float: right">
<div> <div>
@ -60,7 +61,7 @@
<ul> <ul>
{% for r in picture.people.all() %} {% for r in picture.people.all() %}
<li> <li>
<a href="{{ r.user.get_absolute_url() }}">{{ r.user.get_display_name() }}</a> <a href="{{ r.user.get_absolute_url() }}">{{ r.user.get_short_name() }}</a>
{% if user == r.user or user.is_in_group(settings.SITH_SAS_ADMIN_GROUP_ID) %} {% if user == r.user or user.is_in_group(settings.SITH_SAS_ADMIN_GROUP_ID) %}
<a href="?remove_user={{ r.user.id }}">{% trans %}Delete{% endtrans %}</a> <a href="?remove_user={{ r.user.id }}">{% trans %}Delete{% endtrans %}</a>
{% endif %} {% endif %}
@ -73,12 +74,18 @@
<p><input type="submit" value="{% trans %}Go{% endtrans %}" /></p> <p><input type="submit" value="{% trans %}Go{% endtrans %}" /></p>
</form> </form>
</div> </div>
<div>
<h5>{% trans %}Infos{% endtrans %}</h5>
<p>{% trans %}Date: {% endtrans %}{{ picture.date|date(DATETIME_FORMAT) }}</p>
<p>{{ picture.parent.children.filter(id__lte=picture.id).count() }} / {{ picture.parent.children.count() }}</p>
</div>
<div> <div>
<h5>{% trans %}Tools{% endtrans %}</h5> <h5>{% trans %}Tools{% endtrans %}</h5>
<p> <p>
<a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a> <a href="{{ picture.get_download_url() }}">{% trans %}HD version{% endtrans %}</a>
</p> </p>
<p style="font-size: smaller;"> <p style="font-size: smaller;">
<a href="{{ url('sas:picture_edit', picture_id=picture.id) }}">{% trans %}Edit{% endtrans %}</a><br>
<a href="?rotate_left">{% trans %}Rotate left{% endtrans %}</a><br> <a href="?rotate_left">{% trans %}Rotate left{% endtrans %}</a><br>
<a href="?rotate_right">{% trans %}Rotate right{% endtrans %}</a><br> <a href="?rotate_right">{% trans %}Rotate right{% endtrans %}</a><br>
<a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a><br> <a href="?ask_removal">{% trans %}Ask for removal{% endtrans %}</a><br>

View File

@ -6,7 +6,9 @@ urlpatterns = [
url(r'^$', SASMainView.as_view(), name='main'), url(r'^$', SASMainView.as_view(), name='main'),
url(r'^moderation$', ModerationView.as_view(), name='moderation'), url(r'^moderation$', ModerationView.as_view(), name='moderation'),
url(r'^album/(?P<album_id>[0-9]+)$', AlbumView.as_view(), name='album'), url(r'^album/(?P<album_id>[0-9]+)$', AlbumView.as_view(), name='album'),
url(r'^album/(?P<album_id>[0-9]+)/edit$', AlbumEditView.as_view(), name='album_edit'),
url(r'^picture/(?P<picture_id>[0-9]+)$', PictureView.as_view(), name='picture'), url(r'^picture/(?P<picture_id>[0-9]+)$', PictureView.as_view(), name='picture'),
url(r'^picture/(?P<picture_id>[0-9]+)/edit$', PictureEditView.as_view(), name='picture_edit'),
url(r'^picture/(?P<picture_id>[0-9]+)/download$', send_pict, name='download'), url(r'^picture/(?P<picture_id>[0-9]+)/download$', send_pict, name='download'),
url(r'^picture/(?P<picture_id>[0-9]+)/download/compressed$', send_compressed, name='download_compressed'), url(r'^picture/(?P<picture_id>[0-9]+)/download/compressed$', send_compressed, name='download_compressed'),
url(r'^picture/(?P<picture_id>[0-9]+)/download/thumb$', send_thumb, name='download_thumb'), url(r'^picture/(?P<picture_id>[0-9]+)/download/thumb$', send_thumb, name='download_thumb'),

View File

@ -5,6 +5,7 @@ from django.views.generic.edit import UpdateView, CreateView, DeleteView, Proces
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from django.utils import timezone from django.utils import timezone
from django.conf import settings from django.conf import settings
from django.forms.models import modelform_factory
from django import forms from django import forms
from django.core.exceptions import PermissionDenied 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') kwargs['pictures'] = Picture.objects.filter(is_moderated=False, is_in_sas=True).order_by('id')
return kwargs 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"