shelterapiv02.py 8.74 KB
Newer Older
Maarten van der Veen's avatar
Maarten van der Veen committed
1
#! /usr/bin/env python
Aron Gergely's avatar
Aron Gergely committed
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#-*- coding: utf-8 -*-

# ***** BEGIN LICENSE BLOCK *****

#
#
# ***** END LICENSE BLOCK *****

__author__ = ""
__version__ = ""
__date__ = ""
__revision__ = ""
__copyright__ = ""
__license__ = ""

#from bootstrap import db
18
from bootstrap import db, app
Aron Gergely's avatar
Aron Gergely committed
19
from sqlalchemy.sql import func, select
20
from flask import Blueprint, jsonify, request, json, Response
Aron Gergely's avatar
Aron Gergely committed
21
from collections import defaultdict
22
from web.models import Shelter, Attribute, Property, Value, Association, ShelterPicture, Category, Tsvector, Translation
Aron Gergely's avatar
Aron Gergely committed
23

Aron Gergely's avatar
Aron Gergely committed
24

Aron Gergely's avatar
Aron Gergely committed
25
apiv02_bp = Blueprint('development api v0.2', __name__, url_prefix='/api/v0.2')
26

Aron Gergely's avatar
Aron Gergely committed
27
28
29
def tree():
    return defaultdict(tree)

Aron Gergely's avatar
Aron Gergely committed
30

Aron Gergely's avatar
Aron Gergely committed
31
32
33
34
35
@apiv02_bp.route('/', methods=['GET'])
def apimessage():
    message = tree()
    message["API version"] = 0.2
    message["Message"] = "This is the development API"
36
    return jsonify(message)
Aron Gergely's avatar
Aron Gergely committed
37

Aron Gergely's avatar
Aron Gergely committed
38
39
40
41
42
43
44
45
46
@apiv02_bp.route('/documentation', methods=['GET'])
def documentation():
    """
    Retrieves this documentation in JSON format
    
    NOT IMPLEMENTED
    """
    return "hm"

47
48
@apiv02_bp.route('/worldmap', methods=['GET'])
def worldmap():
Aron Gergely's avatar
Aron Gergely committed
49
50
51
52
	"""
	Retrieve a world map in GeoJSON format, 
	with polygons and a centroid point representing each country
	"""
53
	
54
	with app.open_resource('static/data/countries.geojson') as f:
55
		data = json.load(f, encoding='utf-8')
56
	return Response(json.dumps(data), mimetype='application/json;charset=utf-8')
57
58
	#return app.send_static_file('data/world_borders.geojson')
	
Aron Gergely's avatar
Aron Gergely committed
59
60
@apiv02_bp.route('/attributes/<attribute_name>', methods=['GET'])
def getattributes(attribute_name, safetext=False):
Aron Gergely's avatar
Aron Gergely committed
61
62
63
64
65
66
67
    """
    Retrieve available values for a given `attribute_name` 
    separated by semicolons
    
    :param attribute_name: uniqueid of an attribute name
    :type language_code: string
    """
Aron Gergely's avatar
Aron Gergely committed
68
69
70
71
    result= tree()
    
    attributes = Attribute.query.filter(Attribute.uniqueid==attribute_name).\
                                first().associated_values
72
    
Aron Gergely's avatar
Aron Gergely committed
73
74
75
    result[attribute_name] = ";".join([attribute.name for attribute in attributes])
    return jsonify(result)

76
77
@apiv02_bp.route('/translation', methods=['GET'])
def available_translations():
Aron Gergely's avatar
Aron Gergely committed
78
79
80
    """
    Retrieve language codes of available translations 
    """
81
82
83
84
85
86
87
    result = tree()
    
    subquery = db.session.query(Translation.language_code).group_by(Translation.language_code).subquery()
    available_languages = db.session.query(func.string_agg(subquery.c.language_code, ';')).first()
    #for language in available_languages
    result["languages"]= available_languages[0]
	
88
    return Response(json.dumps(result, indent=3), mimetype='application/json;charset=utf-8')
89
90


Aron Gergely's avatar
Aron Gergely committed
91
92
93
94
95
96
97
98
@apiv02_bp.route('/translation/<language_code>', methods=['GET'])
def translations(language_code=None):
    """
    Retrieve translations for a given `language_code`
    
    :param language_code: language code 
    :type language_code: string
    """
99
100
    result = tree()

Aron Gergely's avatar
Aron Gergely committed
101
    query = Translation.query.filter(Translation.language_code==language_code)
102
103
104
    phrases = query	
    for phrase in phrases:
    	result[phrase.original]=phrase.translated
105
106
107
    	
    return Response(json.dumps(result, indent=3), mimetype='application/json;charset=utf-8')
    	
Aron Gergely's avatar
Aron Gergely committed
108
109
110
@apiv02_bp.route('/shelters', methods=['GET'])
@apiv02_bp.route('/shelters/<int:shelter_id>', methods=['GET'])
def allshelters(shelter_id=None):
Aron Gergely's avatar
Aron Gergely committed
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    """
    Retrieves shelters with all their attributes and pictures.
    
     **Example requests**:
     
     .. sourcecode:: html
         
         # get all shelters
         GET http://0.0.0.0:5000/api/v0.2/shelters
         
         # get shelter whith shelter ID 11
         GET http://0.0.0.0:5000/api/v0.2/shelters/11
         
         # get all shelters which have attribute 'storeys' 
         GET http://0.0.0.0:5000/api/v0.2/shelters?attribute=storeys
         
         # get all shelters which have 2 storeys
         GET http://0.0.0.0:5000/api/v0.2/shelters?attribute=storeys&value=2
            
    
    :param shelter_id: a unique shelter ID generated by the server 
    :type shelter_id: int
    
    :query format: 
        if set to ``prettytext``, 
        attribute names are retrieved as nicely formatted text 
        (Capital letters, special characters and spaces allowed)
    
    :query attribute:
        attribute name
    
    :query value: 
       attribute value
    
    :query q: 
        Full text search. Works in English language only. 
    """
