Ajout modele derive CsvDataSource, sans i18n + formulaires
This commit is contained in:
parent
a5e7b9b549
commit
e5101a8513
|
@ -0,0 +1,77 @@
|
|||
# passerelle - uniform access to multiple data sources and services
|
||||
# Copyright (C) 2016 Entr'ouvert
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Affero General Public License as published
|
||||
# by the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django import forms
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from .models import Query, get_code, identifier_re
|
||||
|
||||
|
||||
class QueryForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Query
|
||||
widgets = {
|
||||
'resource': forms.HiddenInput(),
|
||||
'filters': forms.Textarea(attrs={'rows': 2}),
|
||||
'projections': forms.Textarea(attrs={'rows': 2}),
|
||||
'order': forms.Textarea(attrs={'rows': 2}),
|
||||
'distinct': forms.Textarea(attrs={'rows': 2}),
|
||||
}
|
||||
fields = '__all__'
|
||||
|
||||
def clean_lines_of_expressions(self, lines, named=False):
|
||||
if not lines:
|
||||
return lines
|
||||
errors = []
|
||||
for i, line in enumerate(lines.splitlines()):
|
||||
if named:
|
||||
line = line.split(':', 1)
|
||||
if len(line) != 2:
|
||||
errors.append(ValidationError(
|
||||
_('Syntax error line %d: each line must be prefixed '
|
||||
'with an identifier followed by a colon.') % (i + 1)))
|
||||
continue
|
||||
name, line = line
|
||||
if not identifier_re.match(name):
|
||||
errors.append(
|
||||
ValidationError(_('Syntax error line %d: invalid identifier, '
|
||||
'it must starts with a letter and only '
|
||||
'contains letters, digits and _.') % (i + 1)))
|
||||
continue
|
||||
try:
|
||||
get_code(line)
|
||||
except SyntaxError as e:
|
||||
errors.append(ValidationError(
|
||||
_('Syntax error line %(line)d at character %(character)d') % {
|
||||
'line': i + 1,
|
||||
'character': e.offset
|
||||
}))
|
||||
if errors:
|
||||
raise ValidationError(errors)
|
||||
return lines
|
||||
|
||||
def clean_filters(self):
|
||||
return self.clean_lines_of_expressions(self.data.get('filters'))
|
||||
|
||||
def clean_projections(self):
|
||||
return self.clean_lines_of_expressions(self.data.get('projections'), named=True)
|
||||
|
||||
def clean_order(self):
|
||||
return self.clean_lines_of_expressions(self.data.get('order'))
|
||||
|
||||
def clean_distinct(self):
|
||||
return self.clean_lines_of_expressions(self.data.get('distinct'))
|
|
@ -53,3 +53,35 @@ class LDAPResource(BaseResource):
|
|||
@classmethod
|
||||
def is_enabled(cls):
|
||||
return True
|
||||
|
||||
class Query(models.Model):
|
||||
resource = models.ForeignKey('LDAPResource')
|
||||
slug = models.SlugField('Name (slug)')
|
||||
label = models.CharField('Label', max_length=100)
|
||||
description = models.TextField('Description', blank=True)
|
||||
filters = models.TextField('Filters', blank=True,
|
||||
help_text='List of filter clauses (Python expression)')
|
||||
projections = models.TextField('Projections', blank=True,
|
||||
help_text='List of projections (name:expression)')
|
||||
order = models.TextField('Order', blank=True,
|
||||
help_text='Ordering columns')
|
||||
distinct = models.TextField('Distinct', blank=True,
|
||||
help_text='Distinct columns')
|
||||
structure = models.CharField('Structure',
|
||||
max_length=20,
|
||||
choices=[
|
||||
('array', 'Array'),
|
||||
('dict', 'Dictionary'),
|
||||
('tuples', 'Tuples'),
|
||||
('onerow', 'Single Row'),
|
||||
('one', 'Single Value')],
|
||||
default='dict',
|
||||
help_text='Data structure used for the response')
|
||||
|
||||
class Meta:
|
||||
ordering = ['slug']
|
||||
|
||||
def get_list(self, attribute):
|
||||
if not getattr(self, attribute):
|
||||
return []
|
||||
return getattr(self, attribute).strip().splitlines()
|
||||
|
|
Reference in New Issue