Stefano Cossu 6 лет назад
Родитель
Сommit
4090e51570

+ 36 - 6
lakesuperior/endpoints/query.py

@@ -1,4 +1,8 @@
-from flask import Blueprint, request
+from flask import Blueprint, request, render_template
+from rdflib.plugin import PluginException
+
+from lakesuperior.dictionaries.namespaces import ns_mgr as nsm
+from lakesuperior.query import QueryEngine
 
 # Query endpoint. raw SPARQL queries exposing the underlying layout can be made
 # available. Also convenience methods that allow simple lookups based on simple
@@ -14,7 +18,13 @@ def find():
     '''
     Search by entering a search term and optional property and comparison term.
     '''
-    valid_operands = ('=', '>', '<', '<>')
+    valid_operands = (
+        ('=', 'Equals'),
+        ('>', 'Greater Than'),
+        ('<', 'Less Than'),
+        ('<>', 'Not Equal'),
+        ('a', 'RDF Type'),
+    )
 
     term = request.args.get('term')
     prop = request.args.get('prop', default=1)
@@ -22,12 +32,32 @@ def find():
     # @TODO
 
 
-@query.route('/sparql', methods=['POST'])
-def sparql(q):
+@query.route('/sparql', methods=['GET', 'POST'])
+def sparql():
     '''
     Perform a direct SPARQL query on the underlying triplestore.
 
     @param q SPARQL query string.
     '''
-    # @TODO
-    pass
+    accept_mimetypes = {
+        'text/csv': 'csv',
+        'application/sparql-results+json': 'json',
+        'application/sparql-results+xml': 'xml',
+    }
+    if request.method == 'GET':
+        return render_template('sparql_query.html', nsm=nsm)
+    else:
+        qres = QueryEngine().sparql_query(request.form['query'])
+        match = request.accept_mimetypes.best_match(accept_mimetypes.keys())
+        if match:
+            enc = accept_mimetypes[match]
+        else:
+            enc = request.accept_mimetypes.best
+
+        try:
+            out = qres.serialize(format=enc)
+        except PluginException:
+            return ('Unable to serialize results into format {}'.format(enc),
+                    406)
+
+    return out, 200

+ 43 - 9
lakesuperior/endpoints/templates/base.html

@@ -1,21 +1,55 @@
 <!doctype html>
 <html>
     <head>
-        {% block head %}
-            <meta charset="utf-8">
-            <meta http-equiv="X-UA-Compatible" content="IE=edge">
-            <meta name="viewport" content="width=device-width, initial-scale=1">
+    {% block head %}
+        <meta charset="utf-8">
+        <meta http-equiv="X-UA-Compatible" content="IE=edge">
+        <meta name="viewport" content="width=device-width, initial-scale=1">
 
-            <title>{% block title %}{% endblock %} :: LAKEsuperior</title>
+        <title>{% block title %}{% endblock %} :: LAKEsuperior</title>
 
-            <link href="{{url_for('ldp.static', filename='assets/css/bootstrap.min.css')}}" rel="stylesheet">
-        {% endblock %}
+        <link href="{{url_for('ldp.static', filename='assets/css/bootstrap.min.css')}}" rel="stylesheet">
+        <link href="{{url_for('ldp.static', filename='assets/css/bootstrap-theme.min.css')}}" rel="stylesheet">
+    {% endblock %}
+    {% block extra_js %}{% endblock %}
     </head>
     <body>
-        <div class="container">
+        <nav class="navbar navbar-default">
+          <div class="container-fluid">
+            <!-- Brand and toggle get grouped for better mobile display -->
+            <div class="navbar-header">
+              <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
+                <span class="sr-only">Toggle navigation</span>
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+                <span class="icon-bar"></span>
+              </button>
+              <a class="navbar-brand" href="#">LAKEsuperior</a>
+            </div>
+            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
+              <ul class="nav navbar-nav">
+                <li><a href="/ldp">Browse Resources<span class="sr-only">(current)</span></a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Query<span class="caret"></span></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="/query/term">Term Search</a></li>
+                    <li><a href="/query/sparql">SPARQL Query</a></li>
+                  </ul>
+                </li>
+              </ul>
+              <form class="navbar-form navbar-left">
+                <div class="form-group">
+                  <input type="text" class="form-control" placeholder="Search">
+                </div>
+                <button type="submit" class="btn btn-default">Submit</button>
+              </form>
+            </div><!-- /.navbar-collapse -->
+          </div><!-- /.container-fluid -->
+        </nav>
+        <main class="container">
             <h1>{{ self.title() }}</h1>
             {% block content %}{% endblock %}
-        </div>
+        </main>
         <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
         <script src="{{url_for('ldp.static', filename='assets/js/jquery-3.2.1.min.js')}}"></script>
         <!-- Include all compiled plugins (below), or include individual files as needed -->

+ 2 - 5
lakesuperior/endpoints/templates/index.html

@@ -1,8 +1,5 @@
 {% extends 'base.html' %}
-{% block title %}LAKEsuperior :: Homepage{% endblock %}
+{% block title %}LAKEsuperior{% endblock %}
 {% block content %}
