Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
AE
Sith
Commits
869634d6
Commit
869634d6
authored
Nov 20, 2016
by
Skia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add thumbnail generation
parent
71d22e36
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
104 additions
and
12 deletions
+104
-12
club/migrations/0005_auto_20161120_1149.py
club/migrations/0005_auto_20161120_1149.py
+20
-0
club/models.py
club/models.py
+2
-1
core/migrations/0009_auto_20161120_1155.py
core/migrations/0009_auto_20161120_1155.py
+31
-0
core/models.py
core/models.py
+15
-2
core/utils.py
core/utils.py
+1
-1
core/views/files.py
core/views/files.py
+2
-2
sas/models.py
sas/models.py
+6
-0
sas/templates/sas/album.jinja
sas/templates/sas/album.jinja
+1
-1
sas/templates/sas/moderation.jinja
sas/templates/sas/moderation.jinja
+1
-1
sas/templates/sas/picture.jinja
sas/templates/sas/picture.jinja
+6
-3
sas/urls.py
sas/urls.py
+2
-0
sas/views.py
sas/views.py
+17
-1
No files found.
club/migrations/0005_auto_20161120_1149.py
0 → 100644
View file @
869634d6
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'club'
,
'0004_auto_20160915_1057'
),
]
operations
=
[
migrations
.
AlterField
(
model_name
=
'club'
,
name
=
'home'
,
field
=
models
.
OneToOneField
(
related_name
=
'home_of_club'
,
blank
=
True
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
verbose_name
=
'home'
,
null
=
True
,
to
=
'core.SithFile'
),
),
]
club/models.py
View file @
869634d6
...
...
@@ -36,7 +36,8 @@ class Club(models.Model):
default
=
settings
.
SITH_GROUPS
[
'root'
][
'id'
])
edit_groups
=
models
.
ManyToManyField
(
Group
,
related_name
=
"editable_club"
,
blank
=
True
)
view_groups
=
models
.
ManyToManyField
(
Group
,
related_name
=
"viewable_club"
,
blank
=
True
)
home
=
models
.
OneToOneField
(
SithFile
,
related_name
=
'home_of_club'
,
verbose_name
=
_
(
"home"
),
null
=
True
,
blank
=
True
)
home
=
models
.
OneToOneField
(
SithFile
,
related_name
=
'home_of_club'
,
verbose_name
=
_
(
"home"
),
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
)
def
check_loop
(
self
):
"""Raise a validation error when a loop is found within the parent list"""
...
...
core/migrations/0009_auto_20161120_1155.py
0 → 100644
View file @
869634d6
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
import
django.db.models.deletion
import
core.models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'core'
,
'0008_sithfile_asked_for_removal'
),
]
operations
=
[
migrations
.
AddField
(
model_name
=
'sithfile'
,
name
=
'compressed'
,
field
=
models
.
FileField
(
upload_to
=
core
.
models
.
get_compressed_directory
,
null
=
True
,
verbose_name
=
'compressed file'
,
blank
=
True
),
),
migrations
.
AddField
(
model_name
=
'sithfile'
,
name
=
'thumbnail'
,
field
=
models
.
FileField
(
upload_to
=
core
.
models
.
get_thumbnail_directory
,
null
=
True
,
verbose_name
=
'thumbnail'
,
blank
=
True
),
),
migrations
.
AlterField
(
model_name
=
'user'
,
name
=
'home'
,
field
=
models
.
OneToOneField
(
verbose_name
=
'home'
,
related_name
=
'home_of'
,
on_delete
=
django
.
db
.
models
.
deletion
.
SET_NULL
,
null
=
True
,
to
=
'core.SithFile'
,
blank
=
True
),
),
]
core/models.py
View file @
869634d6
...
...
@@ -115,7 +115,8 @@ class User(AbstractBaseUser):
),
)
groups
=
models
.
ManyToManyField
(
RealGroup
,
related_name
=
'users'
,
blank
=
True
)
home
=
models
.
OneToOneField
(
'SithFile'
,
related_name
=
'home_of'
,
verbose_name
=
_
(
"home"
),
null
=
True
,
blank
=
True
)
home
=
models
.
OneToOneField
(
'SithFile'
,
related_name
=
'home_of'
,
verbose_name
=
_
(
"home"
),
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
)
profile_pict
=
models
.
OneToOneField
(
'SithFile'
,
related_name
=
'profile_of'
,
verbose_name
=
_
(
"profile"
),
null
=
True
,
blank
=
True
,
on_delete
=
models
.
SET_NULL
)
avatar_pict
=
models
.
OneToOneField
(
'SithFile'
,
related_name
=
'avatar_of'
,
verbose_name
=
_
(
"avatar"
),
null
=
True
,
...
...
@@ -491,10 +492,18 @@ class Preferences(models.Model):
def
get_directory
(
instance
,
filename
):
return
'.{0}/{1}'
.
format
(
instance
.
get_parent_path
(),
filename
)
def
get_compressed_directory
(
instance
,
filename
):
return
'.{0}/compressed/{1}'
.
format
(
instance
.
get_parent_path
(),
filename
)
def
get_thumbnail_directory
(
instance
,
filename
):
return
'.{0}/thumbnail/{1}'
.
format
(
instance
.
get_parent_path
(),
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
)
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
)
...
...
@@ -528,6 +537,10 @@ class SithFile(models.Model):
for
c
in
self
.
children
.
all
():
c
.
delete
()
self
.
file
.
delete
()
if
self
.
compressed
:
self
.
compressed
.
delete
()
if
self
.
thumbnail
:
self
.
thumbnail
.
delete
()
return
super
(
SithFile
,
self
).
delete
()
def
clean
(
self
):
...
...
@@ -605,7 +618,7 @@ class SithFile(models.Model):
return
l
def
get_parent_path
(
self
):
return
'/'
+
'/'
.
join
([
p
.
name
for
p
in
self
.
get_parent_list
()])
return
'/'
+
'/'
.
join
([
p
.
name
for
p
in
self
.
get_parent_list
()
[::
-
1
]
])
def
get_display_name
(
self
):
return
self
.
name
...
...
core/utils.py
View file @
869634d6
...
...
@@ -13,7 +13,7 @@ def scale_dimension(width, height, long_edge):
ratio
=
long_edge
*
1.
/
height
return
int
(
width
*
ratio
),
int
(
height
*
ratio
)
def
resize_image
(
im
,
edge
,
format
):
# TODO move that into a utils file
def
resize_image
(
im
,
edge
,
format
):
(
w
,
h
)
=
im
.
size
(
width
,
height
)
=
scale_dimension
(
w
,
h
,
long_edge
=
edge
)
content
=
BytesIO
()
...
...
core/views/files.py
View file @
869634d6
...
...
@@ -19,7 +19,7 @@ import os
from
core.models
import
SithFile
from
core.views
import
CanViewMixin
,
CanEditMixin
,
CanEditPropMixin
,
CanCreateMixin
,
can_view
,
not_found
def
send_file
(
request
,
file_id
,
file_class
=
SithFile
):
def
send_file
(
request
,
file_id
,
file_class
=
SithFile
,
file_attr
=
"file"
):
"""
Send a file through Django without loading the whole file into
memory at once. The FileWrapper will turn the file object into an
...
...
@@ -35,7 +35,7 @@ def send_file(request, file_id, file_class=SithFile):
Counter
.
objects
.
filter
(
token
=
request
.
session
[
'counter_token'
]).
exists
())
):
raise
PermissionDenied
name
=
f
.
file
.
name
name
=
f
.
__getattribute__
(
file_attr
)
.
name
with
open
(
settings
.
MEDIA_ROOT
+
name
,
'rb'
)
as
filename
:
wrapper
=
FileWrapper
(
filename
)
response
=
HttpResponse
(
wrapper
,
content_type
=
f
.
mime_type
)
...
...
sas/models.py
View file @
869634d6
...
...
@@ -24,6 +24,12 @@ class Picture(SithFile):
def
get_download_url
(
self
):
return
reverse
(
'sas:download'
,
kwargs
=
{
'picture_id'
:
self
.
id
})
def
get_download_compressed_url
(
self
):
return
reverse
(
'sas:download_compressed'
,
kwargs
=
{
'picture_id'
:
self
.
id
})
def
get_download_thumb_url
(
self
):
return
reverse
(
'sas:download_thumb'
,
kwargs
=
{
'picture_id'
:
self
.
id
})
def
get_next
(
self
):
return
self
.
parent
.
children
.
exclude
(
is_moderated
=
False
,
asked_for_removal
=
True
).
filter
(
id__gt
=
self
.
id
).
order_by
(
'id'
).
first
()
...
...
sas/templates/sas/album.jinja
View file @
869634d6
...
...
@@ -28,7 +28,7 @@
{%
if
p.as_picture.can_be_viewed_by
(
user
)
%}
<div
style=
"display: inline-block; border: solid 1px black; width: 9%; margin: 0.1%"
>
<a
href=
"
{{
url
(
"sas:picture"
,
picture_id
=
p.id
)
}}
#pict"
>
<img
src=
"
{{
p.as_picture.get_download_url
()
}}
"
alt=
"
{{
p.get_display_name
()
}}
"
style=
"max-width: 100%"
/>
<img
src=
"
{{
p.as_picture.get_download_
thumb_
url
()
}}
"
alt=
"
{{
p.get_display_name
()
}}
"
style=
"max-width: 100%"
/>
</a>
</div>
{%
endif
%}
...
...
sas/templates/sas/moderation.jinja
View file @
869634d6
...
...
@@ -17,7 +17,7 @@
{%
endif
%}
<p>
<a
href=
"
{{
url
(
"sas:picture"
,
picture_id
=
p.id
)
}}
"
>
<img
src=
"
{{
url
(
'sas:download'
,
picture_id
=
p.id
)
}}
"
alt=
"
{{
p.name
}}
"
style=
"width: 100px"
>
<img
src=
"
{{
p.get_download_thumb_url
(
)
}}
"
alt=
"
{{
p.name
}}
"
style=
"width: 100px"
>
</a><br/>
{%
trans
%}
Full name:
{%
endtrans
%}{{
p.get_parent_path
()
+
'/'
+
p.name
}}
<br/>
{%
trans
%}
Owner:
{%
endtrans
%}{{
p.owner.get_display_name
()
}}
<br/>
...
...
sas/templates/sas/picture.jinja
View file @
869634d6
...
...
@@ -35,21 +35,21 @@
{{
print_path
(
picture.parent
)
}}
{{
picture.get_display_name
()
}}
<h3>
{{
picture.get_display_name
()
}}
</h3>
<div
style=
"display: inline-block; width: 89%; background: #333;"
id=
"pict"
>
<img
src=
"
{{
picture.get_download_url
()
}}
"
alt=
"
{{
picture.get_display_name
()
}}
"
style=
"width: 90%; display: block; margin: auto"
/>
<img
src=
"
{{
picture.get_download_
compressed_
url
()
}}
"
alt=
"
{{
picture.get_display_name
()
}}
"
style=
"width: 90%; display: block; margin: auto"
/>
</div>
<div
style=
"display: inline-block; width: 10%; vertical-align: top;"
>
<div>
<div
id=
"prev"
>
{%
if
picture.get_previous
()
%}
<a
href=
"
{{
url
(
"sas:picture"
,
picture_id
=
picture.get_previous
()
.
id
)
}}
#pict"
>
<img
src=
"
{{
picture.get_previous
()
.
as_picture.get_download_url
()
}}
"
alt=
"
{{
picture.get_previous
()
.
get_display_name
()
}}
"
/>
<img
src=
"
{{
picture.get_previous
()
.
as_picture.get_download_
thumb_
url
()
}}
"
alt=
"
{{
picture.get_previous
()
.
get_display_name
()
}}
"
/>
</a>
{%
endif
%}
</div>
<div
id=
"next"
>
{%
if
picture.get_next
()
%}
<a
href=
"
{{
url
(
"sas:picture"
,
picture_id
=
picture.get_next
()
.
id
)
}}
#pict"
>
<img
src=
"
{{
picture.get_next
()
.
as_picture.get_download_url
()
}}
"
alt=
"
{{
picture.get_next
()
.
get_display_name
()
}}
"
/>
<img
src=
"
{{
picture.get_next
()
.
as_picture.get_download_
thumb_
url
()
}}
"
alt=
"
{{
picture.get_next
()
.
get_display_name
()
}}
"
/>
</a>
{%
endif
%}
</div>
...
...
@@ -73,6 +73,9 @@
<p><input
type=
"submit"
value=
"
{%
trans
%}
Go
{%
endtrans
%}
"
/></p>
</form>
</div>
<p>
<a
href=
"
{{
picture.get_download_url
()
}}
"
>
{%
trans
%}
HD version
{%
endtrans
%}
</a>
</p>
<p
style=
"font-size: smaller;"
>
<a
href=
"?ask_removal"
>
{%
trans
%}
Ask for removal
{%
endtrans
%}
</a>
</p>
...
...
sas/urls.py
View file @
869634d6
...
...
@@ -8,6 +8,8 @@ urlpatterns = [
url
(
r
'^album/(?P<album_id>[0-9]+)$'
,
AlbumView
.
as_view
(),
name
=
'album'
),
url
(
r
'^picture/(?P<picture_id>[0-9]+)$'
,
PictureView
.
as_view
(),
name
=
'picture'
),
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/thumb$'
,
send_thumb
,
name
=
'download_thumb'
),
# url(r'^album/new$', AlbumCreateView.as_view(), name='album_new'),
# url(r'^(?P<club_id>[0-9]+)/$', ClubView.as_view(), name='club_view'),
]
...
...
sas/views.py
View file @
869634d6
...
...
@@ -23,6 +23,9 @@ class SASForm(forms.Form):
required
=
False
)
def
process
(
self
,
parent
,
owner
,
files
,
automodere
=
False
):
from
core.utils
import
resize_image
from
io
import
BytesIO
from
PIL
import
Image
try
:
if
self
.
cleaned_data
[
'album_name'
]
!=
""
:
album
=
Album
(
parent
=
parent
,
name
=
self
.
cleaned_data
[
'album_name'
],
owner
=
owner
,
is_moderated
=
automodere
)
...
...
@@ -36,8 +39,15 @@ class SASForm(forms.Form):
is_folder
=
False
,
is_moderated
=
automodere
)
try
:
new_file
.
clean
()
# TODO: generate thumbnail
im
=
Image
.
open
(
BytesIO
(
f
.
read
()))
thumb
=
resize_image
(
im
,
200
,
f
.
content_type
.
split
(
'/'
)[
-
1
])
compressed
=
resize_image
(
im
,
600
,
f
.
content_type
.
split
(
'/'
)[
-
1
])
new_file
.
thumbnail
=
thumb
new_file
.
thumbnail
.
name
=
new_file
.
name
new_file
.
compressed
=
compressed
new_file
.
compressed
.
name
=
new_file
.
name
new_file
.
save
()
print
(
new_file
.
compressed
)
except
Exception
as
e
:
self
.
add_error
(
None
,
_
(
"Error uploading file %(file_name)s: %(msg)s"
)
%
{
'file_name'
:
f
,
'msg'
:
repr
(
e
)})
...
...
@@ -120,6 +130,12 @@ class PictureView(CanViewMixin, DetailView, FormMixin):
def
send_pict
(
request
,
picture_id
):
return
send_file
(
request
,
picture_id
,
Picture
)
def
send_compressed
(
request
,
picture_id
):
return
send_file
(
request
,
picture_id
,
Picture
,
"compressed"
)
def
send_thumb
(
request
,
picture_id
):
return
send_file
(
request
,
picture_id
,
Picture
,
"thumbnail"
)
class
AlbumView
(
CanViewMixin
,
DetailView
,
FormMixin
):
model
=
Album
form_class
=
SASForm
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment