shelterapiv02.py 8.6 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
#-*- coding: utf-8 -*-

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

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

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

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

23
import conf, os.path
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
30
31
32
33
34
def tree():
    return defaultdict(tree)

@apiv02_bp.route('/', methods=['GET'])
def apimessage():
    message = tree()
    message["API version"] = 0.2
    message["Message"] = "This is the development API"
35
    defaultjson()
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
    result = tree()
    
    subquery = db.session.query(Translation.language_code).group_by(Translation.language_code).subquery()
84
    available_languages = db.session.query(func.array_agg(subquery.c.language_code)).first()
85
86
87
    #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
152
153
    
    
    picpath = os.path.relpath(conf.SHELTERS_PICTURES_PATH)
Aron Gergely's avatar
Aron Gergely committed
154
155
156
157
158
159
160
161
162
163
164
    
    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)
    
165
    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
166
167
    		.join(Category, Category.id == ShelterPicture.category_id)		
    
168
    catquery = db.session.query(Category.name).filter(Category.section_id != None)
169
    
Aron Gergely's avatar
Aron Gergely committed
170
171
172
173
174
175
176
    ##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)
177
    
Aron Gergely's avatar
Aron Gergely committed
178
179
180
181
182
183
184
185
186
187
    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)
188
    
Aron Gergely's avatar
Aron Gergely committed
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
    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)
210
211
212
213
214
215
216
217
218
    
    
    for shelter_property in shelter_properties:
    	if not result[shelter_property.shelter_id]:
    		for category in catquery:
    			if category.name == "Identification":
    				result[shelter_property.shelter_id][category.name]["Cover"]
    			result[shelter_property.shelter_id][category.name]["Attributes"]
    			result[shelter_property.shelter_id][category.name]["Pictures"]
Aron Gergely's avatar
Aron Gergely committed
219
    	
220
221
222
    	if request.args.get('format') == 'prettytext':
    		result[shelter_property.shelter_id][shelter_property.supercategory_name]["Attributes"][shelter_property.name] = shelter_property.value
    	else:
223
    		result[shelter_property.shelter_id][shelter_property.supercategory_name]["Attributes"][shelter_property.uniqueid] = shelter_property.value
Aron Gergely's avatar
Aron Gergely committed
224
    
225
226
227
228
229
230
231
232
    
    for picture in shelter_pictures:
    	if picture.is_main_picture == True:
    		result[picture.shelter_id]["Identification"]["Cover"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
    	elif not result[picture.shelter_id][picture.name]["Pictures"]:
    		result[picture.shelter_id][picture.name]["Pictures"] = ["{}/{}/{}".format(picpath, picture.shelter_id, picture.filename)]
    	else:
    		result[picture.shelter_id][picture.name]["Pictures"].append("{}/{}/{}".format(picpath, picture.shelter_id, picture.filename))
Aron Gergely's avatar
Aron Gergely committed
233
  
234
    return jsonify(result)