-    <ul>
-        <li><a href='/ldp'>LDP REST endpoint</a></li>
-        <li><a href='/query'>Query endpoint</a></li>
-    </ul>
+<p>That&lsquo;s it for the home page.</p>
 {% endblock %}

+ 25 - 0
lakesuperior/endpoints/templates/namespaces.html

@@ -0,0 +1,25 @@
+<h2>Namespaces</h2>
+ <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#nslist" aria-expanded="false" aria-controls="nsList">
+    Expand/Collapse
+</button>
+<div class="collapse" id="nslist">
+    <div class="card card-body">
+        <table class="table table-striped">
+            <thead>
+                <tr>
+                    <td>Prefix</td>
+                    <td>URI</td>
+                </tr>
+            </thead>
+            <tbody>
+            {% for ns in nsm.namespaces() | sort %}
+                <tr>
+                    <td>{{ ns[0] }}</td>
+                    <td>{{ ns[1] }}</td>
+                </tr>
+            {% endfor %}
+            </tbody>
+        </table>
+    </div>
+</div>
+

+ 27 - 24
lakesuperior/endpoints/templates/resource.html

@@ -1,30 +1,6 @@
 {% extends 'base.html' %}
 {% block title %}{{ rsrc.identifier }}{% endblock %}
 {% block content %}
-<h2>Namespaces</h2>
- <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#nslist" aria-expanded="false" aria-controls="nsList">
-    Expand/Collapse
-</button>
-<div class="collapse" id="nslist">
-    <div class="card card-body">
-        <table class="table table-striped">
-            <thead>
-                <tr>
-                    <td>Prefix</td>
-                    <td>URI</td>
-                </tr>
-            </thead>
-            <tbody>
-            {% for ns in nsm.namespaces() | sort %}
-                <tr>
-                    <td>{{ ns[0] }}</td>
-                    <td>{{ ns[1] }}</td>
-                </tr>
-            {% endfor %}
-            </tbody>
-        </table>
-    </div>
-</div>
 <h2>Resource</h2>
 <table class="table table-striped">
     <thead>
@@ -69,4 +45,31 @@
     {% endfor %}
     </tbody>
 </table>
+{% block namespaces %}
+            <h2>Namespaces</h2>
+             <button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#nslist" aria-expanded="false" aria-controls="nsList">
+                Expand/Collapse
+            </button>
+            <div class="collapse" id="nslist">
+                <div class="card card-body">
+                    <table class="table table-striped">
+                        <thead>
+                            <tr>
+                                <td>Prefix</td>
+                                <td>URI</td>
+                            </tr>
+                        </thead>
+                        <tbody>
+                        {% for ns in nsm.namespaces() | sort %}
+                            <tr>
+                                <td>{{ ns[0] }}</td>
+                                <td>{{ ns[1] }}</td>
+                            </tr>
+                        {% endfor %}
+                        </tbody>
+                    </table>
+                </div>
+            </div>
+
+{% endblock %}
 {% endblock %}

+ 16 - 0
lakesuperior/endpoints/templates/sparql_query.html

@@ -0,0 +1,16 @@
+{% extends 'base.html' %}
+{% block extra_js %}
+<link href="{{url_for('ldp.static', filename='assets/css/yasgui.min.css')}}" rel="stylesheet" type='text/css'/>
+<script src="{{url_for('ldp.static', filename='assets/js/yasgui.min.js')}}"></script>
+{% endblock %}
+{% block title %}SPARQL Query{% endblock %}
+{% block content %}
+<div id="sparql_ui"></div>
+<script type="text/javascript">
+    var yasgui = YASGUI(document.getElementById("sparql_ui"), {
+        catalogueEndpoints: [{endpoint: '{{url_for('query.sparql')}}'}],
+        endpoint: '{{url_for('query.sparql')}}',
+        tracker: {}
+    });
+</script>
+{% endblock %}

+ 17 - 0
lakesuperior/query.py

@@ -0,0 +1,17 @@
+from flask import current_app, g
+
+from lakesuperior.dictionaries.namespaces import ns_collection as nsc
+from lakesuperior.dictionaries.namespaces import ns_mgr as nsm
+
+class QueryEngine:
+    '''
+    Handle both simple term-based and full-fledged SPARQL queries.
+    '''
+
+    def sparql_query(self, qry):
+        '''
+        Send a SPARQL query to the triplestore.
+
+        The returned value may be different.
+        '''
+        return current_app.rdfly.raw_query(qry)

+ 7 - 0
lakesuperior/store_layouts/ldp_rs/rsrc_centric_layout.py

@@ -214,6 +214,13 @@ class RsrcCentricLayout:
         return self._parse_construct(qry, init_bindings=bindings)
 
 
+    def raw_query(self, qry_str):
+        '''
+        Perform a straight query to the graph store.
+        '''
+        return self.ds.query(qry_str)
+
+
     def extract_imr(
                 self, uid, ver_uid=None, strict=True, incl_inbound=False,
                 incl_children=True, embed_children=False, **kwargs):

Разница между файлами не показана из-за своего большого размера
+ 7 - 0
static/assets/css/yasgui.min.css


Разница между файлами не показана из-за своего большого размера
+ 0 - 0
static/assets/js/yasgui.min.js


Некоторые файлы не были показаны из-за большого количества измененных файлов