Aron Gergely's avatar
Aron Gergely committed
148
149
150
    result = tree()
    
    #shelter pictures folder path
151
    picpath = '/public/shelters/pictures'
Aron Gergely's avatar
Aron Gergely committed
152
153
154
155
156
157
158
159
160
161
162
    
    Supercategory = db.aliased(Category)
    
    querybase = db.session.query(Property.shelter_id, Category.name.label("category_name"), Supercategory.name.label("supercategory_name"), Attribute.name, Attribute.uniqueid,func.string_agg(Value.name,';').label("value"))\
    		.join(Category, Category.id==Property.category_id)\
    		.join(Attribute, Attribute.id==Property.attribute_id)\
    		.join(Supercategory, Supercategory.id==Category.parent_id)\
    		.join(Association, Property.id==Association.property_id)\
    		.join(Value, Association.value_id==Value.id)\
    		.group_by(Property.shelter_id, Supercategory.name, Category.name, Attribute.name, Attribute.uniqueid)
    
163
    picquerybase = db.session.query(ShelterPicture.shelter_id, ShelterPicture.file_name.label("filename"), ShelterPicture.is_main_picture, Category.name)\
Aron Gergely's avatar
Aron Gergely committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
    		.join(Category, Category.id == ShelterPicture.category_id)		
    
    ##queries if no request arguments
    shelter_properties = querybase
    shelter_pictures = picquerybase
        	
    if shelter_id:
    	shelter_properties = shelter_properties.filter(Property.shelter_id==shelter_id)
    	shelter_pictures = shelter_pictures.filter(ShelterPicture.shelter_id==shelter_id)

    if request.args.getlist('attribute'):
    	attribute = request.args.getlist('attribute')	
    	
    	subquery = db.session.query(Property.shelter_id)\
    			.join(Attribute, Attribute.id==Property.attribute_id)\
    			.filter(Attribute.uniqueid.in_(attribute))\
    			.group_by(Property.shelter_id)
    			
    	shelter_properties = shelter_properties.filter(subquery.subquery().c.shelter_id==Property.shelter_id)
    	shelter_pictures = shelter_pictures.filter(subquery.subquery().c.shelter_id==ShelterPicture.shelter_id)

    if request.args.getlist('value'):
    	value = request.args.getlist('value')
    	if not request.args.getlist('attribute'):
    		subquery = db.session.query(Property.shelter_id)\
    			.join(Attribute, Attribute.id==Property.attribute_id)\
    			.filter(Property.values.any(Value.name.in_(value)))\
    			.group_by(Property.shelter_id)
    	else:
    		subquery = subquery.filter(Property.values.any(Value.name.in_(value)))
    	
    	shelter_properties = shelter_properties.filter(subquery.subquery().c.shelter_id==Property.shelter_id)
    	shelter_pictures = shelter_pictures.filter(subquery.subquery().c.shelter_id==ShelterPicture.shelter_id)
    
    if request.args.get('q'):
    	attribute = request.args.get('q')
    	
    	shelter_properties = shelter_properties.join(Tsvector, Property.shelter_id==Tsvector.shelter_id).filter(Tsvector.lexeme.match(attribute))
    	shelter_pictures = shelter_pictures.join(Tsvector, ShelterPicture.shelter_id==Tsvector.shelter_id).filter(Tsvector.lexeme.match(attribute))

    #print(shelter_properties)
    #print(shelter_pictures)
    
    if request.args.get('format') == 'prettytext':
    	for shelter_property in shelter_properties:
209
    		result[shelter_property.shelter_id][shelter_property.supercategory_name]["Attributes"][shelter_property.name] = shelter_property.value
Aron Gergely's avatar
Aron Gergely committed
210
211
    	
    	for picture in shelter_pictures:
212
    		if picture.is_main_picture == True:
213
    			result[picture.shelter_id]["Identification"]["Cover"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
214
    		elif not result[picture.shelter_id][picture.name]["Pictures"]:
215
    			result[picture.shelter_id][picture.name]["Pictures"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
Aron Gergely's avatar
Aron Gergely committed
216
    		else:
217
    			result[picture.shelter_id][picture.name]["Pictures"].append("{}/{}/{}".format(picpath, picture.shelter_id, picture.filename))
Aron Gergely's avatar
Aron Gergely committed
218
219
220
    
    else:
    	for shelter_property in shelter_properties:
221
    		result[shelter_property.shelter_id][shelter_property.supercategory_name]["Attributes"][shelter_property.uniqueid] = shelter_property.value
Aron Gergely's avatar
Aron Gergely committed
222
223
    
    	for picture in shelter_pictures:
224
    		if picture.is_main_picture == True:
225
    			result[picture.shelter_id]["Identification"]["Cover"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
226
    		elif not result[picture.shelter_id][picture.name]["Pictures"]:
227
    			result[picture.shelter_id][picture.name]["Pictures"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
Aron Gergely's avatar
Aron Gergely committed
228
    		else:
229
    			result[picture.shelter_id][picture.name]["Pictures"].append("{}/{}/{}".format(picpath, picture.shelter_id, picture.filename))
Aron Gergely's avatar
Aron Gergely committed
230
  
231
    return jsonify(result)