Commit 8f24c0b4 authored by Administrator's avatar Administrator

Merge branch 'mat-master' of ssh://delanoe.org:1979/gargantext into mat-master

parents f94ea5ac 68f66271
...@@ -10,7 +10,7 @@ from sqlalchemy import text, distinct ...@@ -10,7 +10,7 @@ from sqlalchemy import text, distinct
from sqlalchemy.sql import func from sqlalchemy.sql import func
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from gargantext_web.sqla import * from gargantext_web.db import *
def DebugHttpResponse(data): def DebugHttpResponse(data):
......
...@@ -2,18 +2,21 @@ from node import models ...@@ -2,18 +2,21 @@ from node import models
from gargantext_web import settings from gargantext_web import settings
Language = models.Language.sa __all__ = ['literalquery', 'session', 'cache']
Metadata = models.Metadata.sa
Ngram = models.Ngram.sa
Node = models.Node.sa
Node_Metadata = models.Node_Metadata.sa
NodeNgram = Node_Ngram = models.Node_Ngram.sa
NodeNodeNgram = models.NodeNgramNgram.sa
NodeType = models.NodeType.sa
Resource = models.Resource.sa
ResourceType = models.ResourceType.sa
# map the Django models found in node.models to SQLAlchemy models
for model_name, model in models.__dict__.items():
if hasattr(model, 'sa'):
globals()[model_name] = model.sa
__all__.append(model_name)
NodeNgram = Node_Ngram
# debugging tool, to translate SQLAlchemy queries to string
def literalquery(statement, dialect=None): def literalquery(statement, dialect=None):
"""Generate an SQL expression string with bound parameters rendered inline """Generate an SQL expression string with bound parameters rendered inline
for the given SQLAlchemy statement. for the given SQLAlchemy statement.
...@@ -55,6 +58,9 @@ def literalquery(statement, dialect=None): ...@@ -55,6 +58,9 @@ def literalquery(statement, dialect=None):
return LiteralCompiler(dialect, statement) return LiteralCompiler(dialect, statement)
# SQLAlchemy session management
def get_sessionmaker(): def get_sessionmaker():
from django.db import connections from django.db import connections
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
...@@ -67,6 +73,57 @@ def get_sessionmaker(): ...@@ -67,6 +73,57 @@ def get_sessionmaker():
engine = create_engine(url, use_native_hstore=True) engine = create_engine(url, use_native_hstore=True)
return sessionmaker(bind=engine) return sessionmaker(bind=engine)
Session = get_sessionmaker() Session = get_sessionmaker()
session = Session() session = Session()
# SQLAlchemy model objects caching
from sqlalchemy import or_
class ModelCache(dict):
def __init__(self, model, preload=False):
self._model = model.sa
self._columns_names = [column.name for column in model._meta.fields if column.unique]
self._columns = [getattr(self._model, column_name) for column_name in self._columns_names]
self._columns_validators = []
if preload:
self.preload()
def __missing__(self, key):
for column in self._columns:
conditions = []
try:
formatted_key = column.type.python_type(key)
conditions.append(column == key)
except ValueError:
pass
if formatted_key in self:
self[key] = self[formatted_key]
else:
element = session.query(self._model).filter(or_(*conditions)).first()
if element is None:
raise KeyError
self[key] = element
return element
def preload(self):
self.clear()
for element in session.query(self._model).all():
for column_name in self._columns_names:
key = getattr(element, column_name)
self[key] = element
class Cache:
def __getattr__(self, key):
try:
model = getattr(models, key)
except AttributeError:
raise AttributeError('No such model: `%s`' % key)
modelcache = ModelCache(model)
setattr(self, key, modelcache)
return modelcache
cache = Cache()
...@@ -29,15 +29,15 @@ def _upload_to(instance, filename): ...@@ -29,15 +29,15 @@ def _upload_to(instance, filename):
class Language(models.Model): class Language(models.Model):
iso2 = models.CharField(max_length=2, unique=True) iso2 = models.CharField(max_length=2, unique=True)
iso3 = models.CharField(max_length=3) iso3 = models.CharField(max_length=3, unique=True)
fullname = models.CharField(max_length=255) fullname = models.CharField(max_length=255, unique=True)
implemented = models.BooleanField(blank=True) implemented = models.BooleanField(blank=True)
def __str__(self): def __str__(self):
return self.fullname return self.fullname
class ResourceType(models.Model): class ResourceType(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255, unique=True)
def __str__(self): def __str__(self):
return self.name return self.name
...@@ -45,7 +45,7 @@ class ResourceType(models.Model): ...@@ -45,7 +45,7 @@ class ResourceType(models.Model):
class Ngram(models.Model): class Ngram(models.Model):
language = models.ForeignKey(Language, blank=True, null=True, on_delete=models.SET_NULL) language = models.ForeignKey(Language, blank=True, null=True, on_delete=models.SET_NULL)
n = models.IntegerField() n = models.IntegerField()
terms = models.CharField(max_length=255) terms = models.CharField(max_length=255, unique=True)
nodes = models.ManyToManyField(through='Node_Ngram', to='Node') nodes = models.ManyToManyField(through='Node_Ngram', to='Node')
def __str__(self): def __str__(self):
...@@ -62,7 +62,7 @@ class Resource(models.Model): ...@@ -62,7 +62,7 @@ class Resource(models.Model):
return self.file return self.file
class NodeType(models.Model): class NodeType(models.Model):
name = models.CharField(max_length=200) name = models.CharField(max_length=200, unique=True)
def __str__(self): def __str__(self):
return self.name return self.name
......
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
var operators = {
'string': [
{'label': 'starts with', 'key': 'startswith'},
{'label': 'contains', 'key': 'contains'},
{'label': 'ends with', 'key': 'endswith'},
{'label': 'is', 'key': '='},
{'label': 'is before', 'key': '<'},
{'label': 'is after', 'key': '>'}
],
'integer': [
{'label': 'is', 'key': '='},
{'label': 'is lower than', 'key': '<'},
{'label': 'is higher than', 'key': '>'}
],
'float': [
{'label': 'is', 'key': '='},
{'label': 'is lower than', 'key': '<'},
{'label': 'is higher than', 'key': '>'}
],
'datetime': [
{'label': 'is', 'key': '='},
{'label': 'is before', 'key': '<'},
{'label': 'is after', 'key': '>'}
],
};
var MetadataList = Backbone.Model.extend({
urlRoot: '/api/nodes/(:/nodeId)/children/metadata',
defaults: function() {
return {
key: '',
type: 'string',
values: null,
};
}
});
var Filter = Backbone.Model.extend({
defaults: function() {
return {
entity: null,
key: null,
transformation: null,
operator: null,
value: null
};
}
});
var FilterList = Backbone.Collection.extend({
model: Filter
});
var FilterView = Backbone.View.extend({
tagName: 'li',
className: 'filter',
template: _.template($('#filter-template').html()),
events: {
'change select[name=entity]': 'changeEntity',
'click button.remove': 'clear'
},
initialize: function(){
// this.model.bind('reset', this.render);
// this.model.bind('change', this.render);
// this.model.bind('destroy', this.clear);
// this.render();
},
changeEntity: function(){
alert('CHANGE')
},
render: function() {
// this.$el.html(this.template(this.model.toJSON()));
this.$el.html(this.template({}));
return this;
},
clear: function() {
// alert('CLEAR');
// this.model.invoke('destroy');
this.model.destroy();
}
});
var FilterListView = Backbone.View.extend({
tagName: 'div',
className: 'filters',
template: _.template($('#filterlist-template').html()),
events: {
'click button.add': 'addOne'
},
initialize: function(parameters) {
this.filterList = new FilterList();
this.metadataList = new MetadataList({nodeId: parameters.nodeId});
console.log(this.metadataList.fetch({nodeId: parameters.nodeId}))
this.listenTo(this.filterList, 'add', this.addOne);
this.listenTo(this.filterList, 'reset', this.addAll);
this.listenTo(this.filterList, 'all', this.render);
},
render: function() {
// render template
var rendered = this.$el.html(this.template({}));
// return the object
return this;
},
addOne: function(filter){
var view = new FilterView({model: filter});
this.$('ul.filters').append(
view.render(filter).$el
);
}
});
var operators = {
'string': [
{'label': 'starts with', 'key': 'startswith'},
{'label': 'contains', 'key': 'contains'},
{'label': 'ends with', 'key': 'endswith'},
{'label': 'is', 'key': '='},
{'label': 'is before', 'key': '<'},
{'label': 'is after', 'key': '>'}
],
'integer': [
{'label': 'is', 'key': '='},
{'label': 'is lower than', 'key': '<'},
{'label': 'is higher than', 'key': '>'}
],
'float': [
{'label': 'is', 'key': '='},
{'label': 'is lower than', 'key': '<'},
{'label': 'is higher than', 'key': '>'}
],
'datetime': [
{'label': 'is', 'key': '='},
{'label': 'is before', 'key': '<'},
{'label': 'is after', 'key': '>'}
],
};
// MODELS
var Metadata = can.Model({
findAll: 'GET /api/nodes/{parent}/children/metadata'
});
var QueriedNodeList = can.Model({
findAll: 'POST /api/nodes/{parent}/children/queries'
});
var Filter = can.Model({
findAll: function(){
return $.Deferred().resolve([]);
},
findOne: function(){
return $.Deferred().resolve(undefined);
},
update: function(){
return $.Deferred().resolve();
},
destroy: function(){
return $.Deferred().resolve();
}
}, {});
// CONTROLLERS
var FilterController = can.Control.extend({
'init': function(element, options){
this.element = element;
Filter.findAll({}, function(filter){
element.append(
$(can.view('FilterView', {filter: filter}))
);
});
this.element.find('li select[name=entity]').each(function() {
$(this).change();
});
},
'li select[name=entity] change': 'changeEntity',
'changeEntity': function(element, event){
var entityName = this.element.find('select[name=entity]').val();
element.closest('li')
.find('span.entity').hide()
.filter('.' + entityName).show();
// alert(value);
}
});
var FilterListController = can.Control.extend({
'init': function(element, options){
this.element = element.html( can.view('FilterListView', options) );
// Filter.findAll({}, function(filters){
// var el = this.element;
// el.html( can.view('filterView', {filters: filters}) )
// });
// metadata = Metadata.findAll(parameters);
},
'button.create click': function(){
var filterController = new FilterController(
this.element.find('ul.filters')
);
},
'filter': function(filter){
this.options.filter = filter;
this.on();
},
'{filter} destroyed': function(){
this.element.hide();
}
});
// var Query = can.Model({
// 'init' : function(parameters) {
// }
// });
This diff is collapsed.
This diff is collapsed.
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</span> </span>
<span ng-if="filter.entity.key == 'ngrams'"> <span ng-if="filter.entity.key == 'ngrams'">
are in this list: are in this list:
<tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true"> <tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true" replace-spaces-with-dashes="false">
<auto-complete source="getNgrams($query)"></auto-complete> <auto-complete source="getNgrams($query)"></auto-complete>
</tags-input ng-model="tags"> </tags-input ng-model="tags">
</span> </span>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment