Add early author search; Load Photo.mimetype on instantiation
This commit is contained in:
parent
5038d92b93
commit
564518f4d8
12 changed files with 69 additions and 46 deletions
|
@ -121,7 +121,7 @@ DEFAULT_CONFIGURATION = {
|
||||||
|
|
||||||
'min_username_length': 2,
|
'min_username_length': 2,
|
||||||
'max_username_length': 24,
|
'max_username_length': 24,
|
||||||
'valid_username_chars': string.ascii_letters + string.digits + '~!@#$%^&*()[]{}:;,.<>/\\-_+=',
|
'valid_username_chars': string.ascii_letters + string.digits + '~!@#$%^*()[]{}:;,.<>/\\-_+=',
|
||||||
'min_password_length': 6,
|
'min_password_length': 6,
|
||||||
|
|
||||||
'id_length': 12,
|
'id_length': 12,
|
||||||
|
|
22
etiquette.py
22
etiquette.py
|
@ -404,8 +404,8 @@ def get_search_core():
|
||||||
limit = 50
|
limit = 50
|
||||||
|
|
||||||
# OFFSET
|
# OFFSET
|
||||||
offset = request.args.get('offset', None)
|
offset = request.args.get('offset', '')
|
||||||
if offset:
|
if offset.isdigit():
|
||||||
offset = int(offset)
|
offset = int(offset)
|
||||||
else:
|
else:
|
||||||
offset = None
|
offset = None
|
||||||
|
@ -421,6 +421,15 @@ def get_search_core():
|
||||||
tag_mays = [qualname_map.get(tag, tag) for tag in tag_mays if tag != '']
|
tag_mays = [qualname_map.get(tag, tag) for tag in tag_mays if tag != '']
|
||||||
tag_forbids = [qualname_map.get(tag, tag) for tag in tag_forbids if tag != '']
|
tag_forbids = [qualname_map.get(tag, tag) for tag in tag_forbids if tag != '']
|
||||||
|
|
||||||
|
# AUTHOR
|
||||||
|
authors = request.args.get('author', None)
|
||||||
|
if authors:
|
||||||
|
authors = authors.split(',')
|
||||||
|
authors = [a.strip() for a in authors]
|
||||||
|
authors = [P.get_user(username=a) for a in authors]
|
||||||
|
else:
|
||||||
|
authors = None
|
||||||
|
|
||||||
# ORDERBY
|
# ORDERBY
|
||||||
orderby = request.args.get('orderby', None)
|
orderby = request.args.get('orderby', None)
|
||||||
if orderby:
|
if orderby:
|
||||||
|
@ -430,11 +439,11 @@ def get_search_core():
|
||||||
orderby = None
|
orderby = None
|
||||||
|
|
||||||
# HAS_TAGS
|
# HAS_TAGS
|
||||||
has_tags = request.args.get('has_tags', '')
|
has_tags = request.args.get('has_tags', None)
|
||||||
if has_tags == '':
|
if has_tags:
|
||||||
has_tags = None
|
|
||||||
else:
|
|
||||||
has_tags = helpers.truthystring(has_tags)
|
has_tags = helpers.truthystring(has_tags)
|
||||||
|
else:
|
||||||
|
has_tags = None
|
||||||
|
|
||||||
# MINMAXERS
|
# MINMAXERS
|
||||||
area = request.args.get('area', None)
|
area = request.args.get('area', None)
|
||||||
|
@ -454,6 +463,7 @@ def get_search_core():
|
||||||
'bytes': bytes,
|
'bytes': bytes,
|
||||||
'duration': duration,
|
'duration': duration,
|
||||||
|
|
||||||
|
'authors': authors,
|
||||||
'created': created,
|
'created': created,
|
||||||
'extension': extension_list,
|
'extension': extension_list,
|
||||||
'extension_not': extension_not_list,
|
'extension_not': extension_not_list,
|
||||||
|
|
|
@ -38,7 +38,7 @@ def photo(p, include_albums=True, include_tags=True):
|
||||||
'has_thumbnail': bool(p.thumbnail),
|
'has_thumbnail': bool(p.thumbnail),
|
||||||
'created': p.created,
|
'created': p.created,
|
||||||
'filename': p.basename,
|
'filename': p.basename,
|
||||||
'mimetype': p.mimetype(),
|
'mimetype': p.mimetype,
|
||||||
}
|
}
|
||||||
if include_albums:
|
if include_albums:
|
||||||
j['albums'] = [album(a, minimal=True) for a in p.albums()]
|
j['albums'] = [album(a, minimal=True) for a in p.albums()]
|
||||||
|
|
17
objects.py
17
objects.py
|
@ -300,6 +300,8 @@ class Photo(ObjectBase):
|
||||||
self.ratio = row_tuple['ratio']
|
self.ratio = row_tuple['ratio']
|
||||||
self.thumbnail = row_tuple['thumbnail']
|
self.thumbnail = row_tuple['thumbnail']
|
||||||
|
|
||||||
|
self.mimetype = helpers.get_mimetype(self.real_filepath)
|
||||||
|
|
||||||
def __reinit__(self):
|
def __reinit__(self):
|
||||||
'''
|
'''
|
||||||
Reload the row from the database and do __init__ with them.
|
Reload the row from the database and do __init__ with them.
|
||||||
|
@ -392,8 +394,7 @@ class Photo(ObjectBase):
|
||||||
hopeful_filepath = self.make_thumbnail_filepath()
|
hopeful_filepath = self.make_thumbnail_filepath()
|
||||||
return_filepath = None
|
return_filepath = None
|
||||||
|
|
||||||
mime = self.mimetype()
|
if self.mimetype == 'image':
|
||||||
if mime == 'image':
|
|
||||||
self.photodb.log.debug('Thumbnailing %s' % self.real_filepath)
|
self.photodb.log.debug('Thumbnailing %s' % self.real_filepath)
|
||||||
try:
|
try:
|
||||||
image = PIL.Image.open(self.real_filepath)
|
image = PIL.Image.open(self.real_filepath)
|
||||||
|
@ -413,7 +414,7 @@ class Photo(ObjectBase):
|
||||||
image.save(hopeful_filepath, quality=50)
|
image.save(hopeful_filepath, quality=50)
|
||||||
return_filepath = hopeful_filepath
|
return_filepath = hopeful_filepath
|
||||||
|
|
||||||
elif mime == 'video' and constants.ffmpeg:
|
elif self.mimetype == 'video' and constants.ffmpeg:
|
||||||
#print('video')
|
#print('video')
|
||||||
probe = constants.ffmpeg.probe(self.real_filepath)
|
probe = constants.ffmpeg.probe(self.real_filepath)
|
||||||
try:
|
try:
|
||||||
|
@ -495,9 +496,6 @@ class Photo(ObjectBase):
|
||||||
hopeful_filepath = os.path.join(folder, basename) + '.jpg'
|
hopeful_filepath = os.path.join(folder, basename) + '.jpg'
|
||||||
return hopeful_filepath
|
return hopeful_filepath
|
||||||
|
|
||||||
def mimetype(self):
|
|
||||||
return helpers.get_mimetype(self.real_filepath)
|
|
||||||
|
|
||||||
@decorators.time_me
|
@decorators.time_me
|
||||||
def reload_metadata(self, *, commit=True):
|
def reload_metadata(self, *, commit=True):
|
||||||
'''
|
'''
|
||||||
|
@ -510,8 +508,7 @@ class Photo(ObjectBase):
|
||||||
self.ratio = None
|
self.ratio = None
|
||||||
self.duration = None
|
self.duration = None
|
||||||
|
|
||||||
mime = self.mimetype()
|
if self.mimetype == 'image':
|
||||||
if mime == 'image':
|
|
||||||
try:
|
try:
|
||||||
image = PIL.Image.open(self.real_filepath)
|
image = PIL.Image.open(self.real_filepath)
|
||||||
except (OSError, ValueError):
|
except (OSError, ValueError):
|
||||||
|
@ -521,7 +518,7 @@ class Photo(ObjectBase):
|
||||||
image.close()
|
image.close()
|
||||||
self.photodb.log.debug('Loaded image data for {photo:r}'.format(photo=self))
|
self.photodb.log.debug('Loaded image data for {photo:r}'.format(photo=self))
|
||||||
|
|
||||||
elif mime == 'video' and constants.ffmpeg:
|
elif self.mimetype == 'video' and constants.ffmpeg:
|
||||||
try:
|
try:
|
||||||
probe = constants.ffmpeg.probe(self.real_filepath)
|
probe = constants.ffmpeg.probe(self.real_filepath)
|
||||||
if probe and probe.video:
|
if probe and probe.video:
|
||||||
|
@ -531,7 +528,7 @@ class Photo(ObjectBase):
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
elif mime == 'audio':
|
elif self.mimetype == 'audio':
|
||||||
try:
|
try:
|
||||||
probe = constants.ffmpeg.probe(self.real_filepath)
|
probe = constants.ffmpeg.probe(self.real_filepath)
|
||||||
if probe and probe.audio:
|
if probe and probe.audio:
|
||||||
|
|
|
@ -452,6 +452,8 @@ class PDBPhotoMixin:
|
||||||
elif author is not None:
|
elif author is not None:
|
||||||
# Just to confirm
|
# Just to confirm
|
||||||
author_id = self.get_user(id=author).id
|
author_id = self.get_user(id=author).id
|
||||||
|
else:
|
||||||
|
author_id = None
|
||||||
|
|
||||||
extension = os.path.splitext(filename)[1]
|
extension = os.path.splitext(filename)[1]
|
||||||
extension = extension.replace('.', '')
|
extension = extension.replace('.', '')
|
||||||
|
@ -524,6 +526,7 @@ class PDBPhotoMixin:
|
||||||
bytes=None,
|
bytes=None,
|
||||||
duration=None,
|
duration=None,
|
||||||
|
|
||||||
|
authors=None,
|
||||||
created=None,
|
created=None,
|
||||||
extension=None,
|
extension=None,
|
||||||
extension_not=None,
|
extension_not=None,
|
||||||
|
@ -541,11 +544,14 @@ class PDBPhotoMixin:
|
||||||
orderby=None
|
orderby=None
|
||||||
):
|
):
|
||||||
'''
|
'''
|
||||||
PHOTO PROPERTISE
|
PHOTO PROPERTIES
|
||||||
area, width, height, ratio, bytes, duration:
|
area, width, height, ratio, bytes, duration:
|
||||||
A hyphen_range string representing min and max. Or just a number for lower bound.
|
A hyphen_range string representing min and max. Or just a number for lower bound.
|
||||||
|
|
||||||
TAGS AND FILTERS
|
TAGS AND FILTERS
|
||||||
|
authors:
|
||||||
|
A list of User object or users IDs.
|
||||||
|
|
||||||
created:
|
created:
|
||||||
A hyphen_range string respresenting min and max. Or just a number for lower bound.
|
A hyphen_range string respresenting min and max. Or just a number for lower bound.
|
||||||
|
|
||||||
|
@ -615,6 +621,11 @@ class PDBPhotoMixin:
|
||||||
extension_not = helpers._normalize_extensions(extension_not)
|
extension_not = helpers._normalize_extensions(extension_not)
|
||||||
mimetype = helpers._normalize_extensions(mimetype)
|
mimetype = helpers._normalize_extensions(mimetype)
|
||||||
|
|
||||||
|
if authors is not None:
|
||||||
|
if isinstance(authors, str):
|
||||||
|
authors = {authors, }
|
||||||
|
authors = set(a.id if isinstance(a, objects.User) else a for a in authors)
|
||||||
|
|
||||||
if filename is not None:
|
if filename is not None:
|
||||||
if not isinstance(filename, str):
|
if not isinstance(filename, str):
|
||||||
filename = ' '.join(filename)
|
filename = ' '.join(filename)
|
||||||
|
@ -669,10 +680,13 @@ class PDBPhotoMixin:
|
||||||
#print('Failed extension_not')
|
#print('Failed extension_not')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if mimetype and photo.mimetype() not in mimetype:
|
if mimetype and photo.mimetype not in mimetype:
|
||||||
#print('Failed mimetype')
|
#print('Failed mimetype')
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if authors and photo.author_id not in authors:
|
||||||
|
continue
|
||||||
|
|
||||||
if filename and not _helper_filenamefilter(subject=photo.basename, terms=filename):
|
if filename and not _helper_filenamefilter(subject=photo.basename, terms=filename):
|
||||||
#print('Failed filename')
|
#print('Failed filename')
|
||||||
continue
|
continue
|
||||||
|
|
Binary file not shown.
|
@ -154,6 +154,10 @@ li
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
.photo_card_grid_filename
|
||||||
|
{
|
||||||
|
word-break:break-word;
|
||||||
|
}
|
||||||
.photo_card_grid_tags
|
.photo_card_grid_tags
|
||||||
{
|
{
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
@ -195,8 +199,3 @@ li
|
||||||
{
|
{
|
||||||
background-color: #faa;
|
background-color: #faa;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: 'Highlander';
|
|
||||||
src: url('/static/Highlander_Normal.ttf');
|
|
||||||
}
|
|
|
@ -47,12 +47,12 @@ p
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% set photos = album.photos() %}
|
||||||
<span>
|
<span>
|
||||||
Download:
|
Download:
|
||||||
<a href="/album/{{album.id}}.zip?recursive=no">These files</a>
|
{% if photos %}<a href="/album/{{album.id}}.zip?recursive=no">These files</a>{% endif %}
|
||||||
{% if sub_albums %} | <a href="/album/{{album.id}}.zip?recursive=yes">Include children</a>{% endif %}
|
{% if sub_albums %}<a href="/album/{{album.id}}.zip?recursive=yes">Include children</a>{% endif %}
|
||||||
</span>
|
</span>
|
||||||
{% set photos = album.photos() %}
|
|
||||||
{% if photos %}
|
{% if photos %}
|
||||||
<h3>Photos</h3>
|
<h3>Photos</h3>
|
||||||
<ul>
|
<ul>
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
<script src="/static/common.js"></script>
|
<script src="/static/common.js"></script>
|
||||||
{% set filename = photo.id + "." + photo.extension %}
|
{% set filename = photo.id + "." + photo.extension %}
|
||||||
{% set link = "/file/" + filename %}
|
{% set link = "/file/" + filename %}
|
||||||
{% set mimetype=photo.mimetype() %}
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
#content_body
|
#content_body
|
||||||
|
@ -21,6 +20,7 @@
|
||||||
#left
|
#left
|
||||||
{
|
{
|
||||||
display: flex;
|
display: flex;
|
||||||
|
padding: 8px;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
background-color: rgba(0, 0, 0, 0.1);
|
background-color: rgba(0, 0, 0, 0.1);
|
||||||
|
@ -117,10 +117,10 @@
|
||||||
{% if photo.width %}
|
{% if photo.width %}
|
||||||
<li>Dimensions: {{photo.width}}x{{photo.height}} px</li>
|
<li>Dimensions: {{photo.width}}x{{photo.height}} px</li>
|
||||||
<li>Aspect ratio: {{photo.ratio}}</li>
|
<li>Aspect ratio: {{photo.ratio}}</li>
|
||||||
<li>Size: {{photo.bytestring()}}</li>
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
<li>Size: {{photo.bytestring()}}</li>
|
||||||
{% if photo.duration %}
|
{% if photo.duration %}
|
||||||
<li>Duration: {{photo.duration_str}}</li>
|
<li>Duration: {{photo.duration_string()}}</li>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<li><a href="/file/{{photo.id}}.{{photo.extension}}?download=1">Download as {{photo.id}}.{{photo.extension}}</a></li>
|
<li><a href="/file/{{photo.id}}.{{photo.extension}}?download=1">Download as {{photo.id}}.{{photo.extension}}</a></li>
|
||||||
<li><a href="/file/{{photo.id}}.{{photo.extension}}?download=1&original_filename=1">Download as "{{photo.basename}}"</a></li>
|
<li><a href="/file/{{photo.id}}.{{photo.extension}}?download=1&original_filename=1">Download as "{{photo.basename}}"</a></li>
|
||||||
|
@ -144,12 +144,12 @@
|
||||||
<div id="right">
|
<div id="right">
|
||||||
<!-- THE PHOTO ITSELF -->
|
<!-- THE PHOTO ITSELF -->
|
||||||
<div class="photo_viewer">
|
<div class="photo_viewer">
|
||||||
{% if mimetype == "image" %}
|
{% if photo.mimetype == "image" %}
|
||||||
<div id="photo_img_holder"><img id="photo_img" src="{{link}}" onclick="toggle_hoverzoom()" onload="this.style.opacity=0.99"></div>
|
<div id="photo_img_holder"><img id="photo_img" src="{{link}}" onclick="toggle_hoverzoom()" onload="this.style.opacity=0.99"></div>
|
||||||
<!-- <img src="{{link}}"> -->
|
<!-- <img src="{{link}}"> -->
|
||||||
{% elif mimetype == "video" %}
|
{% elif photo.mimetype == "video" %}
|
||||||
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
|
<video src="{{link}}" controls preload=none {%if photo.thumbnail%}poster="/thumbnail/{{photo.id}}.jpg"{%endif%}></video>
|
||||||
{% elif mimetype == "audio" %}
|
{% elif photo.mimetype == "audio" %}
|
||||||
<audio src="{{link}}" controls></audio>
|
<audio src="{{link}}" controls></audio>
|
||||||
{% else %}
|
{% else %}
|
||||||
<a href="{{link}}">View {{filename}}</a>
|
<a href="{{link}}">View {{filename}}</a>
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="photo_card_grid_info">
|
<div class="photo_card_grid_info">
|
||||||
<a target="_blank" href="/photo/{{photo.id}}" style="word-break:break-all">{{photo.basename}}</a>
|
<a target="_blank" class="photo_card_grid_filename" href="/photo/{{photo.id}}">{{photo.basename}}</a>
|
||||||
<span class="photo_card_grid_file_metadata">
|
<span class="photo_card_grid_file_metadata">
|
||||||
{% if photo.width %}
|
{% if photo.width %}
|
||||||
{{photo.width}}x{{photo.height}},
|
{{photo.width}}x{{photo.height}},
|
||||||
|
|
|
@ -33,7 +33,7 @@ form
|
||||||
#left, #right
|
#left, #right
|
||||||
{
|
{
|
||||||
/* Keep the prev-next buttons from scraping the floor */
|
/* Keep the prev-next buttons from scraping the floor */
|
||||||
padding-bottom: 30px;
|
/*padding-bottom: 30px;*/
|
||||||
}
|
}
|
||||||
#left
|
#left
|
||||||
{
|
{
|
||||||
|
@ -44,26 +44,27 @@ form
|
||||||
#right
|
#right
|
||||||
{
|
{
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
padding: 8px;
|
||||||
width: auto;
|
width: auto;
|
||||||
}
|
}
|
||||||
.prev_next_holder
|
.prev_next_holder
|
||||||
{
|
{
|
||||||
/* Makes div match size of content */
|
display: flex;
|
||||||
overflow: auto;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.prev_page
|
.prev_page
|
||||||
{
|
{
|
||||||
float: left;
|
margin-right: 10px;
|
||||||
}
|
}
|
||||||
.next_page
|
.next_page
|
||||||
{
|
{
|
||||||
float: right;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
.prev_page, .next_page
|
.prev_page, .next_page
|
||||||
{
|
{
|
||||||
display: inline-block;
|
flex: 1;
|
||||||
width: 48%;
|
display: flex;
|
||||||
height: auto;
|
justify-content: center;
|
||||||
background-color: #ffffd4;
|
background-color: #ffffd4;
|
||||||
font-size: 20;
|
font-size: 20;
|
||||||
border: 1px solid black;
|
border: 1px solid black;
|
||||||
|
@ -79,7 +80,6 @@ form
|
||||||
{% macro prev_next_buttons() %}
|
{% macro prev_next_buttons() %}
|
||||||
{% if prev_page_url or next_page_url %}
|
{% if prev_page_url or next_page_url %}
|
||||||
<div class="prev_next_holder">
|
<div class="prev_next_holder">
|
||||||
<center>
|
|
||||||
{% if prev_page_url %}
|
{% if prev_page_url %}
|
||||||
<a class="prev_page" href="{{prev_page_url}}">Previous</a>
|
<a class="prev_page" href="{{prev_page_url}}">Previous</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
|
@ -90,7 +90,6 @@ form
|
||||||
{% else %}
|
{% else %}
|
||||||
<a class="next_page"><br></a>
|
<a class="next_page"><br></a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</center>
|
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
@ -238,11 +237,14 @@ form
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<div id="right">
|
<div id="right">
|
||||||
<p>You got {{photos|length}} items</p><br>
|
<p>You got {{photos|length}} items</p>
|
||||||
{{prev_next_buttons()}}
|
{{prev_next_buttons()}}
|
||||||
|
<div id="search_results_holder">
|
||||||
{% for photo in photos %}
|
{% for photo in photos %}
|
||||||
{{photo_card.create_photo_card(photo, view=search_kwargs["view"])}}
|
{{photo_card.create_photo_card(photo, view=search_kwargs["view"])}}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
{{prev_next_buttons()}}
|
{{prev_next_buttons()}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,6 +29,7 @@ body
|
||||||
right: 8px;
|
right: 8px;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
top: 30px;
|
top: 30px;
|
||||||
|
padding: 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
Loading…
Reference in a new issue