tagging on import
parent
6765425be5
commit
4f10129c5a
|
@ -72,7 +72,7 @@ class PhotosApiV1(object):
|
|||
ext = get_extension(file.filename)
|
||||
assert ext in known_extensions
|
||||
photo_path = generate_storage_path(photo_date, photo_meta['hash'][0:8], ext)
|
||||
|
||||
# shouldn't we just trust the database?
|
||||
if self.library.storage.exists(photo_path):
|
||||
return abort_upload(f"file already in library: {photo_path}")
|
||||
|
||||
|
@ -84,7 +84,7 @@ class PhotosApiV1(object):
|
|||
|
||||
# misc input validation
|
||||
# also if sha doesn't match uploaded metadata, abort
|
||||
# todo don't use asserts
|
||||
# TODO don't use asserts
|
||||
try:
|
||||
assert shasum == photo_meta["hash"], "uploaded file didn't match provided sha"
|
||||
|
||||
|
@ -130,8 +130,14 @@ class PhotosApiV1(object):
|
|||
lat=Decimal(meta["lat"]) if meta["lat"] else None,
|
||||
lon=Decimal(meta["lon"]) if meta["lon"] else None,
|
||||
files=photo_objs) # TODO support title field et
|
||||
|
||||
db.add(ps)
|
||||
|
||||
for tag_name in meta["tags"]:
|
||||
tag = db.query(Tag).filter(Tag.name == tag_name).first()
|
||||
assert tag, "unknown tag name"
|
||||
db.add(TagItem(tag_id=tag.id, set=ps))
|
||||
|
||||
ps_json = ps.to_json() # we do this now to avoid a sqlalchemy bug where the object disappears after the commit
|
||||
|
||||
try:
|
||||
|
@ -211,7 +217,7 @@ class PhotosApiV1(object):
|
|||
@cherrypy.expose
|
||||
@cherrypy.tools.json_out()
|
||||
@cherrypy.popargs("uuid")
|
||||
def tags(self, uuid=None, page=0, pagesize=50):
|
||||
def tags(self, uuid=None, name=None, page=0, pagesize=50):
|
||||
if cherrypy.request.method == "POST": # creating tag
|
||||
tagdata = json.loads(cherrypy.request.body.read())
|
||||
tagname = tagdata.get("name")
|
||||
|
@ -228,12 +234,17 @@ class PhotosApiV1(object):
|
|||
db.delete(tag)
|
||||
db.commit()
|
||||
return {}
|
||||
elif uuid: # getting tag
|
||||
t = db.query(Tag).filter(Tag.uuid == uuid).first()
|
||||
elif uuid or name: # getting tag
|
||||
q = db.query(Tag)
|
||||
if uuid:
|
||||
q = q.filter(Tag.uuid == uuid)
|
||||
if name:
|
||||
q = q.filter(Tag.name == name)
|
||||
t = q.first()
|
||||
if not t:
|
||||
cherrypy.response.status = 404
|
||||
return {"error": "not found"}
|
||||
return t.to_json()
|
||||
return [t.to_json()]
|
||||
else: # getting all tags
|
||||
page, pagesize = int(page), int(pagesize)
|
||||
return [t.to_json() for t in
|
||||
|
|
|
@ -4,7 +4,7 @@ import argparse
|
|||
import requests
|
||||
from requests.exceptions import HTTPError
|
||||
from photoapp.utils import get_extension
|
||||
from photoapp.types import known_extensions, PhotoStatus
|
||||
from photoapp.types import known_extensions, PhotoStatus, Tag
|
||||
from photoapp.common import pwhash
|
||||
from photoapp.ingest import get_photosets
|
||||
from urllib.parse import urlparse
|
||||
|
@ -93,8 +93,11 @@ class PhotoApiClient(object):
|
|||
def create_tag(self, name, title, description):
|
||||
return self.post("tags", json={"name": name, "title": title, "description": description})
|
||||
|
||||
def list_tags(self):
|
||||
return self.get("tags")
|
||||
def list_tags(self, name):
|
||||
params = {}
|
||||
if name:
|
||||
params["name"] = name
|
||||
return self.get("tags", params=params)
|
||||
|
||||
# def delete_user(self, username):
|
||||
# return self.delete("user", params={"username": username})
|
||||
|
@ -143,6 +146,7 @@ def get_args():
|
|||
p_ingest = sp_action.add_parser("ingest", help="import images into the library")
|
||||
p_ingest.add_argument("-c", "--copy-of", help="existing uuid the imported images will be placed under")
|
||||
p_ingest.add_argument("-w", "--workers", default=1, type=int, help="number of parallel uploads")
|
||||
p_ingest.add_argument("-t", "--tag", help="tag name to apply to the import")
|
||||
p_ingest.add_argument("files", nargs="+", help="files to import")
|
||||
|
||||
sp_action.add_parser("stats", help="show library statistics")
|
||||
|
@ -161,7 +165,8 @@ def get_args():
|
|||
p_create.add_argument("-t", "--title")
|
||||
p_create.add_argument("-d", "--description")
|
||||
|
||||
p_tagaction.add_parser('list', help='list tags')
|
||||
p_tag_list = p_tagaction.add_parser('list', help='list tags')
|
||||
p_tag_list.add_argument("-n", "--name", help="tag name to lookup")
|
||||
|
||||
p_delete = p_tagaction.add_parser('delete', help='delete tags')
|
||||
p_delete.add_argument("-n", "--name", required=True)
|
||||
|
@ -228,6 +233,16 @@ def main():
|
|||
raise
|
||||
|
||||
elif args.action == "ingest":
|
||||
tag = None
|
||||
if args.tag:
|
||||
tag = args.tag.lower()
|
||||
try:
|
||||
client.list_tags(name=tag).json()
|
||||
except requests.exceptions.HTTPError as he:
|
||||
if he.response.status_code != 404:
|
||||
raise
|
||||
client.create_tag(tag, tag, "")
|
||||
|
||||
sets, skipped = get_photosets(args.files)
|
||||
|
||||
rows = []
|
||||
|
@ -255,6 +270,13 @@ def main():
|
|||
|
||||
def upload_set(set_):
|
||||
payload = set_.to_json()
|
||||
|
||||
# add tags to set
|
||||
if args.tag:
|
||||
# it's kinda cheap to do this in json instead of building out the PhotoSet data structure
|
||||
# but trust me it's worth it
|
||||
payload["tags"] = [tag]
|
||||
|
||||
payload["files"] = {os.path.basename(photo.path): photo.to_json() for photo in set_.files}
|
||||
|
||||
files = []
|
||||
|
@ -334,7 +356,7 @@ def main():
|
|||
client.create_tag(args.name, args.title, args.description)
|
||||
elif args.action_tag == "list":
|
||||
rows = []
|
||||
for tag in client.list_tags().json():
|
||||
for tag in client.list_tags(name=args.name).json():
|
||||
rows.append([tag["name"], tag["title"], maybetruncate(tag["description"], 24), tag["uuid"]])
|
||||
print(tabulate(rows, headers=["name", "title", "description", "uuid"]))
|
||||
|
||||
|
|
Loading…
Reference in New Issue