Commit e29bb514e1a967ba48fa48df9bdae25fd7be94bd

Authored by janek37
1 parent 85716dbc

zmiana formatowania, poprawka do dodawania zakończeń, ostrzeganie przed zamknięciem

Showing 189 changed files with 53113 additions and 37346 deletions

Too many changes to show.

To preserve performance only 44 of 189 files are displayed.

accounts/ajax.py
... ... @@ -4,19 +4,21 @@ from django.contrib.auth.models import User, Group
4 4 from common.decorators import ajax
5 5 from dictionary.models import Vocabulary
6 6  
  7 +
7 8 @ajax(method='post')
8 9 def set_group(request, user_id, group_id, set):
9   - user = User.objects.get(pk=user_id)
10   - group = Group.objects.get(pk=group_id)
11   - if set:
12   - user.groups.add(group)
13   - else:
14   - user.groups.remove(group)
15   - return {}
  10 + user = User.objects.get(pk=user_id)
  11 + group = Group.objects.get(pk=group_id)
  12 + if set:
  13 + user.groups.add(group)
  14 + else:
  15 + user.groups.remove(group)
  16 + return {}
  17 +
16 18  
17 19 @ajax(method='post')
18 20 def save_default_owner(request, vocab_id):
19   - us = request.user.usersettings
20   - us.default_owner = Vocabulary.objects.get(pk=vocab_id)
21   - us.save()
22   - return {}
  21 + us = request.user.usersettings
  22 + us.default_owner = Vocabulary.objects.get(pk=vocab_id)
  23 + us.save()
  24 + return {}
... ...
accounts/forms.py
... ... @@ -3,35 +3,38 @@
3 3 import random
4 4 import string
5 5 from django.forms import *
6   -from django.utils.translation import ugettext_lazy as _
7 6 from django.contrib.auth.forms import PasswordResetForm
8 7 from django.contrib.auth.models import User
9 8 from accounts.models import UserSettings
10 9  
  10 +
11 11 class AddUserForm(ModelForm):
12   - def save(self, commit=True, request=None):
13   - user = super(AddUserForm, self).save(commit=False)
14   - password = ''.join(random.choice(string.printable) for i in range(32))
15   - user.set_password(password)
16   - if commit:
17   - user.save()
18   - fakeform = PasswordResetForm(data={'email': user.email})
19   - if fakeform.is_valid(): # oczywiście, że jest
20   - fakeform.save(request=request)
21   - UserSettings.objects.create(user=user)
22   - user.groups.add(*self.cleaned_data['groups'])
23   - return user
24   - class Meta:
25   - model = User
26   - fields = ['username', 'first_name', 'last_name', 'email', 'groups']
  12 + def save(self, commit=True, request=None):
  13 + user = super(AddUserForm, self).save(commit=False)
  14 + password = ''.join(random.choice(string.printable) for i in range(32))
  15 + user.set_password(password)
  16 + if commit:
  17 + user.save()
  18 + fakeform = PasswordResetForm(data={'email': user.email})
  19 + if fakeform.is_valid(): # oczywiście, że jest
  20 + fakeform.save(request=request)
  21 + UserSettings.objects.create(user=user)
  22 + user.groups.add(*self.cleaned_data['groups'])
  23 + return user
  24 +
  25 + class Meta:
  26 + model = User
  27 + fields = ['username', 'first_name', 'last_name', 'email', 'groups']
  28 +
27 29  
28 30 class SettingsForm(ModelForm):
29   - def __init__(self, vocabularies=None, **kwargs):
30   - super(SettingsForm, self).__init__(**kwargs)
31   - if vocabularies:
32   - self.fields['default_owner'].queryset = vocabularies
33   - else:
34   - self.fields['default_owner'].widget = HiddenInput()
35   - class Meta:
36   - model = UserSettings
37   - fields = ['incremental_search', 'filter_search', 'default_owner']
  31 + def __init__(self, vocabularies=None, **kwargs):
  32 + super(SettingsForm, self).__init__(**kwargs)
  33 + if vocabularies:
  34 + self.fields['default_owner'].queryset = vocabularies
  35 + else:
  36 + self.fields['default_owner'].widget = HiddenInput()
  37 +
  38 + class Meta:
  39 + model = UserSettings
  40 + fields = ['incremental_search', 'filter_search', 'default_owner']
... ...
accounts/management/commands/create_groups.py
1 1 #-*- coding:utf-8 -*-
2 2  
3 3 from django.contrib.auth.models import Permission, Group
4   -from django.core.management.base import BaseCommand, CommandError
  4 +from django.core.management.base import BaseCommand
  5 +
5 6  
6 7 class Command(BaseCommand):
7   - args = 'none'
8   - help = 'Creates default groups'
  8 + args = 'none'
  9 + help = 'Creates default groups'
9 10  
10   - def handle(self, **options):
11   - create_groups()
  11 + def handle(self, **options):
  12 + create_groups()
12 13  
13 14  
14 15 def get_permission(codename):
15   - return Permission.objects.get(codename=codename)
  16 + return Permission.objects.get(codename=codename)
  17 +
16 18  
17 19 def create_groups():
18   - Group.objects.all().delete()
19   - observers = Group.objects.create(name=u'Obserwator')
20   - lexicographers = Group.objects.create(name=u'Leksykograf')
21   - superlexicographers = Group.objects.create(name=u'Superleksykograf')
22   - patternmakers = Group.objects.create(name=u'Wzorzysta')
23   - managers = Group.objects.create(name=u'Wydawca')
24   - admins = Group.objects.create(name=u'Administrator')
25   -
26   - observers.permissions.add(get_permission('view_lexeme'))
27   - #observers.permissions.add(get_permission('add_comment'))
28   - observers.permissions.add(get_permission('view_pattern'))
29   - lexicographers.permissions.add(get_permission('view_lexeme'))
30   - lexicographers.permissions.add(get_permission('change_lexeme'))
31   - lexicographers.permissions.add(get_permission('export_lexemes'))
32   - lexicographers.permissions.add(get_permission('view_pattern'))
33   - superlexicographers.permissions.add(get_permission('view_lexeme'))
34   - superlexicographers.permissions.add(get_permission('change_lexeme'))
35   - superlexicographers.permissions.add(get_permission('export_lexemes'))
36   - superlexicographers.permissions.add(get_permission('lexeme_priority'))
37   - superlexicographers.permissions.add(get_permission('view_pattern'))
38   - # może dokonywać zmian w Banku błędów
39   - # może dokonywać zmian w zakładce Etykiety
40   - patternmakers.permissions.add(get_permission('view_pattern'))
41   - patternmakers.permissions.add(get_permission('change_pattern'))
42   - managers.permissions.add(get_permission('manage_vocabulary'))
43   - managers.permissions.add(get_permission('view_lexeme'))
44   - managers.permissions.add(get_permission('view_all_lexemes'))
45   - managers.permissions.add(get_permission('view_pattern'))
46   - managers.permissions.add(get_permission('add_user'))
47   - managers.permissions.add(get_permission('export_lexemes'))
48   - # zarządzanie rolami użytkowników:
49   - managers.permissions.add(get_permission('change_group'))
50   - admins.permissions.add(get_permission('add_user'))
51   - admins.permissions.add(get_permission('change_group'))
52   - admins.permissions.add(get_permission('create_admin'))
53   - admins.permissions.add(get_permission('manage_vocabulary'))
54   - admins.permissions.add(get_permission('manage_all_vocabularies'))
  20 + Group.objects.all().delete()
  21 + observers = Group.objects.create(name=u'Obserwator')
  22 + lexicographers = Group.objects.create(name=u'Leksykograf')
  23 + superlexicographers = Group.objects.create(name=u'Superleksykograf')
  24 + patternmakers = Group.objects.create(name=u'Wzorzysta')
  25 + managers = Group.objects.create(name=u'Wydawca')
  26 + admins = Group.objects.create(name=u'Administrator')
  27 +
  28 + observers.permissions.add(get_permission('view_lexeme'))
  29 + #observers.permissions.add(get_permission('add_comment'))
  30 + observers.permissions.add(get_permission('view_pattern'))
  31 + lexicographers.permissions.add(get_permission('view_lexeme'))
  32 + lexicographers.permissions.add(get_permission('change_lexeme'))
  33 + lexicographers.permissions.add(get_permission('export_lexemes'))
  34 + lexicographers.permissions.add(get_permission('view_pattern'))
  35 + superlexicographers.permissions.add(get_permission('view_lexeme'))
  36 + superlexicographers.permissions.add(get_permission('change_lexeme'))
  37 + superlexicographers.permissions.add(get_permission('export_lexemes'))
  38 + superlexicographers.permissions.add(get_permission('lexeme_priority'))
  39 + superlexicographers.permissions.add(get_permission('view_pattern'))
  40 + # może dokonywać zmian w Banku błędów
  41 + # może dokonywać zmian w zakładce Etykiety
  42 + patternmakers.permissions.add(get_permission('view_pattern'))
  43 + patternmakers.permissions.add(get_permission('change_pattern'))
  44 + managers.permissions.add(get_permission('manage_vocabulary'))
  45 + managers.permissions.add(get_permission('view_lexeme'))
  46 + managers.permissions.add(get_permission('view_all_lexemes'))
  47 + managers.permissions.add(get_permission('view_pattern'))
  48 + managers.permissions.add(get_permission('add_user'))
  49 + managers.permissions.add(get_permission('export_lexemes'))
  50 + # zarządzanie rolami użytkowników:
  51 + managers.permissions.add(get_permission('change_group'))
  52 + admins.permissions.add(get_permission('add_user'))
  53 + admins.permissions.add(get_permission('change_group'))
  54 + admins.permissions.add(get_permission('create_admin'))
  55 + admins.permissions.add(get_permission('manage_vocabulary'))
  56 + admins.permissions.add(get_permission('manage_all_vocabularies'))
... ...
accounts/management/commands/create_users.py
... ... @@ -5,92 +5,97 @@ from django.core.management.base import BaseCommand, CommandError
5 5 from dictionary.models import Vocabulary
6 6 from accounts.models import UserSettings
7 7  
  8 +
8 9 class Command(BaseCommand):
9   - args = 'none'
10   - help = 'Creates default users'
  10 + args = 'none'
  11 + help = 'Creates default users'
11 12  
12   - def handle(self, **options):
13   - create_users()
  13 + def handle(self, **options):
  14 + create_users()
14 15  
15 16  
16 17 def create_users():
17   - observers = Group.objects.get(name=u'Obserwator')
18   - lexicographers = Group.objects.get(name=u'Leksykograf')
19   - superlexicographers = Group.objects.get(name=u'Superleksykograf')
20   - patternmakers = Group.objects.get(name=u'Wzorzysta')
21   - managers = Group.objects.get(name=u'Wydawca')
22   - admins = Group.objects.get(name=u'Administrator')
23   -
24   - SGJP = Vocabulary.objects.get(id='SGJP')
25   - SJPDor = Vocabulary.objects.get(id='SJPDor')
26   - zmiotki = Vocabulary.objects.get(id='zmiotki')
27   - try:
28   - WSJP = Vocabulary.objects.get(id='WSJP')
29   - except Vocabulary.DoesNotExist:
30   - WSJP = None
31   - Morfologik, created = Vocabulary.objects.get_or_create(id='Morfologik')
32   - PoliMorf, created = Vocabulary.objects.get_or_create(id='PoliMorf')
33   -
34   - User.objects.all().delete()
35   - sgjp = User.objects.create_user('sgjp', 'sgjp@example.com', 'sgjp')
36   - nzm = User.objects.create_user('nzm', 'nzm@example.com', 'nzm')
37   - redsgjp = User.objects.create_user('redsgjp', 'redsgjp@example.com', 'redsgjp')
38   - rednzm = User.objects.create_user('rednzm', 'rednzm@example.com', 'rednzm')
39   - supersgjp = User.objects.create_user('supersgjp', 'supersgjp@example.com', 'supersgjp')
40   - supernzm = User.objects.create_user('supernzm', 'supernzm@example.com', 'supernzm')
41   - wzornik = User.objects.create_user('wzornik', 'wzornik@example.com', 'wzornik')
42   - admin = User.objects.create_user('admin', 'admin@example.com', 'admin')
43   -
44   - users = (sgjp, nzm, redsgjp, rednzm, supersgjp, supernzm, wzornik, admin)
45   - for user in users:
46   - UserSettings.objects.create(user=user)
47   -
48   - admin.groups.add(admins)
49   -
50   - sgjp_vocabs = (SGJP, SJPDor, zmiotki)
51   - if WSJP: sgjp_vocabs += (WSJP,)
52   - nzm_vocabs = (zmiotki, Morfologik, PoliMorf)
53   -
54   - sgjp.groups.add(managers)
55   - for vocab in sgjp_vocabs:
56   - sgjp.managed_vocabularies.add(vocab)
57   - nzm.groups.add(managers)
58   - for vocab in nzm_vocabs:
59   - nzm.managed_vocabularies.add(vocab)
60   -
61   - redsgjp.groups.add(lexicographers)
62   - for vocab in sgjp_vocabs:
63   - redsgjp.visible_vocabularies.add(vocab)
64   - redsgjp.editable_vocabularies.add(vocab)
65   - redsgjp.visible_vocabularies.add(PoliMorf)
66   -
67   - rednzm.groups.add(lexicographers)
68   - for vocab in nzm_vocabs:
69   - rednzm.visible_vocabularies.add(vocab)
70   - rednzm.editable_vocabularies.add(vocab)
71   - rednzm.visible_vocabularies.add(SGJP)
72   - if WSJP:
73   - rednzm.visible_vocabularies.add(WSJP)
74   - rednzm.visible_vocabularies.add(SJPDor)
75   -
76   - supersgjp.groups.add(superlexicographers)
77   - for vocab in sgjp_vocabs:
78   - supersgjp.visible_vocabularies.add(vocab)
79   - supersgjp.editable_vocabularies.add(vocab)
80   - supersgjp.visible_vocabularies.add(PoliMorf)
81   -
82   - supernzm.groups.add(superlexicographers)
83   - for vocab in nzm_vocabs:
84   - supernzm.visible_vocabularies.add(vocab)
85   - supernzm.editable_vocabularies.add(vocab)
86   - supernzm.visible_vocabularies.add(SGJP)
87   - if WSJP:
88   - supernzm.visible_vocabularies.add(WSJP)
89   - supernzm.visible_vocabularies.add(SJPDor)
90   -
91   - wzornik.groups.add(superlexicographers)
92   - for vocab in sgjp_vocabs:
93   - wzornik.visible_vocabularies.add(vocab)
94   - wzornik.editable_vocabularies.add(vocab)
95   - wzornik.visible_vocabularies.add(PoliMorf)
96   - wzornik.groups.add(patternmakers)
  18 + observers = Group.objects.get(name=u'Obserwator')
  19 + lexicographers = Group.objects.get(name=u'Leksykograf')
  20 + superlexicographers = Group.objects.get(name=u'Superleksykograf')
  21 + patternmakers = Group.objects.get(name=u'Wzorzysta')
  22 + managers = Group.objects.get(name=u'Wydawca')
  23 + admins = Group.objects.get(name=u'Administrator')
  24 +
  25 + SGJP = Vocabulary.objects.get(id='SGJP')
  26 + SJPDor = Vocabulary.objects.get(id='SJPDor')
  27 + zmiotki = Vocabulary.objects.get(id='zmiotki')
  28 + try:
  29 + WSJP = Vocabulary.objects.get(id='WSJP')
  30 + except Vocabulary.DoesNotExist:
  31 + WSJP = None
  32 + Morfologik, created = Vocabulary.objects.get_or_create(id='Morfologik')
  33 + PoliMorf, created = Vocabulary.objects.get_or_create(id='PoliMorf')
  34 +
  35 + User.objects.all().delete()
  36 + sgjp = User.objects.create_user('sgjp', 'sgjp@example.com', 'sgjp')
  37 + nzm = User.objects.create_user('nzm', 'nzm@example.com', 'nzm')
  38 + redsgjp = User.objects.create_user('redsgjp', 'redsgjp@example.com',
  39 + 'redsgjp')
  40 + rednzm = User.objects.create_user('rednzm', 'rednzm@example.com', 'rednzm')
  41 + supersgjp = User.objects.create_user('supersgjp', 'supersgjp@example.com',
  42 + 'supersgjp')
  43 + supernzm = User.objects.create_user('supernzm', 'supernzm@example.com',
  44 + 'supernzm')
  45 + wzornik = User.objects.create_user('wzornik', 'wzornik@example.com',
  46 + 'wzornik')
  47 + admin = User.objects.create_user('admin', 'admin@example.com', 'admin')
  48 +
  49 + users = (sgjp, nzm, redsgjp, rednzm, supersgjp, supernzm, wzornik, admin)
  50 + for user in users:
  51 + UserSettings.objects.create(user=user)
  52 +
  53 + admin.groups.add(admins)
  54 +
  55 + sgjp_vocabs = (SGJP, SJPDor, zmiotki)
  56 + if WSJP: sgjp_vocabs += (WSJP,)
  57 + nzm_vocabs = (zmiotki, Morfologik, PoliMorf)
  58 +
  59 + sgjp.groups.add(managers)
  60 + for vocab in sgjp_vocabs:
  61 + sgjp.managed_vocabularies.add(vocab)
  62 + nzm.groups.add(managers)
  63 + for vocab in nzm_vocabs:
  64 + nzm.managed_vocabularies.add(vocab)
  65 +
  66 + redsgjp.groups.add(lexicographers)
  67 + for vocab in sgjp_vocabs:
  68 + redsgjp.visible_vocabularies.add(vocab)
  69 + redsgjp.editable_vocabularies.add(vocab)
  70 + redsgjp.visible_vocabularies.add(PoliMorf)
  71 +
  72 + rednzm.groups.add(lexicographers)
  73 + for vocab in nzm_vocabs:
  74 + rednzm.visible_vocabularies.add(vocab)
  75 + rednzm.editable_vocabularies.add(vocab)
  76 + rednzm.visible_vocabularies.add(SGJP)
  77 + if WSJP:
  78 + rednzm.visible_vocabularies.add(WSJP)
  79 + rednzm.visible_vocabularies.add(SJPDor)
  80 +
  81 + supersgjp.groups.add(superlexicographers)
  82 + for vocab in sgjp_vocabs:
  83 + supersgjp.visible_vocabularies.add(vocab)
  84 + supersgjp.editable_vocabularies.add(vocab)
  85 + supersgjp.visible_vocabularies.add(PoliMorf)
  86 +
  87 + supernzm.groups.add(superlexicographers)
  88 + for vocab in nzm_vocabs:
  89 + supernzm.visible_vocabularies.add(vocab)
  90 + supernzm.editable_vocabularies.add(vocab)
  91 + supernzm.visible_vocabularies.add(SGJP)
  92 + if WSJP:
  93 + supernzm.visible_vocabularies.add(WSJP)
  94 + supernzm.visible_vocabularies.add(SJPDor)
  95 +
  96 + wzornik.groups.add(superlexicographers)
  97 + for vocab in sgjp_vocabs:
  98 + wzornik.visible_vocabularies.add(vocab)
  99 + wzornik.editable_vocabularies.add(vocab)
  100 + wzornik.visible_vocabularies.add(PoliMorf)
  101 + wzornik.groups.add(patternmakers)
... ...
accounts/management/commands/dummy_passwords.py
... ... @@ -3,15 +3,16 @@
3 3 from django.contrib.auth.models import User
4 4 from django.core.management.base import BaseCommand
5 5  
  6 +
6 7 class Command(BaseCommand):
7   - args = 'none'
8   - help = 'Sets dummy passwords'
  8 + args = 'none'
  9 + help = 'Sets dummy passwords'
9 10  
10   - def handle(self, **options):
11   - dummy_passwords()
  11 + def handle(self, **options):
  12 + dummy_passwords()
12 13  
13 14  
14 15 def dummy_passwords():
15   - for user in User.objects.all():
16   - user.set_password(user.username)
17   - user.save()
18 16 \ No newline at end of file
  17 + for user in User.objects.all():
  18 + user.set_password(user.username)
  19 + user.save()
19 20 \ No newline at end of file
... ...
accounts/models.py
... ... @@ -6,45 +6,48 @@ from dictionary.models import Vocabulary
6 6  
7 7 MANAGER_GROUPS = ('Obserwator', 'Leksykograf', 'Superleksykograf')
8 8  
  9 +
9 10 def manager_groups():
10   - return Group.objects.filter(name__in=MANAGER_GROUPS)
  11 + return Group.objects.filter(name__in=MANAGER_GROUPS)
  12 +
11 13  
12 14 class UserSettings(Model):
13   - user = OneToOneField(User)
14   - incremental_search = BooleanField(
15   - default=True,
16   - verbose_name=u'wyszukiwanie przyrostowe',
17   - help_text=u'Wyszukiwanie odbywa się automatycznie w miarę wpisywania '
18   - u'szukanego hasła. Sugerujemy wyłączenie w wypadku wolnego '
19   - u'połączenia internetowego.')
20   - filter_search = BooleanField(
21   - default=False,
22   - verbose_name=u'wyszukiwanie przez filtrowanie',
23   - help_text=u'Wyszukiwanie powoduje zawężenie listy haseł do pasujących '
24   - u'do zapytania.')
25   - default_owner = ForeignKey(
26   - Vocabulary, blank=True, null=True,
27   - verbose_name=u'domyślny słownik właściciel dodawanych leksemów')
28   -
29   - def views_lexeme(self):
30   - return self.user.has_perm('dictionary.view_lexeme')
31   -
32   - def views_all_lexemes(self):
33   - return self.user.has_perm('dictionary.view_all_lexemes')
34   -
35   - def changes_lexeme(self):
36   - return self.user.has_perm('dictionary.change_lexeme')
37   -
38   - def manages_vocabulary(self):
39   - return self.user.has_perm('dictionary.manage_vocabulary')
40   -
41   - def manages_all_vocabs(self):
42   - return self.user.has_perm('dictionary.manage_all_vocabularies')
43   -
44   - class Meta:
45   - permissions = (
46   - ('create_admin', u'Może nadawać dowolne role'),
47   - )
  15 + user = OneToOneField(User)
  16 + incremental_search = BooleanField(
  17 + default=True,
  18 + verbose_name=u'wyszukiwanie przyrostowe',
  19 + help_text=u'Wyszukiwanie odbywa się automatycznie w miarę wpisywania '
  20 + u'szukanego hasła. Sugerujemy wyłączenie w wypadku wolnego '
  21 + u'połączenia internetowego.')
  22 + filter_search = BooleanField(
  23 + default=False,
  24 + verbose_name=u'wyszukiwanie przez filtrowanie',
  25 + help_text=u'Wyszukiwanie powoduje zawężenie listy haseł do pasujących '
  26 + u'do zapytania.')
  27 + default_owner = ForeignKey(
  28 + Vocabulary, blank=True, null=True,
  29 + verbose_name=u'domyślny słownik właściciel dodawanych leksemów')
  30 +
  31 + def views_lexeme(self):
  32 + return self.user.has_perm('dictionary.view_lexeme')
  33 +
  34 + def views_all_lexemes(self):
  35 + return self.user.has_perm('dictionary.view_all_lexemes')
  36 +
  37 + def changes_lexeme(self):
  38 + return self.user.has_perm('dictionary.change_lexeme')
  39 +
  40 + def manages_vocabulary(self):
  41 + return self.user.has_perm('dictionary.manage_vocabulary')
  42 +
  43 + def manages_all_vocabs(self):
  44 + return self.user.has_perm('dictionary.manage_all_vocabularies')
  45 +
  46 + class Meta:
  47 + permissions = (
  48 + ('create_admin', u'Może nadawać dowolne role'),
  49 + )
  50 +
48 51  
49 52 def filtering_mode(user):
50   - return user.usersettings.filter_search
  53 + return user.usersettings.filter_search
... ...
accounts/templates/manage_groups.html
... ... @@ -2,32 +2,33 @@
2 2 {% load ingroup %}
3 3  
4 4 {% block extrahead %}
5   - <script type="text/javascript" src="{{ MEDIA_URL }}js/manage-groups.js"></script>
  5 + <script type="text/javascript"
  6 + src="{{ MEDIA_URL }}js/manage-groups.js"></script>
6 7 {% endblock %}
7 8  
8 9 {% block title %}Role użytkowników{% endblock %}
9 10  
10 11 {% block content %}
11   - <h3>Role użytkowników</h3>
12   - <table id="user-groups">
13   - <tr>
14   - <th>nazwa</th>
15   - {% for group in groups %}
16   - <th>{{ group.name }}</th>
17   - {% endfor %}
18   - </tr>
19   - {% for u in users %}
20   - <tr>
21   - <td>{{ u.username }}</td>
22   - {% for group in groups %}
23   - <td>
24   - <input
25   - type="checkbox"
26   - id="group-{{ group.pk }}-{{ u.pk }}"
27   - {% if u|ingroup:group %}checked="checked"{% endif %}/>
28   - </td>
  12 + <h3>Role użytkowników</h3>
  13 + <table id="user-groups">
  14 + <tr>
  15 + <th>nazwa</th>
  16 + {% for group in groups %}
  17 + <th>{{ group.name }}</th>
  18 + {% endfor %}
  19 + </tr>
  20 + {% for u in users %}
  21 + <tr>
  22 + <td>{{ u.username }}</td>
  23 + {% for group in groups %}
  24 + <td>
  25 + <input
  26 + type="checkbox"
  27 + id="group-{{ group.pk }}-{{ u.pk }}"
  28 + {% if u|ingroup:group %}checked="checked"{% endif %}/>
  29 + </td>
  30 + {% endfor %}
  31 + </tr>
29 32 {% endfor %}
30   - </tr>
31   - {% endfor %}
32   - </table>
  33 + </table>
33 34 {% endblock %}
... ...
accounts/templates/registration/activate.html
... ... @@ -4,10 +4,11 @@
4 4  
5 5 {% block content %}
6 6  
7   -{% blocktrans %}
8   -<h1>Activation</h1>
9   -<p>Your account is now activated. Go <a href="{% url 'main' %}">here</a> to continue.</p>
  7 + {% blocktrans %}
  8 + <h1>Activation</h1>
  9 + <p>Your account is now activated. Go <a href="{% url 'main' %}">here</a>
  10 + to continue.</p>
10 11  
11   -{% endblocktrans %}
  12 + {% endblocktrans %}
12 13  
13 14 {% endblock %}
... ...
accounts/templates/registration/login.html
... ... @@ -3,32 +3,35 @@
3 3 {% load url from future %}
4 4  
5 5 {% block content %}
6   -{% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %}
7   -<p class="errornote">
8   -{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
9   -</p>
10   -{% endif %}
  6 + {% if form.errors and not form.non_field_errors and not form.this_is_the_login_form.errors %}
  7 + <p class="errornote">
  8 + {% blocktrans count form.errors.items|length as counter %}Please
  9 + correct the error below.{% plural %}Please correct the errors
  10 + below.{% endblocktrans %}
  11 + </p>
  12 + {% endif %}
11 13  
12   -{% if form.non_field_errors or form.this_is_the_login_form.errors %}
13   -{% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %}
14   -<p class="errornote">
15   - {{ error }}
16   -</p>
17   -{% endfor %}
18   -{% endif %}
  14 + {% if form.non_field_errors or form.this_is_the_login_form.errors %}
  15 + {% for error in form.non_field_errors|add:form.this_is_the_login_form.errors %}
  16 + <p class="errornote">
  17 + {{ error }}
  18 + </p>
  19 + {% endfor %}
  20 + {% endif %}
19 21  
20   -<div id="content-main">
21   -<form action="" method="post" id="login-form">{% csrf_token %}
22   - {{ form.as_p }}
23   - <div class="submit-row">
24   - <label>&nbsp;</label><input type="submit" value="{% trans 'Log in' %}" />
25   - </div>
26   -</form>
  22 + <div id="content-main">
  23 + <form action="" method="post" id="login-form">{% csrf_token %}
  24 + {{ form.as_p }}
  25 + <div class="submit-row">
  26 + <label>&nbsp;</label><input type="submit"
  27 + value="{% trans 'Log in' %}"/>
  28 + </div>
  29 + </form>
27 30  
28   -<a href="{% url 'auth_password_reset' %}">Nie pamiętam hasła</a>
  31 + <a href="{% url 'auth_password_reset' %}">Nie pamiętam hasła</a>
29 32  
30   -<script type="text/javascript">
31   -document.getElementById('id_username').focus()
32   -</script>
33   -</div>
  33 + <script type="text/javascript">
  34 + document.getElementById('id_username').focus()
  35 + </script>
  36 + </div>
34 37 {% endblock %}
... ...
accounts/templates/registration/logout.html
... ... @@ -4,8 +4,8 @@
4 4  
5 5 {% block content %}
6 6  
7   -<p>{% trans "Thanks for spending some quality time with the Web site today." %}</p>
  7 + <p>{% trans "Thanks for spending some quality time with the Web site today." %}</p>
8 8  
9   -<p><a href="{% url 'auth_login' %}">{% trans 'Log in again' %}</a></p>
  9 + <p><a href="{% url 'auth_login' %}">{% trans 'Log in again' %}</a></p>
10 10  
11 11 {% endblock %}
... ...
accounts/templates/registration/password_change_done.html
... ... @@ -2,14 +2,15 @@
2 2 {% load i18n %}
3 3 {% load url from future %}
4 4  
5   -{% block userlinks %}{% trans 'Change password' %} / <a href="{{ url 'auth_logout' }}">{% trans 'Log out' %}</a>{% endblock %}
  5 +{% block userlinks %}{% trans 'Change password' %} /
  6 + <a href="{{ url 'auth_logout' }}">{% trans 'Log out' %}</a>{% endblock %}
6 7  
7 8 {% block title %}{% trans 'Password change successful' %}{% endblock %}
8 9  
9 10 {% block content %}
10 11  
11   -<h1>{% trans 'Password change successful' %}</h1>
  12 + <h1>{% trans 'Password change successful' %}</h1>
12 13  
13   -<p>{% trans 'Your password was changed.' %}</p>
  14 + <p>{% trans 'Your password was changed.' %}</p>
14 15  
15 16 {% endblock %}
... ...
accounts/templates/registration/password_change_form.html
1 1 {% extends "base.html" %}
2 2 {% load i18n %}
3 3 {% load url from future %}
4   -{% block userlinks %}{% trans 'Change password' %} / <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %}
  4 +{% block userlinks %}{% trans 'Change password' %} /
  5 + <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %}
5 6  
6 7 {% block title %}{% trans 'Password change' %}{% endblock %}
7 8  
8   -{% block content %}<div id="content-main">
9   -
10   -<form action="" method="post">{% csrf_token %}
11   -<div>
12   -{% if form.errors %}
13   - <p class="errornote">
14   - {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
15   - </p>
16   -{% endif %}
17   -
18   -<h1>{% trans 'Password change' %}</h1>
19   -
20   -<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
21   -
22   -<fieldset class="module aligned wide">
23   -
24   -<div class="form-row">
25   - {{ form.old_password.errors }}
26   - <label for="id_old_password" class="required">{% trans 'Old password' %}:</label>{{ form.old_password }}
27   -</div>
28   -
29   -<div class="form-row">
30   - {{ form.new_password1.errors }}
31   - <label for="id_new_password1" class="required">{% trans 'New password' %}:</label>{{ form.new_password1 }}
32   -</div>
33   -
34   -<div class="form-row">
35   -{{ form.new_password2.errors }}
36   - <label for="id_new_password2" class="required">{% trans 'Password (again)' %}:</label>{{ form.new_password2 }}
37   -</div>
38   -
39   -</fieldset>
40   -
41   -<div class="submit-row">
42   - <input type="submit" value="{% trans 'Change my password' %}" class="default" />
43   -</div>
44   -
45   -<script type="text/javascript">document.getElementById("id_old_password").focus();</script>
46   -</div>
47   -</form></div>
  9 +{% block content %}
  10 + <div id="content-main">
  11 +
  12 + <form action="" method="post">{% csrf_token %}
  13 + <div>
  14 + {% if form.errors %}
  15 + <p class="errornote">
  16 + {% blocktrans count form.errors.items|length as counter %}
  17 + Please correct the error below.{% plural %}Please
  18 + correct the errors below.{% endblocktrans %}
  19 + </p>
  20 + {% endif %}
  21 +
  22 + <h1>{% trans 'Password change' %}</h1>
  23 +
  24 + <p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
  25 +
  26 + <fieldset class="module aligned wide">
  27 +
  28 + <div class="form-row">
  29 + {{ form.old_password.errors }}
  30 + <label for="id_old_password"
  31 + class="required">{% trans 'Old password' %}:</label>{{ form.old_password }}
  32 + </div>
  33 +
  34 + <div class="form-row">
  35 + {{ form.new_password1.errors }}
  36 + <label for="id_new_password1"
  37 + class="required">{% trans 'New password' %}:</label>{{ form.new_password1 }}
  38 + </div>
  39 +
  40 + <div class="form-row">
  41 + {{ form.new_password2.errors }}
  42 + <label for="id_new_password2"
  43 + class="required">{% trans 'Password (again)' %}:</label>{{ form.new_password2 }}
  44 + </div>
  45 +
  46 + </fieldset>
  47 +
  48 + <div class="submit-row">
  49 + <input type="submit" value="{% trans 'Change my password' %}"
  50 + class="default"/>
  51 + </div>
  52 +
  53 + <script type="text/javascript">document.getElementById("id_old_password").focus();</script>
  54 + </div>
  55 + </form></div>
48 56  
49 57 {% endblock %}
... ...
accounts/templates/registration/password_reset_complete.html
... ... @@ -5,10 +5,10 @@
5 5  
6 6 {% block content %}
7 7  
8   -<h1>{% trans 'Password reset complete' %}</h1>
  8 + <h1>{% trans 'Password reset complete' %}</h1>
9 9  
10   -<p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>
  10 + <p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>
11 11  
12   -<p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>
  12 + <p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>
13 13  
14 14 {% endblock %}
... ...
accounts/templates/registration/password_reset_confirm.html
... ... @@ -5,26 +5,32 @@
5 5  
6 6 {% block content %}
7 7  
8   -{% if validlink %}
  8 + {% if validlink %}
9 9  
10   -<h1>{% trans 'Enter new password' %}</h1>
  10 + <h1>{% trans 'Enter new password' %}</h1>
11 11  
12   -<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
  12 + <p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
13 13  
14   -<form action="" method="post">{% csrf_token %}
15   -{{ form.new_password1.errors }}
16   -<p class="aligned wide"><label for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}</p>
17   -{{ form.new_password2.errors }}
18   -<p class="aligned wide"><label for="id_new_password2">{% trans 'Confirm password:' %}</label>{{ form.new_password2 }}</p>
19   -<p><input type="submit" value="{% trans 'Change my password' %}" /></p>
20   -</form>
  14 + <form action="" method="post">{% csrf_token %}
  15 + {{ form.new_password1.errors }}
  16 + <p class="aligned wide"><label
  17 + for="id_new_password1">{% trans 'New password:' %}</label>{{ form.new_password1 }}
  18 + </p>
  19 + {{ form.new_password2.errors }}
  20 + <p class="aligned wide"><label
  21 + for="id_new_password2">{% trans 'Confirm password:' %}</label>{{ form.new_password2 }}
  22 + </p>
21 23  
22   -{% else %}
  24 + <p><input type="submit" value="{% trans 'Change my password' %}"/>
  25 + </p>
  26 + </form>
23 27  
24   -<h1>{% trans 'Password reset unsuccessful' %}</h1>
  28 + {% else %}
25 29  
26   -<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
  30 + <h1>{% trans 'Password reset unsuccessful' %}</h1>
27 31  
28   -{% endif %}
  32 + <p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
  33 +
  34 + {% endif %}
29 35  
30 36 {% endblock %}
... ...
accounts/templates/registration/password_reset_done.html
... ... @@ -5,8 +5,8 @@
5 5  
6 6 {% block content %}
7 7  
8   -<h1>{% trans 'Password reset successful' %}</h1>
  8 + <h1>{% trans 'Password reset successful' %}</h1>
9 9  
10   -<p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p>
  10 + <p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p>
11 11  
12 12 {% endblock %}
... ...
accounts/templates/registration/password_reset_email.html
1 1 {% load i18n %}{% load url from future %}{% autoescape off %}
2 2  
3   -Szanowny Użytkowniku!
  3 + Szanowny Użytkowniku!
4 4  
5   -Ten list jest częścią procedury ustanawiania lub zmiany hasła w systemie Kuźnia.
6   -Jeżeli fakt, że masz konto w systemie Kuźnia jest dla Ciebie
7   -zaskoczeniem, zechciej ten list uznać za doniesienie, że właśnie
8   -założyliśmy Ci konto.
  5 + Ten list jest częścią procedury ustanawiania lub zmiany hasła w systemie
  6 + Kuźnia.
  7 + Jeżeli fakt, że masz konto w systemie Kuźnia jest dla Ciebie
  8 + zaskoczeniem, zechciej ten list uznać za doniesienie, że właśnie
  9 + założyliśmy Ci konto.
9 10  
10   -Aby wprowadzić nowe hasło, przejdź na następującą stronę:
11   -{% block reset_link %}
12   -{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
13   -{% endblock %}
  11 + Aby wprowadzić nowe hasło, przejdź na następującą stronę:
  12 + {% block reset_link %}
  13 + {{ protocol }}://
  14 + {{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
  15 + {% endblock %}
14 16  
15   -Twoja nazwa użytkownika: {{ user.username }}
  17 + Twoja nazwa użytkownika: {{ user.username }}
16 18  
17   -Z wyrazami szacunku
18   -Zespół Kuźni
  19 + Z wyrazami szacunku
  20 + Zespół Kuźni
19 21 {% endautoescape %}
... ...
accounts/templates/registration/password_reset_form.html
... ... @@ -5,13 +5,15 @@
5 5  
6 6 {% block content %}
7 7  
8   -<h1>{% trans "Password reset" %}</h1>
  8 + <h1>{% trans "Password reset" %}</h1>
9 9  
10   -<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
  10 + <p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
11 11  
12   -<form action="" method="post">{% csrf_token %}
13   -{{ form.email.errors }}
14   -<p><label for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }} <input type="submit" value="{% trans 'Reset my password' %}" /></p>
15   -</form>
  12 + <form action="" method="post">{% csrf_token %}
  13 + {{ form.email.errors }}
  14 + <p><label
  15 + for="id_email">{% trans 'E-mail address:' %}</label> {{ form.email }}
  16 + <input type="submit" value="{% trans 'Reset my password' %}"/></p>
  17 + </form>
16 18  
17 19 {% endblock %}
... ...
accounts/templates/registration/registration_complete.html
... ... @@ -3,9 +3,10 @@
3 3  
4 4 {% block content %}
5 5  
6   -{% blocktrans %}
7   -<h1>Thank you</h1>
8   -<p>An email has been sent to you. You need to click link in it to activate your account.</p>
9   -{% endblocktrans %}
  6 + {% blocktrans %}
  7 + <h1>Thank you</h1>
  8 + <p>An email has been sent to you. You need to click link in it to
  9 + activate your account.</p>
  10 + {% endblocktrans %}
10 11  
11 12 {% endblock %}
... ...
accounts/templates/registration/registration_form.html
... ... @@ -3,36 +3,40 @@
3 3 {% load url from future %}
4 4  
5 5 {% block extrahead %}
6   - <style>
7   - label {
8   - vertical-align: top;
9   - width: 100px;
10   - display: inline-block;
11   - }
12   - </style>
  6 + <style>
  7 + label {
  8 + vertical-align: top;
  9 + width: 100px;
  10 + display: inline-block;
  11 + }
  12 + </style>
13 13 {% endblock %}
14 14  
15 15 {% block title %}{% trans 'Registration' %}{% endblock %}
16 16  
17   -{% block content %}<div id="content-main">
  17 +{% block content %}
  18 + <div id="content-main">
18 19  
19   -<form action="" method="post">{% csrf_token %}
20   -<div>
21   -{% if form.errors %}
22   - <p class="errornote">
23   - {% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
24   - </p>
25   -{% endif %}
  20 + <form action="" method="post">{% csrf_token %}
  21 + <div>
  22 + {% if form.errors %}
  23 + <p class="errornote">
  24 + {% blocktrans count form.errors.items|length as counter %}
  25 + Please correct the error below.{% plural %}Please
  26 + correct the errors below.{% endblocktrans %}
  27 + </p>
  28 + {% endif %}
26 29  
27   -<h1>{% trans 'Registration' %}</h1>
  30 + <h1>{% trans 'Registration' %}</h1>
28 31  
29   -{{ form.as_p }}
  32 + {{ form.as_p }}
30 33  
31   -<div class="submit-row">
32   - <input type="submit" value="{% trans 'Add user' %}" class="default" />
33   -</div>
  34 + <div class="submit-row">
  35 + <input type="submit" value="{% trans 'Add user' %}"
  36 + class="default"/>
  37 + </div>
34 38  
35   -</div>
36   -</form></div>
  39 + </div>
  40 + </form></div>
37 41  
38 42 {% endblock %}
... ...
accounts/templates/settings.html
... ... @@ -4,16 +4,16 @@
4 4 {% block title %}Ustawienia{% endblock %}
5 5  
6 6 {% block content %}
7   -<h1>Ustawienia użytkownika</h1>
8   -<form method="post" action="">
9   - {{ form.as_p }}
10   - {% csrf_token %}
11   - <input type="hidden" name="next" value="{{ next }}"/>
12   - <button type="submit">
13   - Zapisz
14   - </button>
15   -</form>
16   -<p>
17   - <a href="{% url 'auth_password_change' %}">Zmiana hasła</a>
18   -</p>
  7 + <h1>Ustawienia użytkownika</h1>
  8 + <form method="post" action="">
  9 + {{ form.as_p }}
  10 + {% csrf_token %}
  11 + <input type="hidden" name="next" value="{{ next }}"/>
  12 + <button type="submit">
  13 + Zapisz
  14 + </button>
  15 + </form>
  16 + <p>
  17 + <a href="{% url 'auth_password_change' %}">Zmiana hasła</a>
  18 + </p>
19 19 {% endblock %}
... ...
accounts/util.py
... ... @@ -6,13 +6,15 @@ from django.contrib.auth.models import User
6 6  
7 7  
8 8 def set_history(user):
9   - cursor = connection.cursor()
10   - cursor.execute("SELECT set_config('var.user_id', %s, true)", [str(user.id)])
  9 + cursor = connection.cursor()
  10 + cursor.execute("SELECT set_config('var.user_id', %s, true)", [str(user.id)])
  11 +
11 12  
12 13 def bot_history():
13   - set_history(User.objects.get(username=u'Kuźniobot'))
  14 + set_history(User.objects.get(username=u'Kuźniobot'))
  15 +
14 16  
15 17 def users_with_perm(perm):
16   - return User.objects.filter(
17   - Q(groups__permissions=perm) | Q(user_permissions=perm) |
18   - Q(is_superuser=True)).distinct()
19 18 \ No newline at end of file
  19 + return User.objects.filter(
  20 + Q(groups__permissions=perm) | Q(user_permissions=perm) |
  21 + Q(is_superuser=True)).distinct()
20 22 \ No newline at end of file
... ...
accounts/views.py
... ... @@ -9,43 +9,47 @@ from accounts.forms import AddUserForm, SettingsForm
9 9 from accounts.models import UserSettings, manager_groups
10 10 from dictionary.models import editable_vocabularies
11 11  
  12 +
12 13 @permission_required('auth.add_user')
13 14 @render('registration/registration_form.html')
14 15 def register(request):
15   - if request.method == 'POST':
16   - form = AddUserForm(data=request.POST)
17   - if form.is_valid():
18   - form.save(request=request)
19   - return HttpResponseRedirect(reverse('registration_complete'))
20   - else:
21   - form = AddUserForm()
22   - if not request.user.has_perm('accounts.create_admin'):
23   - choices = ((g.pk, g.name) for g in manager_groups())
24   - form.fields['groups'].choices = choices
25   - return {'form': form}
  16 + if request.method == 'POST':
  17 + form = AddUserForm(data=request.POST)
  18 + if form.is_valid():
  19 + form.save(request=request)
  20 + return HttpResponseRedirect(reverse('registration_complete'))
  21 + else:
  22 + form = AddUserForm()
  23 + if not request.user.has_perm('accounts.create_admin'):
  24 + choices = ((g.pk, g.name) for g in manager_groups())
  25 + form.fields['groups'].choices = choices
  26 + return {'form': form}
  27 +
26 28  
27 29 @login_required
28 30 @render()
29 31 def settings(request):
30   - user_settings, created = UserSettings.objects.get_or_create(user=request.user)
31   - if request.method == 'POST':
32   - form = SettingsForm(data=request.POST, instance=user_settings)
33   - if form.is_valid():
34   - form.save()
35   - return HttpResponseRedirect(request.POST['next'])
36   - else:
37   - form = SettingsForm(
38   - instance=user_settings,
39   - vocabularies=editable_vocabularies(request.user))
40   - return {'form': form, 'next': request.META.get('HTTP_REFERER', '')}
  32 + user_settings, created = UserSettings.objects.get_or_create(
  33 + user=request.user)
  34 + if request.method == 'POST':
  35 + form = SettingsForm(data=request.POST, instance=user_settings)
  36 + if form.is_valid():
  37 + form.save()
  38 + return HttpResponseRedirect(request.POST['next'])
  39 + else:
  40 + form = SettingsForm(
  41 + instance=user_settings,
  42 + vocabularies=editable_vocabularies(request.user))
  43 + return {'form': form, 'next': request.META.get('HTTP_REFERER', '')}
  44 +
41 45  
42 46 @permission_required('auth.add_user')
43 47 @render()
44 48 def manage_groups(request):
45   - users = User.objects.filter(is_superuser=False)
46   - if request.user.has_perm('accounts.create_admin'):
47   - groups = Group.objects.all()
48   - else:
49   - groups = manager_groups()
50   - js_vars = {'ajax_set_group': reverse('set_group')}
51   - return {'users': users, 'groups': groups, 'js_vars': js_vars}
  49 + users = User.objects.filter(is_superuser=False)
  50 + if request.user.has_perm('accounts.create_admin'):
  51 + groups = Group.objects.all()
  52 + else:
  53 + groups = manager_groups()
  54 + js_vars = {'ajax_set_group': reverse('set_group')}
  55 + return {'users': users, 'groups': groups, 'js_vars': js_vars}
... ...
common/context_processors.py
1 1 # -*- coding: utf-8 -*-
2 2  
3 3 def error_proc(request):
4   - if request.session.get('error', ''):
5   - error = request.session.pop('error')
6   - return {'error': error}
7   - else:
8   - return {}
  4 + if request.session.get('error', ''):
  5 + error = request.session.pop('error')
  6 + return {'error': error}
  7 + else:
  8 + return {}
  9 +
9 10  
10 11 def message_proc(request):
11   - if request.session.get('message', ''):
12   - message = request.session.pop('message')
13   - return {'alert_message': message}
14   - else:
15   - return {}
  12 + if request.session.get('message', ''):
  13 + message = request.session.pop('message')
  14 + return {'alert_message': message}
  15 + else:
  16 + return {}
... ...
common/decorators.py
... ... @@ -15,70 +15,84 @@ from common.util import stringify_keys
15 15  
16 16  
17 17 class AjaxError(Exception):
18   - pass
  18 + pass
  19 +
19 20  
20 21 def json_decode_fallback(value):
21   - try:
22   - return json_decode(value)
23   - except ValueError:
24   - return value
  22 + try:
  23 + return json_decode(value)
  24 + except ValueError:
  25 + return value
  26 +
25 27  
26 28 def ajax(login_required=True, method=None, encode_result=True, template=None):
27   - def decorator(fun):
28   - @wraps(fun)
29   - def ajax_view(request):
30   - kwargs = {}
31   - request_params = None
32   - if method == 'post':
33   - request_params = request.POST
34   - elif method == 'get':
35   - request_params = request.GET
36   - fun_params, xx, fun_kwargs, xxxx = getargspec(fun)
37   - if request_params:
38   - request_params = dict((key, json_decode_fallback(value))
39   - for key, value in request_params.iteritems()
40   - if fun_kwargs or key in fun_params)
41   - kwargs.update(stringify_keys(request_params))
42   - res = None
43   - if login_required and not request.user.is_authenticated():
44   - res = {'result': 'logout'}
45   - if not res:
46   - try:
47   - res = fun(request, **kwargs)
48   - except AjaxError as e:
49   - transaction.rollback()
50   - res = {'result': e.args[0]}
51   - if template:
52   - res = {'html': render_to_string(template, res, RequestContext(request))}
53   - if encode_result:
54   - if 'result' not in res:
55   - res['result'] = 'ok'
56   - return HttpResponse(json_encode(res), mimetype='application/json')
57   - else:
58   - return res
59   - return ajax_view
60   - return decorator
  29 + def decorator(fun):
  30 + @wraps(fun)
  31 + def ajax_view(request):
  32 + kwargs = {}
  33 + request_params = None
  34 + if method == 'post':
  35 + request_params = request.POST
  36 + elif method == 'get':
  37 + request_params = request.GET
  38 + fun_params, xx, fun_kwargs, xxxx = getargspec(fun)
  39 + if request_params:
  40 + request_params = dict((key, json_decode_fallback(value))
  41 + for key, value in
  42 + request_params.iteritems()
  43 + if fun_kwargs or key in fun_params)
  44 + kwargs.update(stringify_keys(request_params))
  45 + res = None
  46 + if login_required and not request.user.is_authenticated():
  47 + res = {'result': 'logout'}
  48 + if not res:
  49 + try:
  50 + res = fun(request, **kwargs)
  51 + except AjaxError as e:
  52 + transaction.rollback()
  53 + res = {'result': e.args[0]}
  54 + if template:
  55 + res = {'html': render_to_string(template, res,
  56 + RequestContext(request))}
  57 + if encode_result:
  58 + if 'result' not in res:
  59 + res['result'] = 'ok'
  60 + return HttpResponse(json_encode(res),
  61 + mimetype='application/json')
  62 + else:
  63 + return res
  64 +
  65 + return ajax_view
  66 +
  67 + return decorator
  68 +
61 69  
62 70 def render(template=None, mimetype=None):
63   - mimetype = mimetype or settings.DEFAULT_CONTENT_TYPE
64   - template1 = template
65   - def decorator(func):
66   - template = template1 # no cóż...
67   - if not template:
68   - template = func.__name__ + '.html'
69   - @wraps(func)
70   - def renderer(request, *args, **kw):
71   - output = func(request, *args, **kw)
72   - if isinstance(output, (list, tuple)):
73   - return render_to_response(
74   - output[1], output[0], RequestContext(request), mimetype=mimetype)
75   - elif isinstance(output, dict):
76   - return render_to_response(
77   - template, output, RequestContext(request), mimetype=mimetype)
78   - return output
79   - return renderer
80   - return decorator
  71 + mimetype = mimetype or settings.DEFAULT_CONTENT_TYPE
  72 + template1 = template
  73 +
  74 + def decorator(func):
  75 + template = template1 # no cóż...
  76 + if not template:
  77 + template = func.__name__ + '.html'
  78 +
  79 + @wraps(func)
  80 + def renderer(request, *args, **kw):
  81 + output = func(request, *args, **kw)
  82 + if isinstance(output, (list, tuple)):
  83 + return render_to_response(
  84 + output[1], output[0], RequestContext(request),
  85 + mimetype=mimetype)
  86 + elif isinstance(output, dict):
  87 + return render_to_response(
  88 + template, output, RequestContext(request),
  89 + mimetype=mimetype)
  90 + return output
  91 +
  92 + return renderer
  93 +
  94 + return decorator
81 95  
82 96 # żeby były linki do szablonów w PyCharm przy ajaxach
83 97 def render_template(t):
84   - return lambda x: x
85 98 \ No newline at end of file
  99 + return lambda x: x
86 100 \ No newline at end of file
... ...
common/forms.py
... ... @@ -3,12 +3,14 @@
3 3 from django import forms
4 4 from django.utils.encoding import force_unicode
5 5  
  6 +
6 7 def hidden_id(id):
7   - return forms.CharField(initial=id, widget=forms.HiddenInput())
  8 + return forms.CharField(initial=id, widget=forms.HiddenInput())
8 9  
9 10 # http://www.djangosnippets.org/snippets/863/ z moimi zmianami
10 11 class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
11 12 """RadioFieldRenderer that renders its last choice with a placeholder."""
  13 +
12 14 def __init__(self, *args, **kwargs):
13 15 super(ChoiceWithOtherRenderer, self).__init__(*args, **kwargs)
14 16 self.choices, self.other = self.choices[:-1], self.choices[-1]
... ... @@ -16,17 +18,22 @@ class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
16 18 def __iter__(self):
17 19 for input in super(ChoiceWithOtherRenderer, self).__iter__():
18 20 yield input
19   - id = '%s_%s' % (self.attrs['id'], self.other[0]) if 'id' in self.attrs else ''
  21 + id = '%s_%s' % (
  22 + self.attrs['id'], self.other[0]) if 'id' in self.attrs else ''
20 23 label_for = ' for="%s"' % id if id else ''
21   - checked = '' if not force_unicode(self.other[0]) == self.value else 'checked="true" '
  24 + checked = '' if not force_unicode(
  25 + self.other[0]) == self.value else 'checked="true" '
22 26 yield '<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s' % (
23 27 label_for, id, self.other[0], self.name, checked, self.other[1])
24 28  
  29 +
25 30 class ChoiceWithOtherWidget(forms.MultiWidget):
26 31 """MultiWidget for use with ChoiceWithOtherField."""
  32 +
27 33 def __init__(self, choices):
28 34 widgets = [
29   - forms.RadioSelect(choices=choices, renderer=ChoiceWithOtherRenderer),
  35 + forms.RadioSelect(choices=choices,
  36 + renderer=ChoiceWithOtherRenderer),
30 37 forms.TextInput
31 38 ]
32 39 super(ChoiceWithOtherWidget, self).__init__(widgets)
... ... @@ -40,20 +47,25 @@ class ChoiceWithOtherWidget(forms.MultiWidget):
40 47 """Format the output by substituting the "other" choice into the first widget."""
41 48 return rendered_widgets[0] % rendered_widgets[1]
42 49  
  50 +
43 51 class ChoiceWithOtherField(forms.MultiValueField):
44 52 """
45 53 ChoiceField with an option for a user-submitted "other" value.
46 54 """
  55 +
47 56 def __init__(self, *args, **kwargs):
48 57 fields = [
49   - forms.ChoiceField(widget=forms.RadioSelect(renderer=ChoiceWithOtherRenderer), *args, **kwargs),
  58 + forms.ChoiceField(
  59 + widget=forms.RadioSelect(renderer=ChoiceWithOtherRenderer),
  60 + *args, **kwargs),
50 61 forms.CharField(required=False)
51 62 ]
52 63 widget = ChoiceWithOtherWidget(choices=kwargs['choices'])
53 64 kwargs.pop('choices')
54 65 self._was_required = kwargs.pop('required', True)
55 66 kwargs['required'] = False
56   - super(ChoiceWithOtherField, self).__init__(widget=widget, fields=fields, *args, **kwargs)
  67 + super(ChoiceWithOtherField, self).__init__(widget=widget, fields=fields,
  68 + *args, **kwargs)
57 69  
58 70 def compress(self, value):
59 71 if self._was_required and (not value or value[0] in (None, '')):
... ... @@ -61,5 +73,6 @@ class ChoiceWithOtherField(forms.MultiValueField):
61 73 if not value:
62 74 return [None, u'']
63 75 return (value[0], value[1]
64   - if force_unicode(value[0]) == force_unicode(self.fields[0].choices[-1][0])
65   - else self.fields[0].choices[int(value[0]) - 1][1])
66 76 \ No newline at end of file
  77 + if force_unicode(value[0]) == force_unicode(
  78 + self.fields[0].choices[-1][0])
  79 + else self.fields[0].choices[int(value[0]) - 1][1])
67 80 \ No newline at end of file
... ...
common/middleware.py
1 1 #-*- coding:utf-8 -*-
2 2  
3   -from django.db import connection
4 3 from decimal import Decimal
5 4  
  5 +from django.db import connection
  6 +
6 7 from accounts.util import set_history
7 8  
  9 +
8 10 class MyMiddleware(object):
9   - def process_request(self, request):
10   - if request.user.is_authenticated():
11   - set_history(request.user)
  11 + def process_request(self, request):
  12 + if request.user.is_authenticated():
  13 + set_history(request.user)
12 14  
13   - def process_response(self, request, response):
14   - if False:
15   - if len(connection.queries) > 0:
16   - print 'Queries for %s:' % request.path_info
17   - for query in connection.queries:
18   - print query['time'], query['sql']
19   - print 'Total of %s queries for %s.' % (
20   - len(connection.queries), request.path)
21   - print 'Total time: %s' % sum(Decimal(q['time'])
22   - for q in connection.queries)
23   - return response
24 15 \ No newline at end of file
  16 + def process_response(self, request, response):
  17 + if False:
  18 + if len(connection.queries) > 0:
  19 + print 'Queries for %s:' % request.path_info
  20 + for query in connection.queries:
  21 + print query['time'], query['sql']
  22 + print 'Total of %s queries for %s.' % (
  23 + len(connection.queries), request.path)
  24 + print 'Total time: %s' % sum(Decimal(q['time'])
  25 + for q in connection.queries)
  26 + return response
25 27 \ No newline at end of file
... ...
common/templates/error.html
1   -<p id="erroralert" style="display:{{ error|yesno:",none"}}">
2   -{{ error }}
  1 +<p id="erroralert" style="display:{{ error|yesno:",none" }}">
  2 + {{ error }}
3 3 </p>
... ...
common/templates/message.html
1   -<p id="messagealert" style="display:{{ alert_message|yesno:",none"}}">
2   -{{ alert_message }}
  1 +<p id="messagealert" style="display:{{ alert_message|yesno:",none" }}">
  2 + {{ alert_message }}
3 3 </p>
... ...
common/templates/navigation.html
1 1 {% for menu_item in menu %}
2   - <li>
3   - <a href="{{ menu_item.url }}">
4   - {{ menu_item.name }}
5   - </a>
6   - </li>
  2 + <li>
  3 + <a href="{{ menu_item.url }}">
  4 + {{ menu_item.name }}
  5 + </a>
  6 + </li>
7 7 {% endfor %}
8 8 \ No newline at end of file
... ...
common/templatetags/format_date.py
... ... @@ -4,10 +4,12 @@ from django.template import Library
4 4  
5 5 register = Library()
6 6  
  7 +
7 8 @register.filter
8 9 def format_date(date):
9   - return date.strftime('%d.%m.%Y %H:%M')
  10 + return date.strftime('%d.%m.%Y %H:%M')
  11 +
10 12  
11 13 @register.filter
12 14 def format_date_exact(date):
13   - return date.strftime('%d.%m.%Y %H:%M:%S.%f')
  15 + return date.strftime('%d.%m.%Y %H:%M:%S.%f')
... ...
common/templatetags/get.py
... ... @@ -4,6 +4,7 @@ from django.template import Library
4 4  
5 5 register = Library()
6 6  
  7 +
7 8 @register.filter
8 9 def get(dict, arg):
9   - return dict[arg]
10 10 \ No newline at end of file
  11 + return dict[arg]
11 12 \ No newline at end of file
... ...
common/templatetags/ingroup.py
... ... @@ -4,6 +4,7 @@ from django.template import Library
4 4  
5 5 register = Library()
6 6  
  7 +
7 8 @register.filter
8 9 def ingroup(user, group):
9   - return group in user.groups.all()
  10 + return group in user.groups.all()
... ...
common/templatetags/jsonify.py
... ... @@ -9,6 +9,7 @@ from django.template import Library
9 9  
10 10 register = Library()
11 11  
  12 +
12 13 @register.filter
13 14 def jsonify(object):
14 15 if isinstance(object, QuerySet):
... ...
common/templatetags/script.py
... ... @@ -3,10 +3,12 @@ from django import template
3 3  
4 4 register = template.Library()
5 5  
  6 +
6 7 @register.simple_tag
7 8 def script():
8   - return '<script type="text/javascript"> /* <![CDATA[ */'
  9 + return '<script type="text/javascript"> /* <![CDATA[ */'
  10 +
9 11  
10 12 @register.simple_tag
11 13 def endscript():
12   - return '/* ]]> */ </script>'
  14 + return '/* ]]> */ </script>'
... ...
common/util.py
... ... @@ -7,96 +7,116 @@ from django.http import HttpResponseRedirect, Http404
7 7  
8 8  
9 9 def debug(entry, text):
10   - print>>sys.stderr, (u'%s: %s' % (entry, text)).encode('utf-8')
  10 + print>> sys.stderr, (u'%s: %s' % (entry, text)).encode('utf-8')
  11 +
11 12  
12 13 def error_redirect(request, error, url='/'):
13   - request.session['error'] = error
14   - return HttpResponseRedirect(url)
  14 + request.session['error'] = error
  15 + return HttpResponseRedirect(url)
  16 +
15 17  
16 18 def message_redirect(request, message, url='/'):
17   - request.session['message'] = message
18   - return HttpResponseRedirect(url)
  19 + request.session['message'] = message
  20 + return HttpResponseRedirect(url)
  21 +
19 22  
20 23 def make_form(request, form_class, **kwargs):
21   - if request.POST.get('det', '') == form_class.base_fields['det'].initial:
22   - return form_class(data=request.POST, files=request.FILES, **kwargs)
23   - else:
24   - return form_class(**kwargs)
  24 + if request.POST.get('det', '') == form_class.base_fields['det'].initial:
  25 + return form_class(data=request.POST, files=request.FILES, **kwargs)
  26 + else:
  27 + return form_class(**kwargs)
  28 +
25 29  
26 30 def invert(l):
27   - return dict((e,nr) for (nr,e) in enumerate(l))
  31 + return dict((e, nr) for (nr, e) in enumerate(l))
  32 +
28 33  
29 34 def generator_slice(generator, count):
30   - res = []
31   - try:
32   - for i in range(count):
33   - res.append(generator.next())
34   - except StopIteration:
35   - pass
36   - return res
  35 + res = []
  36 + try:
  37 + for i in range(count):
  38 + res.append(generator.next())
  39 + except StopIteration:
  40 + pass
  41 + return res
  42 +
37 43  
38 44 def url(regex, view, **kwargs):
39   - if 'name' not in kwargs:
40   - kwargs['name'] = view.rsplit('.', 1)[-1]
41   - return urls.url(regex, view, **kwargs)
  45 + if 'name' not in kwargs:
  46 + kwargs['name'] = view.rsplit('.', 1)[-1]
  47 + return urls.url(regex, view, **kwargs)
  48 +
42 49  
43 50 def stringify_keys(dictionary):
44   - return dict((keyword.encode('ascii'), value)
45   - for keyword, value in dictionary.iteritems())
  51 + return dict((keyword.encode('ascii'), value)
  52 + for keyword, value in dictionary.iteritems())
46 53  
47 54 # copypasta ze standardowego modułu bisect
48 55 def bisect_left(a, x, lo=0, hi=None, cmp=None):
49   - if cmp is None:
50   - cmp = __builtins__.cmp
51   - if lo < 0:
52   - raise ValueError('lo must be non-negative')
53   - if hi is None:
54   - hi = len(a)
55   - while lo < hi:
56   - mid = (lo+hi)//2
57   - if cmp(a[mid], x) < 0: lo = mid+1
58   - else: hi = mid
59   - return lo
  56 + if cmp is None:
  57 + cmp = __builtins__.cmp
  58 + if lo < 0:
  59 + raise ValueError('lo must be non-negative')
  60 + if hi is None:
  61 + hi = len(a)
  62 + while lo < hi:
  63 + mid = (lo + hi) // 2
  64 + if cmp(a[mid], x) < 0:
  65 + lo = mid + 1
  66 + else:
  67 + hi = mid
  68 + return lo
  69 +
60 70  
61 71 def no_history():
62   - from django.db import connection
63   - cursor = connection.cursor()
64   - cursor.execute("SELECT set_config('var.user_id', '0', false)")
  72 + from django.db import connection
  73 +
  74 + cursor = connection.cursor()
  75 + cursor.execute("SELECT set_config('var.user_id', '0', false)")
  76 +
65 77  
66 78 def reverse(seq):
67   - return seq[::-1]
  79 + return seq[::-1]
  80 +
68 81  
69 82 def flatten(seq):
70   - return [item for subseq in seq for item in subseq]
  83 + return [item for subseq in seq for item in subseq]
  84 +
71 85  
72 86 def suffix(string, length):
73   - return string[-length:] if length > 0 else ''
  87 + return string[-length:] if length > 0 else ''
  88 +
74 89  
75 90 def suffixes(s):
76   - return [s[i:] for i in range(len(s)+1)]
  91 + return [s[i:] for i in range(len(s) + 1)]
  92 +
77 93  
78 94 def cut_end(s, end):
79   - assert s.endswith(end)
80   - n = len(end)
81   - if n == 0:
82   - return s
83   - else:
84   - return s[:-n]
  95 + assert s.endswith(end)
  96 + n = len(end)
  97 + if n == 0:
  98 + return s
  99 + else:
  100 + return s[:-n]
  101 +
85 102  
86 103 def error_messages(form):
87   - return '\n'.join(
88   - '%s: %s' % (form.fields[k].label, ' '.join(v)) if k != '__all__'
89   - else ' '.join(v)
90   - for k, v in form.errors.iteritems())
  104 + return '\n'.join(
  105 + '%s: %s' % (form.fields[k].label, ' '.join(v)) if k != '__all__'
  106 + else ' '.join(v)
  107 + for k, v in form.errors.iteritems())
  108 +
91 109  
92 110 class GroupDict(dict):
93   - def add(self, key, value):
94   - if key not in self:
95   - self[key] = []
96   - self[key].append(value)
  111 + def add(self, key, value):
  112 + if key not in self:
  113 + self[key] = []
  114 + self[key].append(value)
  115 +
97 116  
98 117 def json_encode(obj):
99   - return json.dumps(obj, sort_keys=True)
  118 + return json.dumps(obj, sort_keys=True)
  119 +
100 120  
101 121 def json_decode(obj):
102   - return json.loads(obj)
103 122 \ No newline at end of file
  123 + return json.loads(obj)
104 124 \ No newline at end of file
... ...
dictionary/ajax_export.py
... ... @@ -4,42 +4,46 @@ from common.decorators import render, ajax, AjaxError
4 4 from dictionary.forms import MagicQualifierForm
5 5 from dictionary.models import SavedExportData
6 6  
  7 +
7 8 @render()
8 9 @ajax(method='get', encode_result=False)
9 10 def magic_qualifier_row(request):
10   - return {'form': MagicQualifierForm(prefix='magic_NUM')}
  11 + return {'form': MagicQualifierForm(prefix='magic_NUM')}
  12 +
11 13  
12 14 @ajax(method='post')
13 15 def save_export_data(request, name, serialized_data, force=False):
14   - existing_data = SavedExportData.objects.filter(name=name)
15   - if force or not existing_data:
16   - if existing_data:
17   - data = existing_data[0]
  16 + existing_data = SavedExportData.objects.filter(name=name)
  17 + if force or not existing_data:
  18 + if existing_data:
  19 + data = existing_data[0]
  20 + else:
  21 + data = SavedExportData()
  22 + data.name = name
  23 + data.serialized_data = serialized_data
  24 + try:
  25 + data.save()
  26 + except ValueError as e:
  27 + raise AjaxError(e.data)
18 28 else:
19   - data = SavedExportData()
20   - data.name = name
21   - data.serialized_data = serialized_data
22   - try:
23   - data.save()
24   - except ValueError as e:
25   - raise AjaxError(e.data)
26   - else:
27   - return {'exists': True}
28   - return {}
  29 + return {'exists': True}
  30 + return {}
  31 +
29 32  
30 33 @ajax(method='get')
31 34 def get_export_data(request):
32   - data_list = [{
33   - 'id': 'export%s' % data.pk,
34   - 'name': data.name,
35   - 'json': data.serialized_data,
36   - }
37   - for data in SavedExportData.objects.all()]
38   - return {'data_list': data_list}
  35 + data_list = [{
  36 + 'id': 'export%s' % data.pk,
  37 + 'name': data.name,
  38 + 'json': data.serialized_data,
  39 + }
  40 + for data in SavedExportData.objects.all()]
  41 + return {'data_list': data_list}
  42 +
39 43  
40 44 @ajax(method='post')
41 45 def delete_export_data(request, data_id):
42   - export_data_id = data_id[len('export'):]
43   - data = SavedExportData.objects.get(pk=export_data_id)
44   - data.delete()
45   - return {}
  46 + export_data_id = data_id[len('export'):]
  47 + data = SavedExportData.objects.get(pk=export_data_id)
  48 + data.delete()
  49 + return {}
... ...
dictionary/ajax_filters.py
... ... @@ -3,41 +3,44 @@
3 3 from common.decorators import ajax, AjaxError
4 4 from dictionary.models import SavedFilter
5 5  
  6 +
6 7 @ajax(method='post')
7 8 def save_filter(request, name, serialized_filter, super=False, force=False):
8   - existing_filter = SavedFilter.objects.filter(user=request.user, name=name)
9   - if force or not existing_filter:
10   - if existing_filter:
11   - filter = existing_filter[0]
  9 + existing_filter = SavedFilter.objects.filter(user=request.user, name=name)
  10 + if force or not existing_filter:
  11 + if existing_filter:
  12 + filter = existing_filter[0]
  13 + else:
  14 + filter = SavedFilter()
  15 + filter.name = name
  16 + filter.user = request.user
  17 + filter.serialized_filter = serialized_filter
  18 + filter.super = super
  19 + try:
  20 + filter.save()
  21 + except ValueError as e:
  22 + raise AjaxError(e.data)
12 23 else:
13   - filter = SavedFilter()
14   - filter.name = name
15   - filter.user = request.user
16   - filter.serialized_filter = serialized_filter
17   - filter.super = super
18   - try:
19   - filter.save()
20   - except ValueError as e:
21   - raise AjaxError(e.data)
22   - else:
23   - return {'exists': True}
24   - return {}
  24 + return {'exists': True}
  25 + return {}
  26 +
25 27  
26 28 @ajax(method='get')
27 29 def get_filters(request):
28   - filters = [{
29   - 'id': 'filter%s' % filter.pk,
30   - 'name': filter.name,
31   - 'json': filter.serialized_filter,
32   - }
33   - for filter in SavedFilter.objects.filter(user=request.user)]
34   - return {'filters': filters}
  30 + filters = [{
  31 + 'id': 'filter%s' % filter.pk,
  32 + 'name': filter.name,
  33 + 'json': filter.serialized_filter,
  34 + }
  35 + for filter in SavedFilter.objects.filter(user=request.user)]
  36 + return {'filters': filters}
  37 +
35 38  
36 39 @ajax(method='post')
37 40 def delete_filter(request, id):
38   - filter_id = id[len('filter'):]
39   - filter = SavedFilter.objects.get(pk=filter_id)
40   - if filter.user != request.user:
41   - raise AjaxError('access denied')
42   - filter.delete()
43   - return {}
  41 + filter_id = id[len('filter'):]
  42 + filter = SavedFilter.objects.get(pk=filter_id)
  43 + if filter.user != request.user:
  44 + raise AjaxError('access denied')
  45 + filter.delete()
  46 + return {}
... ...
dictionary/ajax_history.py
... ... @@ -4,10 +4,11 @@ from common.decorators import ajax, render_template
4 4 from dictionary.models import History
5 5 from dictionary.history import lexeme_tables
6 6  
  7 +
7 8 @render_template('history_table.html')
8 9 @ajax(method='get', template='history_table.html')
9 10 def history_table(request, lexeme_id):
10   - history_items = History.objects.filter(
11   - lexeme__pk=lexeme_id).order_by('-transaction_began')
12   - transaction_tables = lexeme_tables(history_items)
13   - return {'transaction_tables': transaction_tables}
  11 + history_items = History.objects.filter(
  12 + lexeme__pk=lexeme_id).order_by('-transaction_began')
  13 + transaction_tables = lexeme_tables(history_items)
  14 + return {'transaction_tables': transaction_tables}
... ...
dictionary/ajax_jqgrid.py
... ... @@ -4,267 +4,270 @@ import math
4 4 from accounts.models import filtering_mode
5 5 from common.decorators import render, ajax
6 6  
  7 +
7 8 class JqGridQuery(object):
8   - def __init__(self, filters, sort_rules, mask, user):
9   - self.filters = filters
10   - self.sort_rules = sort_rules
11   - self.mask = mask
12   - self.user = user
  9 + def __init__(self, filters, sort_rules, mask, user):
  10 + self.filters = filters
  11 + self.sort_rules = sort_rules
  12 + self.mask = mask
  13 + self.user = user
  14 +
  15 + def filtering_mode(self):
  16 + return filtering_mode(self.user)
13 17  
14   - def filtering_mode(self):
15   - return filtering_mode(self.user)
16 18  
17 19 class JqGridAjax(object):
18   - model = None
19   - search_field = None
20   - field_translation = {}
  20 + model = None
  21 + search_field = None
  22 + field_translation = {}
21 23  
22   - @classmethod
23   - def translate_field(cls, field):
24   - if field in cls.field_translation:
25   - return cls.field_translation[field]
26   - else:
27   - return field
  24 + @classmethod
  25 + def translate_field(cls, field):
  26 + if field in cls.field_translation:
  27 + return cls.field_translation[field]
  28 + else:
  29 + return field
28 30  
29   - @staticmethod
30   - def sort_field_special_case(rule):
31   - return rule['field']
  31 + @staticmethod
  32 + def sort_field_special_case(rule):
  33 + return rule['field']
32 34  
33   - @classmethod
34   - def get_sort_field(cls, rule):
35   - field = cls.sort_field_special_case(rule)
36   - field = cls.translate_field(field)
37   - if rule['order'] == 'desc':
38   - field = '-' + field
39   - return field
  35 + @classmethod
  36 + def get_sort_field(cls, rule):
  37 + field = cls.sort_field_special_case(rule)
  38 + field = cls.translate_field(field)
  39 + if rule['order'] == 'desc':
  40 + field = '-' + field
  41 + return field
40 42  
41   - @staticmethod
42   - def sort_queryset_special_case(queryset, field):
43   - return queryset
  43 + @staticmethod
  44 + def sort_queryset_special_case(queryset, field):
  45 + return queryset
44 46  
45   - @classmethod
46   - def sort_queryset(cls, queryset, sort_rules):
47   - order_list = []
48   - for rule in sort_rules:
49   - queryset = cls.sort_queryset_special_case(queryset, rule)
50   - order_list.append(cls.get_sort_field(rule))
51   - return queryset.extra(order_by=order_list)
  47 + @classmethod
  48 + def sort_queryset(cls, queryset, sort_rules):
  49 + order_list = []
  50 + for rule in sort_rules:
  51 + queryset = cls.sort_queryset_special_case(queryset, rule)
  52 + order_list.append(cls.get_sort_field(rule))
  53 + return queryset.extra(order_by=order_list)
52 54  
53   - lookup_translation = {
54   - 'eq': 'exact',
55   - 'ne': '-exact',
56   - 'bw': 'startswith',
57   - 'bn': '-startswith',
58   - 'ew': 'endswith',
59   - 'en': '-endswith',
60   - 'cn': 'contains',
61   - 'nc': '-contains',
62   - 're': 'regex',
63   - 'nr': '-regex',
64   - #'se': 'surely',
65   - #'sd': '-maybe',
66   - #'me': 'maybe',
67   - #'md': '-surely',
68   - 'le': 'lte',
69   - 'ge': 'gte',
70   - }
  55 + lookup_translation = {
  56 + 'eq': 'exact',
  57 + 'ne': '-exact',
  58 + 'bw': 'startswith',
  59 + 'bn': '-startswith',
  60 + 'ew': 'endswith',
  61 + 'en': '-endswith',
  62 + 'cn': 'contains',
  63 + 'nc': '-contains',
  64 + 're': 'regex',
  65 + 'nr': '-regex',
  66 + #'se': 'surely',
  67 + #'sd': '-maybe',
  68 + #'me': 'maybe',
  69 + #'md': '-surely',
  70 + 'le': 'lte',
  71 + 'ge': 'gte',
  72 + }
71 73  
72   - @staticmethod
73   - def filter_special_case(filter, lookup, negated, queryset):
74   - return False, filter['field'], queryset
  74 + @staticmethod
  75 + def filter_special_case(filter, lookup, negated, queryset):
  76 + return False, filter['field'], queryset
75 77  
76   - @classmethod
77   - def apply_filter(cls, queryset, filter):
78   - lookup = cls.lookup_translation[filter['op']]
79   - negated = (lookup[0] == '-')
80   - lookup = lookup.lstrip('-')
81   - data = filter['data']
82   - special, field, queryset = cls.filter_special_case(
83   - filter, lookup, negated, queryset)
84   - if not special:
85   - arg = {(field + '__' + lookup): data}
86   - if negated:
87   - queryset = queryset.exclude(**arg)
88   - else:
89   - queryset = queryset.filter(**arg).distinct()
90   - return queryset
  78 + @classmethod
  79 + def apply_filter(cls, queryset, filter):
  80 + lookup = cls.lookup_translation[filter['op']]
  81 + negated = (lookup[0] == '-')
  82 + lookup = lookup.lstrip('-')
  83 + data = filter['data']
  84 + special, field, queryset = cls.filter_special_case(
  85 + filter, lookup, negated, queryset)
  86 + if not special:
  87 + arg = {(field + '__' + lookup): data}
  88 + if negated:
  89 + queryset = queryset.exclude(**arg)
  90 + else:
  91 + queryset = queryset.filter(**arg).distinct()
  92 + return queryset
91 93  
92   - @classmethod
93   - def get_queryset(cls, query):
94   - return cls.model.objects.all()
  94 + @classmethod
  95 + def get_queryset(cls, query):
  96 + return cls.model.objects.all()
95 97  
96   - @classmethod
97   - def get_empty_queryset(cls):
98   - return cls.model.objects.none()
  98 + @classmethod
  99 + def get_empty_queryset(cls):
  100 + return cls.model.objects.none()
99 101  
100   - @classmethod
101   - def apply_filters(cls, query):
102   - filters = query.filters
103   - queryset = cls.get_queryset(query)
104   - if filters:
105   - if filters['groupOp'] == 'AND':
106   - for filter in filters['rules']:
107   - queryset = cls.apply_filter(queryset, filter)
108   - elif filters['groupOp'] == 'OR':
109   - new_queryset = cls.get_empty_queryset()
110   - for filter in filters['rules']:
111   - new_queryset |= cls.apply_filter(queryset, filter)
112   - queryset = new_queryset
113   - return queryset
  102 + @classmethod
  103 + def apply_filters(cls, query):
  104 + filters = query.filters
  105 + queryset = cls.get_queryset(query)
  106 + if filters:
  107 + if filters['groupOp'] == 'AND':
  108 + for filter in filters['rules']:
  109 + queryset = cls.apply_filter(queryset, filter)
  110 + elif filters['groupOp'] == 'OR':
  111 + new_queryset = cls.get_empty_queryset()
  112 + for filter in filters['rules']:
  113 + new_queryset |= cls.apply_filter(queryset, filter)
  114 + queryset = new_queryset
  115 + return queryset
114 116  
115   - @staticmethod
116   - def apply_mask(queryset, mask, sort_rules):
117   - pass # abstract
  117 + @staticmethod
  118 + def apply_mask(queryset, mask, sort_rules):
  119 + pass # abstract
118 120  
119   - @staticmethod
120   - def filter_value_special_case(queryset, rule, from_value, upward):
121   - return False, queryset
  121 + @staticmethod
  122 + def filter_value_special_case(queryset, rule, from_value, upward):
  123 + return False, queryset
122 124  
123   - # filtruje queryset według pola z reguły rule od wartości from,
124   - # wartości dalsze w porządku jeśli upward, w przeciwnym razie bliższe
125   - @classmethod
126   - def filter_value(cls, queryset, rule, from_value, upward):
127   - greater = (rule['order'] == 'asc') == upward
128   - special, queryset = cls.filter_value_special_case(
129   - queryset, rule, from_value, upward)
130   - if special:
131   - return queryset
132   - if greater:
133   - lookup = '__gte'
134   - else:
135   - lookup = '__lte'
136   - field = cls.translate_field(rule['field'])
137   - return queryset.filter(**{field + lookup: from_value})
  125 + # filtruje queryset według pola z reguły rule od wartości from,
  126 + # wartości dalsze w porządku jeśli upward, w przeciwnym razie bliższe
  127 + @classmethod
  128 + def filter_value(cls, queryset, rule, from_value, upward):
  129 + greater = (rule['order'] == 'asc') == upward
  130 + special, queryset = cls.filter_value_special_case(
  131 + queryset, rule, from_value, upward)
  132 + if special:
  133 + return queryset
  134 + if greater:
  135 + lookup = '__gte'
  136 + else:
  137 + lookup = '__lte'
  138 + field = cls.translate_field(rule['field'])
  139 + return queryset.filter(**{field + lookup: from_value})
138 140  
139   - # id instancji z search_field rownym mask badz takiej, ktora bylaby nastepna
140   - # po instancji z search_field równym mask w danym sortowaniu.
141   - # Jezeli nie ma 'wiekszej' instancji badz reguly sortowania nie uwzgledniaja
142   - # search_field, metoda zwroci pierwsza instancje w danym sortowaniu
143   - #
144   - # beznadziejna nazwa metody...
145   - @classmethod
146   - def get_pk(cls, query):
147   - whole_queryset = cls.apply_filters(query)
148   - queryset = whole_queryset
149   - matching = cls.apply_mask(queryset, query.mask, query.sort_rules)
150   - if matching.count() > 0:
151   - matching = cls.sort_queryset(matching, query.sort_rules)
152   - return matching[0].pk
153   - else:
154   - #gdy nie ma pasującego
155   - rule = query.sort_rules[0]
156   - if rule['field'] == cls.search_field:
157   - queryset = cls.filter_value(
158   - queryset, rule, from_value=query.mask, upward=True)
159   - if queryset.count() == 0:
160   - queryset = whole_queryset
161   - queryset = cls.sort_queryset(queryset, query.sort_rules)
162   - return queryset[0].pk
  141 + # id instancji z search_field rownym mask badz takiej, ktora bylaby nastepna
  142 + # po instancji z search_field równym mask w danym sortowaniu.
  143 + # Jezeli nie ma 'wiekszej' instancji badz reguly sortowania nie uwzgledniaja
  144 + # search_field, metoda zwroci pierwsza instancje w danym sortowaniu
  145 + #
  146 + # beznadziejna nazwa metody...
  147 + @classmethod
  148 + def get_pk(cls, query):
  149 + whole_queryset = cls.apply_filters(query)
  150 + queryset = whole_queryset
  151 + matching = cls.apply_mask(queryset, query.mask, query.sort_rules)
  152 + if matching.count() > 0:
  153 + matching = cls.sort_queryset(matching, query.sort_rules)
  154 + return matching[0].pk
  155 + else:
  156 + #gdy nie ma pasującego
  157 + rule = query.sort_rules[0]
  158 + if rule['field'] == cls.search_field:
  159 + queryset = cls.filter_value(
  160 + queryset, rule, from_value=query.mask, upward=True)
  161 + if queryset.count() == 0:
  162 + queryset = whole_queryset
  163 + queryset = cls.sort_queryset(queryset, query.sort_rules)
  164 + return queryset[0].pk
163 165  
164   - @staticmethod
165   - def get_field_special_case(field, instance):
166   - return False, None
  166 + @staticmethod
  167 + def get_field_special_case(field, instance):
  168 + return False, None
167 169  
168   - @classmethod
169   - def get_field(cls, field, instance):
170   - special, value = cls.get_field_special_case(field, instance)
171   - if not special:
172   - value = getattr(instance, field)
173   - return cls.translate_field(field), value
  170 + @classmethod
  171 + def get_field(cls, field, instance):
  172 + special, value = cls.get_field_special_case(field, instance)
  173 + if not special:
  174 + value = getattr(instance, field)
  175 + return cls.translate_field(field), value
174 176  
175   - # indeks wiersza w danym sortowaniu, w którym
176   - # znajdzie się instancja o danym id
177   - @classmethod
178   - def row_index(cls, pk, query):
179   - selected = cls.model.objects.get(pk=pk)
180   - queryset = cls.apply_filters(query)
181   - if query.filtering_mode():
182   - queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
183   - count = queryset.count()
184   - if count == 0:
185   - return 0, 0
186   - preceding = None
187   - assert len(query.sort_rules) > 0
188   - for rule in query.sort_rules:
189   - field = rule['field']
190   - field, data = cls.get_field(field, selected)
191   - preceding = cls.filter_value(
192   - queryset, rule, from_value=data, upward=False)
193   - return preceding.count(), count
  177 + # indeks wiersza w danym sortowaniu, w którym
  178 + # znajdzie się instancja o danym id
  179 + @classmethod
  180 + def row_index(cls, pk, query):
  181 + selected = cls.model.objects.get(pk=pk)
  182 + queryset = cls.apply_filters(query)
  183 + if query.filtering_mode():
  184 + queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
  185 + count = queryset.count()
  186 + if count == 0:
  187 + return 0, 0
  188 + preceding = None
  189 + assert len(query.sort_rules) > 0
  190 + for rule in query.sort_rules:
  191 + field = rule['field']
  192 + field, data = cls.get_field(field, selected)
  193 + preceding = cls.filter_value(
  194 + queryset, rule, from_value=data, upward=False)
  195 + return preceding.count(), count
194 196  
195   - # też beznadziejna nazwa
196   - @classmethod
197   - def find_id(cls, selected_pk, query):
198   - index, count = cls.row_index(selected_pk, query)
199   - return {
200   - 'rowIndex': index,
201   - 'records': count,
202   - }
  197 + # też beznadziejna nazwa
  198 + @classmethod
  199 + def find_id(cls, selected_pk, query):
  200 + index, count = cls.row_index(selected_pk, query)
  201 + return {
  202 + 'rowIndex': index,
  203 + 'records': count,
  204 + }
203 205  
204   - @classmethod
205   - def get_location(cls, query):
206   - queryset = cls.apply_filters(query)
207   - count = queryset.count()
208   - # nie wiem, czy ma sens - wzorów i tak jest mało, a leksemy są keszowane
209   - if count > 0 and query.mask == '':
210   - return {
211   - 'rowIndex': 0,
212   - 'selected_id': queryset[0].pk,
213   - 'records': count,
214   - }
215   - if query.filtering_mode():
216   - queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
217   - if queryset.count() > 0:
218   - selected_pk = cls.get_pk(query)
219   - index, _count = cls.row_index(selected_pk, query)
220   - else:
221   - index = None
222   - selected_pk = None
223   - return {
224   - 'rowIndex': index,
225   - 'selected_id': selected_pk,
226   - 'records': count,
227   - }
  206 + @classmethod
  207 + def get_location(cls, query):
  208 + queryset = cls.apply_filters(query)
  209 + count = queryset.count()
  210 + # nie wiem, czy ma sens - wzorów i tak jest mało, a leksemy są keszowane
  211 + if count > 0 and query.mask == '':
  212 + return {
  213 + 'rowIndex': 0,
  214 + 'selected_id': queryset[0].pk,
  215 + 'records': count,
  216 + }
  217 + if query.filtering_mode():
  218 + queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
  219 + if queryset.count() > 0:
  220 + selected_pk = cls.get_pk(query)
  221 + index, _count = cls.row_index(selected_pk, query)
  222 + else:
  223 + index = None
  224 + selected_pk = None
  225 + return {
  226 + 'rowIndex': index,
  227 + 'selected_id': selected_pk,
  228 + 'records': count,
  229 + }
228 230  
229   - @classmethod
230   - def get_sorted_queryset(cls, query):
231   - queryset = cls.apply_filters(query)
232   - if query.filtering_mode():
233   - queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
234   - return cls.sort_queryset(queryset, query.sort_rules)
  231 + @classmethod
  232 + def get_sorted_queryset(cls, query):
  233 + queryset = cls.apply_filters(query)
  234 + if query.filtering_mode():
  235 + queryset = cls.apply_mask(queryset, query.mask, query.sort_rules)
  236 + return cls.sort_queryset(queryset, query.sort_rules)
235 237  
236   - @staticmethod
237   - def count_pages(count, page, limit):
238   - total_pages = int(math.ceil(float(count) / limit))
239   - if limit < 0:
240   - limit = 0
241   - page = min(page, total_pages)
242   - start = limit * (page - 1)
243   - start = max(start, 0)
244   - response_rowcount = min(limit, count - start)
245   - return total_pages, start, response_rowcount
  238 + @staticmethod
  239 + def count_pages(count, page, limit):
  240 + total_pages = int(math.ceil(float(count) / limit))
  241 + if limit < 0:
  242 + limit = 0
  243 + page = min(page, total_pages)
  244 + start = limit * (page - 1)
  245 + start = max(start, 0)
  246 + response_rowcount = min(limit, count - start)
  247 + return total_pages, start, response_rowcount
246 248  
247   - @staticmethod
248   - def response_row(instance):
249   - pass # abstract
  249 + @staticmethod
  250 + def response_row(instance):
  251 + pass # abstract
250 252  
251   - @classmethod
252   - def make_response(cls, response_qs, count, page, total_pages):
253   - rows = [{
254   - 'id': instance.pk,
255   - 'cell': cls.response_row(instance),
256   - } for instance in response_qs]
257   - return {
258   - 'page': page,
259   - 'total': total_pages,
260   - 'records': count,
261   - 'rows': rows,
262   - }
  253 + @classmethod
  254 + def make_response(cls, response_qs, count, page, total_pages):
  255 + rows = [{
  256 + 'id': instance.pk,
  257 + 'cell': cls.response_row(instance),
  258 + } for instance in response_qs]
  259 + return {
  260 + 'page': page,
  261 + 'total': total_pages,
  262 + 'records': count,
  263 + 'rows': rows,
  264 + }
263 265  
264   - @classmethod
265   - def get_page(cls, page, limit, query):
266   - queryset = cls.get_sorted_queryset(query)
267   - count = queryset.count()
268   - total_pages, start, response_rowcount = cls.count_pages(count, page, limit)
269   - response_qs = queryset[start:start + response_rowcount]
270   - return cls.make_response(response_qs, count, page, total_pages)
271 266 \ No newline at end of file
  267 + @classmethod
  268 + def get_page(cls, page, limit, query):
  269 + queryset = cls.get_sorted_queryset(query)
  270 + count = queryset.count()
  271 + total_pages, start, response_rowcount = cls.count_pages(count, page,
  272 + limit)
  273 + response_qs = queryset[start:start + response_rowcount]
  274 + return cls.make_response(response_qs, count, page, total_pages)
272 275 \ No newline at end of file
... ...
dictionary/ajax_lexeme_jqgrid.py
... ... @@ -2,60 +2,62 @@
2 2 from hashlib import md5
3 3  
4 4 from django.db.models import Count
  5 +from django.core.cache import cache
  6 +
5 7 from dictionary.models import Lexeme, filter_visible, visible_vocabularies, LexemeInflectionPattern, LexemeAssociation
6 8 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery
7 9 from common.decorators import ajax
8 10 from common.util import bisect_left, reverse, GroupDict, json_encode
9   -from django.core.cache import cache
10   -
11   -class LexemeGrid(JqGridAjax):
12   - model = Lexeme
13   - search_field = 'entry'
14   - field_translation = {
15   - 'part_of_speech': 'part_of_speech__symbol',
16   - }
17   -
18   - @staticmethod
19   - def sort_field_special_case(rule):
20   - if rule['field'] == 'entry' and rule['a_tergo']:
21   - return 'rev'
22   - else:
23   - return rule['field']
24 11  
25   - @staticmethod
26   - def sort_queryset_special_case(queryset, rule):
27   - if rule['field'] == 'entry' and rule['a_tergo']:
28   - return queryset.extra(select={'rev': "reverse(haslo)"})
29   - else:
30   - return queryset
31 12  
32   - @staticmethod
33   - def filter_special_case(filter, lookup, negated, queryset):
34   - field, data = filter['field'], filter['data']
35   - special = False
  13 +class LexemeGrid(JqGridAjax):
  14 + model = Lexeme
  15 + search_field = 'entry'
36 16 field_translation = {
37   - 'form': 'lexemeform__form',
38   - 'lexeme_qualifier': 'qualifiers__pk',
39   - 'lip_qualifier': 'lexemeinflectionpattern__qualifiers__pk',
40   - 'classification_value': 'classificationvalue__pk',
41   - 'pattern_name': 'lexemeinflectionpattern__pattern__name',
42   - 'inflection_characteristic':
43   - 'lexemeinflectionpattern__inflection_characteristic__symbol',
44   - 'containing_vocabulary': 'vocabularies__pk',
45   - 'owner_vocabulary': 'owner_vocabulary__pk',
46   - 'pattern_count': 'pc',
47   - 'ic_count': 'icc',
48   - 'cr_type': 'refs_to__type__pk',
  17 + 'part_of_speech': 'part_of_speech__symbol',
49 18 }
50   - if field == 'pattern_count':
51   - queryset = queryset.annotate(
52   - pc=Count('lexemeinflectionpattern__pattern', distinct=True))
53   - elif field == 'ic_count':
54   - queryset = queryset.annotate(
55   - icc=Count('lexemeinflectionpattern__inflection_characteristic',
56   - distinct=True))
57   - elif field == 'qualifier':
58   - where = '''(
  19 +
  20 + @staticmethod
  21 + def sort_field_special_case(rule):
  22 + if rule['field'] == 'entry' and rule['a_tergo']:
  23 + return 'rev'
  24 + else:
  25 + return rule['field']
  26 +
  27 + @staticmethod
  28 + def sort_queryset_special_case(queryset, rule):
  29 + if rule['field'] == 'entry' and rule['a_tergo']:
  30 + return queryset.extra(select={'rev': "reverse(haslo)"})
  31 + else:
  32 + return queryset
  33 +
  34 + @staticmethod
  35 + def filter_special_case(filter, lookup, negated, queryset):
  36 + field, data = filter['field'], filter['data']
  37 + special = False
  38 + field_translation = {
  39 + 'form': 'lexemeform__form',
  40 + 'lexeme_qualifier': 'qualifiers__pk',
  41 + 'lip_qualifier': 'lexemeinflectionpattern__qualifiers__pk',
  42 + 'classification_value': 'classificationvalue__pk',
  43 + 'pattern_name': 'lexemeinflectionpattern__pattern__name',
  44 + 'inflection_characteristic':
  45 + 'lexemeinflectionpattern__inflection_characteristic__symbol',
  46 + 'containing_vocabulary': 'vocabularies__pk',
  47 + 'owner_vocabulary': 'owner_vocabulary__pk',
  48 + 'pattern_count': 'pc',
  49 + 'ic_count': 'icc',
  50 + 'cr_type': 'refs_to__type__pk',
  51 + }
  52 + if field == 'pattern_count':
  53 + queryset = queryset.annotate(
  54 + pc=Count('lexemeinflectionpattern__pattern', distinct=True))
  55 + elif field == 'ic_count':
  56 + queryset = queryset.annotate(
  57 + icc=Count('lexemeinflectionpattern__inflection_characteristic',
  58 + distinct=True))
  59 + elif field == 'qualifier':
  60 + where = '''(
59 61 exists (
60 62 select * from kwalifikatory_leksemow where lexeme_id = leksemy.id and
61 63 qualifier_id = %s) or
... ... @@ -75,200 +77,209 @@ class LexemeGrid(JqGridAjax):
75 77 where o.l_id = leksemy.id and s.wariant = '1' and
76 78 kz.qualifier_id = %s)
77 79 )'''
78   - if negated:
79   - where = 'not ' + where
80   - queryset = queryset.extra(where=[where], params=[data] * 3)
81   - special = True
82   - return special, field_translation.get(field, field), queryset
83   -
84   - @classmethod
85   - def get_queryset(cls, query):
86   - lexemes = super(LexemeGrid, cls).get_queryset(query)
87   - return filter_visible(lexemes, query.user)
88   -
89   - @staticmethod
90   - def apply_mask(lexemes, mask, sort_rules):
91   - if mask == '':
92   - return lexemes
93   - for rule in sort_rules:
94   - if rule['field'] == 'entry':
95   - if not rule['a_tergo']:
96   - matching_lexemes = lexemes.filter(entry__istartswith=mask)
  80 + if negated:
  81 + where = 'not ' + where
  82 + queryset = queryset.extra(where=[where], params=[data] * 3)
  83 + special = True
  84 + return special, field_translation.get(field, field), queryset
  85 +
  86 + @classmethod
  87 + def get_queryset(cls, query):
  88 + lexemes = super(LexemeGrid, cls).get_queryset(query)
  89 + return filter_visible(lexemes, query.user)
  90 +
  91 + @staticmethod
  92 + def apply_mask(lexemes, mask, sort_rules):
  93 + if mask == '':
  94 + return lexemes
  95 + for rule in sort_rules:
  96 + if rule['field'] == 'entry':
  97 + if not rule['a_tergo']:
  98 + matching_lexemes = lexemes.filter(entry__istartswith=mask)
  99 + else:
  100 + matching_lexemes = lexemes.filter(entry__iendswith=mask)
  101 + break
97 102 else:
98   - matching_lexemes = lexemes.filter(entry__iendswith=mask)
99   - break
100   - else:
101   - matching_lexemes = lexemes.filter(entry__istartswith=mask)
102   - return matching_lexemes
103   -
104   - @staticmethod
105   - def filter_value_special_case(queryset, rule, from_value, greater):
106   - if rule['field'] == 'entry' and rule['a_tergo']:
107   - if greater:
108   - comp = '>='
109   - else:
110   - comp = '<='
111   - queryset = queryset.extra(where=["reverse(haslo) " + comp + " %s"],
112   - params=[reverse(from_value)])
113   - return True, queryset
114   - else:
115   - return False, queryset
  103 + matching_lexemes = lexemes.filter(entry__istartswith=mask)
  104 + return matching_lexemes
  105 +
  106 + @staticmethod
  107 + def filter_value_special_case(queryset, rule, from_value, greater):
  108 + if rule['field'] == 'entry' and rule['a_tergo']:
  109 + if greater:
  110 + comp = '>='
  111 + else:
  112 + comp = '<='
  113 + queryset = queryset.extra(where=["reverse(haslo) " + comp + " %s"],
  114 + params=[reverse(from_value)])
  115 + return True, queryset
  116 + else:
  117 + return False, queryset
  118 +
  119 + @staticmethod
  120 + def get_field_special_case(field, lexeme):
  121 + if field == 'part_of_speech':
  122 + return True, lexeme.part_of_speech.symbol
  123 + else:
  124 + return False, None
  125 +
  126 + @staticmethod
  127 + def response_row(lexeme):
  128 + lip_data = lexeme.lip_data()
  129 + cont_vocabs = '/'.join(v.id for v in lexeme.vocabularies.all())
  130 + return [
  131 + lexeme.id,
  132 + lexeme.entry,
  133 + lexeme.part_of_speech.symbol,
  134 + lip_data['patterns'],
  135 + '', # brak liczby wzorów
  136 + lip_data['inflection_characteristics'],
  137 + '', # brak liczby charfli
  138 + '', # brak formy
  139 + cont_vocabs,
  140 + lexeme.owner_vocabulary.id,
  141 + dict(Lexeme.STATUS_CHOICES).get(lexeme.status),
  142 + '', # brak komentarza
  143 + ]
  144 +
  145 + # indeks wiersza w danym sortowaniu, w którym
  146 + # znajdzie się instancja o danym id
  147 + @classmethod
  148 + def row_index(cls, pk, query):
  149 + pk_list = get_pk_list(query)
  150 + count = len(pk_list)
  151 + if count == 0:
  152 + return 0, 0
  153 + return pk_list.index(pk), count
  154 +
  155 + # id instancji z search_field rownym mask badz takiej, ktora bylaby nastepna
  156 + # po instancji z search_field równym mask w danym sortowaniu.
  157 + # Jezeli nie ma 'wiekszej' instancji badz reguly sortowania nie uwzgledniaja
  158 + # search_field, metoda zwroci pierwsza instancje w danym sortowaniu
  159 + @classmethod
  160 + def get_pk(cls, query):
  161 + pk_list = get_pk_list(query)
  162 + count = len(pk_list)
  163 + if count == 0:
  164 + return None, None, 0
  165 + # nie podoba mi się w ogóle cała ta idea
  166 + sort_rules = query.sort_rules
  167 + assert len(sort_rules) >= 0
  168 + if sort_rules[0]['field'] != cls.search_field:
  169 + selected_pk = super(cls, LexemeGrid).get_pk(query)
  170 + index, count = cls.row_index(selected_pk, query)
  171 + return selected_pk, index, count
  172 +
  173 + index = bisect_left(pk_list, query.mask,
  174 + cmp=make_lexeme_cmp(sort_rules[0]))
  175 + if index == count:
  176 + index -= 1
  177 + return pk_list[index], index, count
  178 +
  179 + @classmethod
  180 + def get_location(cls, query):
  181 + selected_pk, index, count = cls.get_pk(query)
  182 + return {
  183 + 'rowIndex': index,
  184 + 'selected_id': selected_pk,
  185 + 'records': count,
  186 + }
116 187  
117   - @staticmethod
118   - def get_field_special_case(field, lexeme):
119   - if field == 'part_of_speech':
120   - return True, lexeme.part_of_speech.symbol
121   - else:
122   - return False, None
123   -
124   - @staticmethod
125   - def response_row(lexeme):
126   - lip_data = lexeme.lip_data()
127   - cont_vocabs = '/'.join(v.id for v in lexeme.vocabularies.all())
128   - return [
129   - lexeme.id,
130   - lexeme.entry,
131   - lexeme.part_of_speech.symbol,
132   - lip_data['patterns'],
133   - '', # brak liczby wzorów
134   - lip_data['inflection_characteristics'],
135   - '', # brak liczby charfli
136   - '', # brak formy
137   - cont_vocabs,
138   - lexeme.owner_vocabulary.id,
139   - dict(Lexeme.STATUS_CHOICES).get(lexeme.status),
140   - '', # brak komentarza
141   - ]
142   -
143   - # indeks wiersza w danym sortowaniu, w którym
144   - # znajdzie się instancja o danym id
145   - @classmethod
146   - def row_index(cls, pk, query):
147   - pk_list = get_pk_list(query)
148   - count = len(pk_list)
149   - if count == 0:
150   - return 0, 0
151   - return pk_list.index(pk), count
152   -
153   - # id instancji z search_field rownym mask badz takiej, ktora bylaby nastepna
154   - # po instancji z search_field równym mask w danym sortowaniu.
155   - # Jezeli nie ma 'wiekszej' instancji badz reguly sortowania nie uwzgledniaja
156   - # search_field, metoda zwroci pierwsza instancje w danym sortowaniu
157   - @classmethod
158   - def get_pk(cls, query):
159   - pk_list = get_pk_list(query)
160   - count = len(pk_list)
161   - if count == 0:
162   - return None, None, 0
163   - # nie podoba mi się w ogóle cała ta idea
164   - sort_rules = query.sort_rules
165   - assert len(sort_rules) >= 0
166   - if sort_rules[0]['field'] != cls.search_field:
167   - selected_pk = super(cls, LexemeGrid).get_pk(query)
168   - index, count = cls.row_index(selected_pk, query)
169   - return selected_pk, index, count
170   -
171   - index = bisect_left(pk_list, query.mask, cmp=make_lexeme_cmp(sort_rules[0]))
172   - if index == count:
173   - index -= 1
174   - return pk_list[index], index, count
175   -
176   - @classmethod
177   - def get_location(cls, query):
178   - selected_pk, index, count = cls.get_pk(query)
179   - return {
180   - 'rowIndex': index,
181   - 'selected_id': selected_pk,
182   - 'records': count,
183   - }
184 188  
185 189 import locale
  190 +
186 191 locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8')
187 192  
  193 +
188 194 def make_lexeme_cmp(rule):
189   - def lexeme_cmp(pk, mask):
190   - e1 = Lexeme.objects.get(pk=pk).entry
191   - e2 = mask
192   - if rule['a_tergo']:
193   - e1 = reverse(e1)
194   - e2 = reverse(e2)
195   - result = locale.strcoll(e1, e2)
196   - if rule['order'] == 'desc' and e2 != '':
197   - result = -result
198   - return result
199   - return lexeme_cmp
  195 + def lexeme_cmp(pk, mask):
  196 + e1 = Lexeme.objects.get(pk=pk).entry
  197 + e2 = mask
  198 + if rule['a_tergo']:
  199 + e1 = reverse(e1)
  200 + e2 = reverse(e2)
  201 + result = locale.strcoll(e1, e2)
  202 + if rule['order'] == 'desc' and e2 != '':
  203 + result = -result
  204 + return result
  205 +
  206 + return lexeme_cmp
200 207  
201 208 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu
202 209 @ajax(method='get')
203 210 def find_id(request, id, sort_rules, mask, filters=None):
204   - query = JqGridQuery(
205   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
206   - return LexemeGrid.find_id(id, query)
  211 + query = JqGridQuery(
  212 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  213 + return LexemeGrid.find_id(id, query)
207 214  
208 215 # Zapytanie o id oraz indeks pierwszego wiersza przy danym sortowaniu,
209 216 # którego hasło rozpoczyna się od mask.
210 217 # 'selected_id' == None, jeśli takiego nie ma
211 218 @ajax(method='get')
212 219 def get_location(request, sort_rules, mask='', filters=None):
213   - query = JqGridQuery(
214   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
215   - return LexemeGrid.get_location(query)
  220 + query = JqGridQuery(
  221 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  222 + return LexemeGrid.get_location(query)
216 223  
217 224 # twór Miłosza - trzeba kiedyś poprawić
218 225 def cache_key(query):
219   - key = json_encode(query.sort_rules) + json_encode(query.filters)
220   - for vocabulary in visible_vocabularies(query.user):
221   - key += vocabulary.id
222   - if query.filtering_mode():
223   - key += query.mask
224   - return md5(key).hexdigest()
  226 + key = json_encode(query.sort_rules) + json_encode(query.filters)
  227 + for vocabulary in visible_vocabularies(query.user):
  228 + key += vocabulary.id
  229 + if query.filtering_mode():
  230 + key += query.mask
  231 + return md5(key).hexdigest()
  232 +
225 233  
226 234 def get_cached_lexemes(query):
227   - key = cache_key(query)
228   - return cache.get(key)
  235 + key = cache_key(query)
  236 + return cache.get(key)
  237 +
229 238  
230 239 def cache_lexemes(pk_list, query):
231   - key = cache_key(query)
232   - cache.set(key, pk_list)
233   - key_list = cache.get('key_list', [])
234   - if key not in key_list:
235   - key_list.append(key)
236   - cache.set('key_list', key_list)
  240 + key = cache_key(query)
  241 + cache.set(key, pk_list)
  242 + key_list = cache.get('key_list', [])
  243 + if key not in key_list:
  244 + key_list.append(key)
  245 + cache.set('key_list', key_list)
  246 +
237 247  
238 248 def get_pk_list(query, force_reload=False):
239   - if not force_reload:
240   - pk_list = get_cached_lexemes(query)
241   - else:
242   - pk_list = None
243   - if pk_list is None:
244   - lexemes = LexemeGrid.get_sorted_queryset(query)
245   - if 'rev' in lexemes.query.extra_select:
246   - pk_list = list(row[0] for row in lexemes.values_list('pk', 'rev'))
  249 + if not force_reload:
  250 + pk_list = get_cached_lexemes(query)
247 251 else:
248   - #print lexemes.values_list('pk', flat=True).query
249   - pk_list = list(lexemes.values_list('pk', flat=True))
250   - cache_lexemes(pk_list, query)
251   - return pk_list
  252 + pk_list = None
  253 + if pk_list is None:
  254 + lexemes = LexemeGrid.get_sorted_queryset(query)
  255 + if 'rev' in lexemes.query.extra_select:
  256 + pk_list = list(row[0] for row in lexemes.values_list('pk', 'rev'))
  257 + else:
  258 + #print lexemes.values_list('pk', flat=True).query
  259 + pk_list = list(lexemes.values_list('pk', flat=True))
  260 + cache_lexemes(pk_list, query)
  261 + return pk_list
  262 +
252 263  
253 264 @ajax(method='get')
254 265 def get_lexemes(request, page, rows, sort_rules, filters=None, mask='',
255 266 target_page=0, totalrows=0, force_reload=False):
256   - request.session['sort_rules'] = json_encode(sort_rules)
257   - request.session['filters'] = json_encode(filters)
258   - page = target_page or page
259   - limit = totalrows or rows
260   - query = JqGridQuery(
261   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
262   - pk_list = get_pk_list(query, force_reload)
263   - count = len(pk_list)
264   - total_pages, start, response_rowcount = LexemeGrid.count_pages(
265   - count, page, limit)
266   - sublist = pk_list[start:start + response_rowcount]
267   - lexemes_qs = Lexeme.objects.filter(pk__in=sublist).select_related(
268   - 'owner_vocabulary', 'part_of_speech').prefetch_related(
269   - 'lexemeinflectionpattern_set__pattern',
270   - 'lexemeinflectionpattern_set__inflection_characteristic',
271   - 'vocabularies')
272   - lexemes_dict = dict((l.pk, l) for l in lexemes_qs)
273   - lexemes = [lexemes_dict[pk] for pk in sublist]
274   - return LexemeGrid.make_response(lexemes, count, page, total_pages)
  267 + request.session['sort_rules'] = json_encode(sort_rules)
  268 + request.session['filters'] = json_encode(filters)
  269 + page = target_page or page
  270 + limit = totalrows or rows
  271 + query = JqGridQuery(
  272 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  273 + pk_list = get_pk_list(query, force_reload)
  274 + count = len(pk_list)
  275 + total_pages, start, response_rowcount = LexemeGrid.count_pages(
  276 + count, page, limit)
  277 + sublist = pk_list[start:start + response_rowcount]
  278 + lexemes_qs = Lexeme.objects.filter(pk__in=sublist).select_related(
  279 + 'owner_vocabulary', 'part_of_speech').prefetch_related(
  280 + 'lexemeinflectionpattern_set__pattern',
  281 + 'lexemeinflectionpattern_set__inflection_characteristic',
  282 + 'vocabularies')
  283 + lexemes_dict = dict((l.pk, l) for l in lexemes_qs)
  284 + lexemes = [lexemes_dict[pk] for pk in sublist]
  285 + return LexemeGrid.make_response(lexemes, count, page, total_pages)
... ...
dictionary/ajax_lexeme_view.py
... ... @@ -7,552 +7,584 @@ from django.db.models import Max
7 7 from dictionary.ajax_jqgrid import JqGridQuery
8 8 from dictionary.ajax_lexeme_jqgrid import cache_key, get_pk_list
9 9 from dictionary.models import Lexeme, LexemeInflectionPattern, PartOfSpeech, \
10   - Pattern, InflectionCharacteristic, Vocabulary, Qualifier, \
11   - prepare_table, ClassificationValue, CrossReference, TableTemplate, get_root, \
12   - InputLexeme, CrossReferenceType, filter_visible, \
13   - editable_vocabularies, visible_qualifiers, LexemeAttributeValue
  10 + Pattern, InflectionCharacteristic, Vocabulary, Qualifier, \
  11 + prepare_table, ClassificationValue, CrossReference, TableTemplate, get_root, \
  12 + InputLexeme, CrossReferenceType, filter_visible, \
  13 + editable_vocabularies, visible_qualifiers, LexemeAttributeValue
14 14 from dictionary.forms import LexemeEditForm, LIPEditForm, ClassificationForm, \
15   - CrossReferenceForm, ActionFieldForm, ACTION_FIELDS, LexemeOpenAttributeForm, \
16   - LexemeClosedAttributeForm, LexemeMultipleAttributeForm
  15 + CrossReferenceForm, ActionFieldForm, ACTION_FIELDS, LexemeOpenAttributeForm, \
  16 + LexemeClosedAttributeForm, LexemeMultipleAttributeForm
17 17 from common.decorators import render, ajax, AjaxError, render_template
18 18 from common.util import error_messages
19 19  
  20 +
20 21 @ajax(method='get', template='inflection_tables.html')
21 22 def get_inflection_tables(request, variant, lexeme_id):
22   - lexeme = Lexeme.all_objects.get(pk=lexeme_id) # może być nowy
23   - if not lexeme.perm(request.user, 'view'):
24   - raise AjaxError('access denied')
25   - qualifiers = visible_qualifiers(request.user)
26   - tables = lexeme.inflection_tables(variant, qualifiers=qualifiers)
27   - return {
28   - 'tables': tables,
29   - 'lexeme': lexeme,
30   - 'cross_references': lexeme.refs_to.order_by('type__index'),
31   - 'info': lexeme.sgjp_info(),
32   - }
  23 + lexeme = Lexeme.all_objects.get(pk=lexeme_id) # może być nowy
  24 + if not lexeme.perm(request.user, 'view'):
  25 + raise AjaxError('access denied')
  26 + qualifiers = visible_qualifiers(request.user)
  27 + tables = lexeme.inflection_tables(variant, qualifiers=qualifiers)
  28 + return {
  29 + 'tables': tables,
  30 + 'lexeme': lexeme,
  31 + 'cross_references': lexeme.refs_to.order_by('type__index'),
  32 + 'info': lexeme.sgjp_info(),
  33 + }
  34 +
33 35  
34 36 @ajax(method='get', template='inflection_table.html')
35 37 def table_preview(request, lexeme_id, pattern, inflection_characteristic,
36 38 lip_id, entry=None, pos=None):
37   - lexeme = Lexeme.all_objects.get(pk=lexeme_id)
38   - if not lexeme.perm(request.user, 'view'):
39   - raise AjaxError('access denied')
40   - if entry is None:
41   - entry = lexeme.entry
42   - if pos is None:
43   - pos = lexeme.part_of_speech.symbol
44   - try:
45   - pattern = Pattern.objects.get(name=pattern)
46   - inflection_characteristic = InflectionCharacteristic.objects.get(
47   - pk=inflection_characteristic)
48   - if lip_id.startswith('lip_add'):
49   - lip = LexemeInflectionPattern(lexeme=lexeme, index=0)
50   - else:
51   - lip = LexemeInflectionPattern.objects.get(pk=int(lip_id[3:]))
52   - lip.pattern = pattern
53   - lip.inflection_characteristic = inflection_characteristic
54   - lip.root = get_root(entry, pos, pattern, inflection_characteristic)
55   - qualifiers = visible_qualifiers(request.user)
56   - table = lip.inflection_table('0', separated=True, qualifiers=qualifiers,
57   - edit_view=True)
58   - prepare_table(table)
59   - except Pattern.DoesNotExist:
60   - table = None
61   - except TableTemplate.DoesNotExist:
62   - table = None
63   - return {'table': table}
  39 + lexeme = Lexeme.all_objects.get(pk=lexeme_id)
  40 + if not lexeme.perm(request.user, 'view'):
  41 + raise AjaxError('access denied')
  42 + if entry is None:
  43 + entry = lexeme.entry
  44 + if pos is None:
  45 + pos = lexeme.part_of_speech.symbol
  46 + try:
  47 + pattern = Pattern.objects.get(name=pattern)
  48 + inflection_characteristic = InflectionCharacteristic.objects.get(
  49 + pk=inflection_characteristic)
  50 + if lip_id.startswith('lip_add'):
  51 + lip = LexemeInflectionPattern(lexeme=lexeme, index=0)
  52 + else:
  53 + lip = LexemeInflectionPattern.objects.get(pk=int(lip_id[3:]))
  54 + lip.pattern = pattern
  55 + lip.inflection_characteristic = inflection_characteristic
  56 + lip.root = get_root(entry, pos, pattern, inflection_characteristic)
  57 + qualifiers = visible_qualifiers(request.user)
  58 + table = lip.inflection_table('0', separated=True, qualifiers=qualifiers,
  59 + edit_view=True)
  60 + prepare_table(table)
  61 + except Pattern.DoesNotExist:
  62 + table = None
  63 + except TableTemplate.DoesNotExist:
  64 + table = None
  65 + return {'table': table}
  66 +
64 67  
65 68 @ajax(method='get', template="odm_forms.html")
66 69 def odm_forms(request, lexeme_id):
67   - to_return = {}
68   - l = Lexeme.all_objects.get(pk=lexeme_id)
69   - if not l.perm(request.user, 'view'):
70   - raise AjaxError('access denied')
71   - odm_lexemes = []
72   - for l in InputLexeme.objects.filter(entry=l.entry):
73   - odm_lexemes.append(list(l.inputform_set.values_list('form', flat=True)))
74   - to_return['odm_lexemes'] = odm_lexemes
75   - return to_return
  70 + to_return = {}
  71 + l = Lexeme.all_objects.get(pk=lexeme_id)
  72 + if not l.perm(request.user, 'view'):
  73 + raise AjaxError('access denied')
  74 + odm_lexemes = []
  75 + for l in InputLexeme.objects.filter(entry=l.entry):
  76 + odm_lexemes.append(list(l.inputform_set.values_list('form', flat=True)))
  77 + to_return['odm_lexemes'] = odm_lexemes
  78 + return to_return
  79 +
76 80  
77 81 def attribute_forms(l, part_of_speech=None, ics=None):
78   - for attr, v in l.attributes_values(part_of_speech, ics):
79   - if not attr.closed:
80   - form_class = LexemeOpenAttributeForm
81   - elif not attr.multiple:
82   - form_class = LexemeClosedAttributeForm
83   - else:
84   - form_class = LexemeMultipleAttributeForm
85   - prefix = 'attr%s' % attr.pk
86   - yield form_class(attribute=attr, initial_value=v, prefix=prefix)
  82 + for attr, v in l.attributes_values(part_of_speech, ics):
  83 + if not attr.closed:
  84 + form_class = LexemeOpenAttributeForm
  85 + elif not attr.multiple:
  86 + form_class = LexemeClosedAttributeForm
  87 + else:
  88 + form_class = LexemeMultipleAttributeForm
  89 + prefix = 'attr%s' % attr.pk
  90 + yield form_class(attribute=attr, initial_value=v, prefix=prefix)
  91 +
87 92  
88 93 @render_template('extra_attributes.html')
89 94 @ajax(method='get', template='extra_attributes.html')
90 95 def extra_attributes(request, lexeme_id, pos, ics):
91   - l = Lexeme.all_objects.get(pk=lexeme_id)
92   - part_of_speech = PartOfSpeech.objects.get(symbol=pos)
93   - ics = InflectionCharacteristic.objects.filter(pk__in=ics)
94   - return {
95   - 'forms': attribute_forms(
96   - l, part_of_speech=part_of_speech, ics=ics),
97   - }
  96 + l = Lexeme.all_objects.get(pk=lexeme_id)
  97 + part_of_speech = PartOfSpeech.objects.get(symbol=pos)
  98 + ics = InflectionCharacteristic.objects.filter(pk__in=ics)
  99 + return {
  100 + 'forms': attribute_forms(
  101 + l, part_of_speech=part_of_speech, ics=ics),
  102 + }
  103 +
98 104  
99 105 @ajax(method='get')
100 106 def check_attributes(request, lexeme_id, pos, ics):
101   - l = Lexeme.all_objects.get(pk=lexeme_id)
102   - part_of_speech = PartOfSpeech.objects.get(symbol=pos)
103   - ics = InflectionCharacteristic.objects.filter(
104   - part_of_speech=part_of_speech, symbol__in=ics)
105   - attrs = list(l.attributes(part_of_speech, ics).values_list('pk', flat=True))
106   - return {'attrs': attrs}
  107 + l = Lexeme.all_objects.get(pk=lexeme_id)
  108 + part_of_speech = PartOfSpeech.objects.get(symbol=pos)
  109 + ics = InflectionCharacteristic.objects.filter(
  110 + part_of_speech=part_of_speech, symbol__in=ics)
  111 + attrs = list(l.attributes(part_of_speech, ics).values_list('pk', flat=True))
  112 + return {'attrs': attrs}
  113 +
107 114  
108 115 @render_template('lexeme_edit_form.html')
109 116 @ajax(method='get', template='lexeme_edit_form.html')
110 117 def lexeme_edit_form(request, id):
111   - to_return = {}
112   - l = Lexeme.all_objects.get(pk=id) # bo może być świeżo utworzony
113   - if not l.perm(request.user, 'view'):
114   - raise AjaxError('access denied')
115   - editable = l.perm(request.user, 'change')
116   - to_return['editable'] = editable
117   - owner = l.owner_vocabulary
118   -
119   - to_return['attribute_forms'] = attribute_forms(l)
120   -
121   - editable_vocabs = editable_vocabularies(request.user)
122   - ro_owner = owner not in editable_vocabs
123   - to_return['multiple_editable'] = editable and editable_vocabs.count() > 1
124   - if ro_owner:
125   - # nie pokazujemy wszystkich, tylko te z właściciela
126   - ro_qualifiers = l.qualifiers.filter(vocabulary=owner)
127   - else:
128   - ro_qualifiers = []
129   - to_return['owner'] = owner
130   - ro_vocabularies = l.visible_vocabularies(request.user).exclude(
131   - pk=owner.pk).exclude(pk__in=editable_vocabs)
132   - to_return['ro_vocabularies'] = ro_vocabularies
133   - to_return['ro_qualifiers'] = ro_qualifiers
134   -
135   - to_return['form'] = LexemeEditForm(
136   - instance=l, editable=editable, user=request.user)
137   - to_return['id'] = l.pk
138   - to_return['part_of_speech'] = l.part_of_speech.symbol
139   - to_return['classification_forms'] = make_classification_forms(
140   - l, editable=editable)
141   -
142   - lips = l.lexemeinflectionpattern_set.all()
143   - to_return['lip_forms'] = [
144   - (LIPEditForm(
145   - lexeme=l, part_of_speech=l.part_of_speech, instance=lip,
146   - prefix='lip' + str(lip.pk), user=request.user, editable=editable),
147   - lip.qualifiers.filter(vocabulary=owner) if ro_owner else [])
148   - for lip in lips]
149   - crs = l.refs_to.order_by('type__index')
150   - to_return['cross_references'] = crs
151   - return to_return
  118 + to_return = {}
  119 + l = Lexeme.all_objects.get(pk=id) # bo może być świeżo utworzony
  120 + if not l.perm(request.user, 'view'):
  121 + raise AjaxError('access denied')
  122 + editable = l.perm(request.user, 'change')
  123 + to_return['editable'] = editable
  124 + owner = l.owner_vocabulary
  125 +
  126 + to_return['attribute_forms'] = attribute_forms(l)
  127 +
  128 + editable_vocabs = editable_vocabularies(request.user)
  129 + ro_owner = owner not in editable_vocabs
  130 + to_return['multiple_editable'] = editable and editable_vocabs.count() > 1
  131 + if ro_owner:
  132 + # nie pokazujemy wszystkich, tylko te z właściciela
  133 + ro_qualifiers = l.qualifiers.filter(vocabulary=owner)
  134 + else:
  135 + ro_qualifiers = []
  136 + to_return['owner'] = owner
  137 + ro_vocabularies = l.visible_vocabularies(request.user).exclude(
  138 + pk=owner.pk).exclude(pk__in=editable_vocabs)
  139 + to_return['ro_vocabularies'] = ro_vocabularies
  140 + to_return['ro_qualifiers'] = ro_qualifiers
  141 +
  142 + to_return['form'] = LexemeEditForm(
  143 + instance=l, editable=editable, user=request.user)
  144 + to_return['id'] = l.pk
  145 + to_return['part_of_speech'] = l.part_of_speech.symbol
  146 + to_return['classification_forms'] = make_classification_forms(
  147 + l, editable=editable)
  148 +
  149 + lips = l.lexemeinflectionpattern_set.all()
  150 + to_return['lip_forms'] = [
  151 + (LIPEditForm(
  152 + lexeme=l, part_of_speech=l.part_of_speech, instance=lip,
  153 + prefix='lip' + str(lip.pk), user=request.user, editable=editable),
  154 + lip.qualifiers.filter(vocabulary=owner) if ro_owner else [])
  155 + for lip in lips]
  156 + crs = l.refs_to.order_by('type__index')
  157 + to_return['cross_references'] = crs
  158 + return to_return
  159 +
152 160  
153 161 @ajax(method='get')
154 162 def check_classifications(request, owner_id, pos):
155   - part_of_speech = PartOfSpeech.objects.get(symbol=pos)
156   - owner = Vocabulary.objects.get(pk=owner_id)
157   - classifications = owner.classifications.filter(
158   - parts_of_speech=part_of_speech)
159   - return {'classifications': list(classifications.values_list('pk', flat=True))}
  163 + part_of_speech = PartOfSpeech.objects.get(symbol=pos)
  164 + owner = Vocabulary.objects.get(pk=owner_id)
  165 + classifications = owner.classifications.filter(
  166 + parts_of_speech=part_of_speech)
  167 + return {
  168 + 'classifications': list(classifications.values_list('pk', flat=True))}
  169 +
160 170  
161 171 def make_classification_forms(lexeme, vocabulary=None, part_of_speech=None,
162 172 editable=True):
163   - if not vocabulary:
164   - vocabulary = lexeme.owner_vocabulary
165   - if not part_of_speech:
166   - part_of_speech = lexeme.part_of_speech
167   - classifications = vocabulary.classifications.filter(
168   - parts_of_speech=part_of_speech)
169   - classification_forms = []
170   - for c in classifications:
171   - values = lexeme.classification_values(c)
172   - classification_forms.append(
173   - ClassificationForm(
174   - classification=c, values=values, prefix='cl' + str(c.pk),
175   - editable=editable))
176   - return classification_forms
  173 + if not vocabulary:
  174 + vocabulary = lexeme.owner_vocabulary
  175 + if not part_of_speech:
  176 + part_of_speech = lexeme.part_of_speech
  177 + classifications = vocabulary.classifications.filter(
  178 + parts_of_speech=part_of_speech)
  179 + classification_forms = []
  180 + for c in classifications:
  181 + values = lexeme.classification_values(c)
  182 + classification_forms.append(
  183 + ClassificationForm(
  184 + classification=c, values=values, prefix='cl' + str(c.pk),
  185 + editable=editable))
  186 + return classification_forms
  187 +
177 188  
178 189 @render_template('classification_forms.html')
179 190 @ajax(method='get', template='classification_forms.html')
180 191 def classification_forms(request, lexeme_id, vocab_id, pos):
181   - l = Lexeme.objects.get(pk=lexeme_id)
182   - part_of_speech = PartOfSpeech.objects.get(symbol=pos)
183   - if vocab_id:
184   - vocab = Vocabulary.objects.get(pk=vocab_id)
185   - else:
186   - vocab = None
187   - forms = make_classification_forms(l, vocab, part_of_speech)
188   - return {'forms': forms}
  192 + l = Lexeme.objects.get(pk=lexeme_id)
  193 + part_of_speech = PartOfSpeech.objects.get(symbol=pos)
  194 + if vocab_id:
  195 + vocab = Vocabulary.objects.get(pk=vocab_id)
  196 + else:
  197 + vocab = None
  198 + forms = make_classification_forms(l, vocab, part_of_speech)
  199 + return {'forms': forms}
  200 +
189 201  
190 202 @render_template('lexeme_edit_form_row.html')
191 203 @ajax(method='get', template='lexeme_edit_form_row.html')
192 204 def new_lip_edit_row(request, lexeme_id, pos_id, num):
193   - l = Lexeme.all_objects.get(pk=lexeme_id)
194   - if not l.perm(request.user, 'change'):
195   - raise AjaxError('access denied')
196   - if not pos_id:
197   - raise AjaxError(u'Nieokreślona część mowy.')
198   - pos = PartOfSpeech.objects.get(pk=pos_id)
199   - lip_form = LIPEditForm(
200   - lexeme=l, part_of_speech=pos, prefix='lip_add_%s' % num, user=request.user)
201   - return {'lip_form': lip_form, 'editable': True}
  205 + l = Lexeme.all_objects.get(pk=lexeme_id)
  206 + if not l.perm(request.user, 'change'):
  207 + raise AjaxError('access denied')
  208 + if not pos_id:
  209 + raise AjaxError(u'Nieokreślona część mowy.')
  210 + pos = PartOfSpeech.objects.get(pk=pos_id)
  211 + lip_form = LIPEditForm(
  212 + lexeme=l, part_of_speech=pos, prefix='lip_add_%s' % num,
  213 + user=request.user)
  214 + return {'lip_form': lip_form, 'editable': True}
  215 +
202 216  
203 217 @render('cross_reference_row.html')
204 218 @ajax(method='get', encode_result=False)
205 219 def new_cross_reference_row(request, id, pos_id):
206   - l = Lexeme.objects.get(pk=id)
207   - if not l.perm(request.user, 'change'):
208   - raise AjaxError('access denied')
209   - pos = PartOfSpeech.objects.get(pk=pos_id)
210   - cr_form = CrossReferenceForm(lexeme=l, pos=pos, prefix='cr_add_NUM')
211   - return {'cr_form': cr_form, 'editable': True}
  220 + l = Lexeme.objects.get(pk=id)
  221 + if not l.perm(request.user, 'change'):
  222 + raise AjaxError('access denied')
  223 + pos = PartOfSpeech.objects.get(pk=pos_id)
  224 + cr_form = CrossReferenceForm(lexeme=l, pos=pos, prefix='cr_add_NUM')
  225 + return {'cr_form': cr_form, 'editable': True}
  226 +
212 227  
213 228 @ajax(method='post')
214 229 def update_lexeme(request, form_data, mask=''):
215   - form_dict = dict((x['name'], x['value']) for x in form_data)
216   - l = Lexeme.all_objects.get(pk=form_dict['id'])
217   - if not l.perm(request.user, 'view'):
218   - raise AjaxError('access denied')
219   - owner = l.owner_vocabulary
220   - created = l.entry == ''
221   - if not l.perm(request.user, 'change'):
222   - return update_lexeme_qualifiers(
223   - l, request.user, form_dict, form_data)
224   - form = LexemeEditForm(data=form_dict, instance=l, user=request.user)
225   - if form.is_valid():
226   - l = form.save()
227   - l.responsible = request.user
228   - l.deleted = False
229   - l.fix_homonym_number()
230   - l.save()
231   - else:
232   - raise AjaxError(error_messages(form))
233   -
234   - for vocab in editable_vocabularies(request.user):
235   - if vocab != owner:
236   - vocab.set_lexeme(l, vocab in form.cleaned_data['vocabularies'])
237   - new_owner = form.cleaned_data.get('new_owner')
238   - if new_owner and new_owner != owner:
239   - l.change_owner(new_owner)
240   - l.save()
241   - for qualifier in form.fields['qualifiers'].queryset:
242   - qualifier.set_for(l, qualifier in form.cleaned_data['qualifiers'])
243   -
244   - classifications = l.owner_vocabulary.classifications.filter(
245   - parts_of_speech=l.part_of_speech)
246   - for c in classifications:
247   - classification_form = ClassificationForm(
248   - data=form_dict, classification=c, prefix='cl' + str(c.pk))
249   - if classification_form.is_valid():
250   - cvs = ClassificationValue.objects.filter(
251   - pk__in=classification_form.cleaned_data['values'])
252   - l_cvs = l.classification_values(c)
253   - for cv in l_cvs:
254   - if cv.pk not in classification_form.cleaned_data['values']:
255   - cv.remove_lexeme(l)
256   - for cv in cvs:
257   - if cv not in l_cvs:
258   - cv.add_lexeme(l)
  230 + form_dict = dict((x['name'], x['value']) for x in form_data)
  231 + l = Lexeme.all_objects.get(pk=form_dict['id'])
  232 + if not l.perm(request.user, 'view'):
  233 + raise AjaxError('access denied')
  234 + owner = l.owner_vocabulary
  235 + created = l.entry == ''
  236 + if not l.perm(request.user, 'change'):
  237 + return update_lexeme_qualifiers(
  238 + l, request.user, form_dict, form_data)
  239 + form = LexemeEditForm(data=form_dict, instance=l, user=request.user)
  240 + if form.is_valid():
  241 + l = form.save()
  242 + l.responsible = request.user
  243 + l.deleted = False
  244 + l.fix_homonym_number()
  245 + l.save()
259 246 else:
260   - raise AjaxError(error_messages(classification_form))
261   - for cv in l.classificationvalue_set.all():
262   - if cv.classification not in classifications:
263   - cv.remove_lexeme(l)
264   -
265   - extra_attributes = l.attributes()
266   - for attr in extra_attributes:
267   - prefix = 'attr' + str(attr.pk)
268   - attr_values = attr.values.filter(lexemes=l)
269   - if not attr.multiple:
270   - assert len(attr_values) <= 1
271   - if not attr.closed:
272   - attr_form = LexemeOpenAttributeForm(
273   - attribute=attr, data=form_dict, prefix=prefix)
274   - else:
275   - attr_form = LexemeClosedAttributeForm(
276   - attribute=attr, data=form_dict, prefix=prefix)
277   - if attr_form.is_valid():
278   - if not attr.closed:
279   - value = attr_form.cleaned_data['value']
280   - av = LexemeAttributeValue.objects.get_or_create(
281   - attribute=attr, value=value)
  247 + raise AjaxError(error_messages(form))
  248 +
  249 + for vocab in editable_vocabularies(request.user):
  250 + if vocab != owner:
  251 + vocab.set_lexeme(l, vocab in form.cleaned_data['vocabularies'])
  252 + new_owner = form.cleaned_data.get('new_owner')
  253 + if new_owner and new_owner != owner:
  254 + l.change_owner(new_owner)
  255 + l.save()
  256 + for qualifier in form.fields['qualifiers'].queryset:
  257 + qualifier.set_for(l, qualifier in form.cleaned_data['qualifiers'])
  258 +
  259 + classifications = l.owner_vocabulary.classifications.filter(
  260 + parts_of_speech=l.part_of_speech)
  261 + for c in classifications:
  262 + classification_form = ClassificationForm(
  263 + data=form_dict, classification=c, prefix='cl' + str(c.pk))
  264 + if classification_form.is_valid():
  265 + cvs = ClassificationValue.objects.filter(
  266 + pk__in=classification_form.cleaned_data['values'])
  267 + l_cvs = l.classification_values(c)
  268 + for cv in l_cvs:
  269 + if cv.pk not in classification_form.cleaned_data['values']:
  270 + cv.remove_lexeme(l)
  271 + for cv in cvs:
  272 + if cv not in l_cvs:
  273 + cv.add_lexeme(l)
282 274 else:
283   - av = attr_form.cleaned_data['value']
284   - if not attr_values or attr_values.get() != av:
285   - for av1 in attr_values:
286   - av1.remove_lexeme(l)
287   - av.add_lexeme(l)
288   - else:
289   - attr_form = LexemeMultipleAttributeForm(
290   - attribute=attr, data=form_dict, prefix=prefix)
291   - if attr_form.is_valid():
292   - new_values = attr_form.cleaned_data['value']
293   - for av in set(attr_values) - set(new_values):
294   - av.remove_lexeme(l)
295   - for av in set(new_values) - set(attr_values):
296   - av.add_lexeme(l)
297   - for av in l.lexemeattributevalue_set.all():
298   - if av.attribute not in extra_attributes:
299   - av.remove_lexeme(l)
300   -
301   - for prefix in form_dict['deleted']:
302   - pk = int(prefix[3:])
303   - LexemeInflectionPattern.objects.get(pk=pk).delete()
304   - for cr_pk in form_dict['deleted_cr']:
305   - CrossReference.objects.get(pk=cr_pk).delete()
306   - submitted_lips = []
307   - submitted_crs = []
308   - for pair in form_data:
309   - # może (?) się psuć, jeśli jest zły charfl
310   - name = pair['name']
311   - prefix = name.split('-')[0]
312   - if name.startswith('lip') and prefix not in submitted_lips:
313   - submitted_lips.append(prefix)
314   - if prefix.startswith('lip_add'):
315   - lip = LexemeInflectionPattern()
316   - lip.lexeme = l
317   - else:
  275 + raise AjaxError(error_messages(classification_form))
  276 + for cv in l.classificationvalue_set.all():
  277 + if cv.classification not in classifications:
  278 + cv.remove_lexeme(l)
  279 +
  280 + extra_attributes = l.attributes()
  281 + for attr in extra_attributes:
  282 + prefix = 'attr' + str(attr.pk)
  283 + attr_values = attr.values.filter(lexemes=l)
  284 + if not attr.multiple:
  285 + assert len(attr_values) <= 1
  286 + if not attr.closed:
  287 + attr_form = LexemeOpenAttributeForm(
  288 + attribute=attr, data=form_dict, prefix=prefix)
  289 + else:
  290 + attr_form = LexemeClosedAttributeForm(
  291 + attribute=attr, data=form_dict, prefix=prefix)
  292 + if attr_form.is_valid():
  293 + if not attr.closed:
  294 + value = attr_form.cleaned_data['value']
  295 + av = LexemeAttributeValue.objects.get_or_create(
  296 + attribute=attr, value=value)
  297 + else:
  298 + av = attr_form.cleaned_data['value']
  299 + if not attr_values or attr_values.get() != av:
  300 + for av1 in attr_values:
  301 + av1.remove_lexeme(l)
  302 + av.add_lexeme(l)
  303 + else:
  304 + attr_form = LexemeMultipleAttributeForm(
  305 + attribute=attr, data=form_dict, prefix=prefix)
  306 + if attr_form.is_valid():
  307 + new_values = attr_form.cleaned_data['value']
  308 + for av in set(attr_values) - set(new_values):
  309 + av.remove_lexeme(l)
  310 + for av in set(new_values) - set(attr_values):
  311 + av.add_lexeme(l)
  312 + for av in l.lexemeattributevalue_set.all():
  313 + if av.attribute not in extra_attributes:
  314 + av.remove_lexeme(l)
  315 +
  316 + for prefix in form_dict['deleted']:
318 317 pk = int(prefix[3:])
319   - lip = LexemeInflectionPattern.objects.get(pk=pk)
320   - form_dict[prefix + '-qualifiers'] = get_list(
321   - form_data, prefix + '-qualifiers')
322   - lip_form = LIPEditForm(
323   - lexeme=l, part_of_speech=l.part_of_speech, data=form_dict, prefix=prefix,
324   - instance=lip, user=request.user, index=len(submitted_lips))
325   - if lip_form.is_valid():
326   - lip = lip_form.save()
327   - lip.root = l.get_root(lip.pattern, lip.inflection_characteristic)
328   - if lip.root is None:
329   - raise AjaxError(u'Niepasujące zakończenie formy podstawowej.')
330   - for qualifier in lip_form.fields['qualifiers'].queryset:
331   - qualifier.set_for(
332   - lip, qualifier in lip_form.cleaned_data['qualifiers'])
333   - lip.save()
334   - else:
335   - raise AjaxError(error_messages(lip_form))
336   - if name.startswith('cr_add') and prefix not in submitted_crs:
337   - submitted_crs.append(prefix)
338   - cr_form = CrossReferenceForm(data=form_dict, prefix=prefix)
339   - if cr_form.is_valid():
340   - cr_form.save()
341   - else:
342   - raise AjaxError(error_messages(cr_form))
343   - if len(submitted_lips) == 0 and l.status != 'cand':
344   - raise AjaxError(u'Wybierz odmianę lub ustaw status "kandydat".')
345   - l.refresh_forms()
346   - if created:
347   - sort_rules = json.loads(request.session['sort_rules'])
348   - filters = json.loads(request.session['filters'])
349   - query = JqGridQuery(
350   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
351   - key = cache_key(query)
352   - pk_list = cache.get(key)
353   - if pk_list:
354   - pk_list = [l.pk] + pk_list
355   - cache.set(key, pk_list)
356   - return {}
  318 + LexemeInflectionPattern.objects.get(pk=pk).delete()
  319 + for cr_pk in form_dict['deleted_cr']:
  320 + CrossReference.objects.get(pk=cr_pk).delete()
  321 + submitted_lips = []
  322 + submitted_crs = []
  323 + for pair in form_data:
  324 + # może (?) się psuć, jeśli jest zły charfl
  325 + name = pair['name']
  326 + prefix = name.split('-')[0]
  327 + if name.startswith('lip') and prefix not in submitted_lips:
  328 + submitted_lips.append(prefix)
  329 + if prefix.startswith('lip_add'):
  330 + lip = LexemeInflectionPattern()
  331 + lip.lexeme = l
  332 + else:
  333 + pk = int(prefix[3:])
  334 + lip = LexemeInflectionPattern.objects.get(pk=pk)
  335 + form_dict[prefix + '-qualifiers'] = get_list(
  336 + form_data, prefix + '-qualifiers')
  337 + lip_form = LIPEditForm(
  338 + lexeme=l, part_of_speech=l.part_of_speech, data=form_dict,
  339 + prefix=prefix,
  340 + instance=lip, user=request.user, index=len(submitted_lips))
  341 + if lip_form.is_valid():
  342 + lip = lip_form.save()
  343 + lip.root = l.get_root(lip.pattern,
  344 + lip.inflection_characteristic)
  345 + if lip.root is None:
  346 + raise AjaxError(
  347 + u'Niepasujące zakończenie formy podstawowej.')
  348 + for qualifier in lip_form.fields['qualifiers'].queryset:
  349 + qualifier.set_for(
  350 + lip, qualifier in lip_form.cleaned_data['qualifiers'])
  351 + lip.save()
  352 + else:
  353 + raise AjaxError(error_messages(lip_form))
  354 + if name.startswith('cr_add') and prefix not in submitted_crs:
  355 + submitted_crs.append(prefix)
  356 + cr_form = CrossReferenceForm(data=form_dict, prefix=prefix)
  357 + if cr_form.is_valid():
  358 + cr_form.save()
  359 + else:
  360 + raise AjaxError(error_messages(cr_form))
  361 + if len(submitted_lips) == 0 and l.status != 'cand':
  362 + raise AjaxError(u'Wybierz odmianę lub ustaw status "kandydat".')
  363 + l.refresh_forms()
  364 + if created:
  365 + sort_rules = json.loads(request.session['sort_rules'])
  366 + filters = json.loads(request.session['filters'])
  367 + query = JqGridQuery(
  368 + filters=filters, sort_rules=sort_rules, mask=mask,
  369 + user=request.user)
  370 + key = cache_key(query)
  371 + pk_list = cache.get(key)
  372 + if pk_list:
  373 + pk_list = [l.pk] + pk_list
  374 + cache.set(key, pk_list)
  375 + return {}
  376 +
357 377  
358 378 def update_lexeme_qualifiers(lexeme, user, form_dict, form_data):
359   - owner = lexeme.owner_vocabulary
360   - editable_vocabs = editable_vocabularies(user).exclude(pk=owner.pk)
361   - l_editable_vocabs = lexeme.editable_vocabularies(user)
362   - qualifiers = Qualifier.objects.filter(vocabulary__in=l_editable_vocabs)
363   - for qualifier in qualifiers:
364   - qualifier.set_for(
365   - lexeme, unicode(qualifier.pk) in form_dict['qualifiers'])
366   - for vocab in editable_vocabs:
367   - vocab.set_lexeme(lexeme, vocab.pk in form_dict['vocabularies'])
368   - submitted_lips = []
369   - for pair in form_data:
370   - name = pair['name']
371   - prefix = name.split('-')[0]
372   - if name.startswith('lip') and prefix not in submitted_lips:
373   - submitted_lips.append(prefix)
374   - pk = int(prefix[3:])
375   - lip = LexemeInflectionPattern.objects.get(pk=pk)
376   - lip_qualifiers = get_list(form_data, prefix + '-qualifiers')
377   - for qualifier in qualifiers:
378   - qualifier.set_for(lip, unicode(qualifier.pk) in lip_qualifiers)
379   - return {}
  379 + owner = lexeme.owner_vocabulary
  380 + editable_vocabs = editable_vocabularies(user).exclude(pk=owner.pk)
  381 + l_editable_vocabs = lexeme.editable_vocabularies(user)
  382 + qualifiers = Qualifier.objects.filter(vocabulary__in=l_editable_vocabs)
  383 + for qualifier in qualifiers:
  384 + qualifier.set_for(
  385 + lexeme, unicode(qualifier.pk) in form_dict['qualifiers'])
  386 + for vocab in editable_vocabs:
  387 + vocab.set_lexeme(lexeme, vocab.pk in form_dict['vocabularies'])
  388 + submitted_lips = []
  389 + for pair in form_data:
  390 + name = pair['name']
  391 + prefix = name.split('-')[0]
  392 + if name.startswith('lip') and prefix not in submitted_lips:
  393 + submitted_lips.append(prefix)
  394 + pk = int(prefix[3:])
  395 + lip = LexemeInflectionPattern.objects.get(pk=pk)
  396 + lip_qualifiers = get_list(form_data, prefix + '-qualifiers')
  397 + for qualifier in qualifiers:
  398 + qualifier.set_for(lip, unicode(qualifier.pk) in lip_qualifiers)
  399 + return {}
  400 +
380 401  
381 402 def get_list(form_data, name):
382   - return [pair['value'] for pair in form_data if pair['name'] == name]
  403 + return [pair['value'] for pair in form_data if pair['name'] == name]
  404 +
383 405  
384 406 @ajax(method='post')
385 407 def delete_lexeme(request, lexeme_id):
386   - lexeme_id = int(lexeme_id)
387   - l = Lexeme.objects.get(pk=lexeme_id)
388   - if not l.perm(request.user, 'change'):
389   - raise AjaxError('access denied')
390   - l.deleted = True
391   - l.save()
392   - key_list = cache.get('key_list', [])
393   - for key in key_list:
394   - pk_list = cache.get(key)
395   - if pk_list and lexeme_id in pk_list:
396   - pk_list.remove(lexeme_id)
397   - cache.set(key, pk_list)
398   - return {}
  408 + lexeme_id = int(lexeme_id)
  409 + l = Lexeme.objects.get(pk=lexeme_id)
  410 + if not l.perm(request.user, 'change'):
  411 + raise AjaxError('access denied')
  412 + l.deleted = True
  413 + l.save()
  414 + key_list = cache.get('key_list', [])
  415 + for key in key_list:
  416 + pk_list = cache.get(key)
  417 + if pk_list and lexeme_id in pk_list:
  418 + pk_list.remove(lexeme_id)
  419 + cache.set(key, pk_list)
  420 + return {}
  421 +
399 422  
400 423 @ajax(method='get')
401 424 def check_pos(request, pos_id, ic_id):
402   - ic = InflectionCharacteristic.objects.get(pk=ic_id)
403   - if InflectionCharacteristic.objects.filter(
404   - symbol=ic.symbol, part_of_speech__pk=pos_id):
405   - return {'answer': 'yes'}
406   - else:
407   - return {'answer': 'no'}
  425 + ic = InflectionCharacteristic.objects.get(pk=ic_id)
  426 + if InflectionCharacteristic.objects.filter(
  427 + symbol=ic.symbol, part_of_speech__pk=pos_id):
  428 + return {'answer': 'yes'}
  429 + else:
  430 + return {'answer': 'no'}
  431 +
408 432  
409 433 @ajax(method='get')
410 434 def check_pattern(request, pattern_name, ic_id):
411   - lips = LexemeInflectionPattern.objects.filter(
412   - inflection_characteristic__pk=ic_id, pattern__name=pattern_name)
413   - lips = lips.exclude(lexeme__status='cand')
414   - if lips.exists():
415   - return {'answer': 'yes'}
416   - else:
417   - return {'answer': 'no'}
  435 + lips = LexemeInflectionPattern.objects.filter(
  436 + inflection_characteristic__pk=ic_id, pattern__name=pattern_name)
  437 + lips = lips.exclude(lexeme__status='cand')
  438 + if lips.exists():
  439 + return {'answer': 'yes'}
  440 + else:
  441 + return {'answer': 'no'}
  442 +
418 443  
419 444 @ajax(method='get')
420 445 def get_ics(request, pos_id):
421   - return {'ics': list(InflectionCharacteristic.objects.filter(
422   - part_of_speech__pk=pos_id).values_list('pk', 'symbol'))}
  446 + return {'ics': list(InflectionCharacteristic.objects.filter(
  447 + part_of_speech__pk=pos_id).values_list('pk', 'symbol'))}
  448 +
423 449  
424 450 START_ID = 1000000
425 451  
  452 +
426 453 @ajax(method='post')
427 454 def create_lexeme(request, vocab_id):
428   - owner = Vocabulary.objects.get(pk=vocab_id)
429   - if request.user not in owner.all_editors():
430   - raise AjaxError('access denied')
431   - next_id = Lexeme.all_objects.filter(
432   - pk__gte=START_ID).aggregate(Max('id'))['id__max']
433   - next_id = next_id + 1 if next_id else START_ID
434   - l = Lexeme()
435   - l.id = next_id
436   - l.homonym_number = 1 # zanim zostanie faktycznie stworzony
437   - l.part_of_speech = PartOfSpeech.objects.get(symbol='subst')
438   - l.owner_vocabulary = owner
439   - l.status = 'cand'
440   - l.responsible = request.user
441   - l.deleted = True # proste i genialne!
442   - l.save()
443   - owner.add_lexeme(l)
444   - return {'id': l.id}
  455 + owner = Vocabulary.objects.get(pk=vocab_id)
  456 + if request.user not in owner.all_editors():
  457 + raise AjaxError('access denied')
  458 + next_id = Lexeme.all_objects.filter(
  459 + pk__gte=START_ID).aggregate(Max('id'))['id__max']
  460 + next_id = next_id + 1 if next_id else START_ID
  461 + l = Lexeme()
  462 + l.id = next_id
  463 + l.homonym_number = 1 # zanim zostanie faktycznie stworzony
  464 + l.part_of_speech = PartOfSpeech.objects.get(symbol='subst')
  465 + l.owner_vocabulary = owner
  466 + l.status = 'cand'
  467 + l.responsible = request.user
  468 + l.deleted = True # proste i genialne!
  469 + l.save()
  470 + owner.add_lexeme(l)
  471 + return {'id': l.id}
  472 +
445 473  
446 474 @ajax(method='get', login_required=True)
447 475 def homonym_count(request, entry, lexeme_id):
448   - lexemes = Lexeme.objects.filter(entry=entry).exclude(pk=lexeme_id)
449   - lexemes = filter_visible(lexemes, request.user)
450   - return {'count': lexemes.count()}
  476 + lexemes = Lexeme.objects.filter(entry=entry).exclude(pk=lexeme_id)
  477 + lexemes = filter_visible(lexemes, request.user)
  478 + return {'count': lexemes.count()}
  479 +
451 480  
452 481 @ajax(method='get', login_required=True)
453 482 def cr_homonyms(request, entry, cr_type):
454   - cr_type = CrossReferenceType.objects.get(pk=cr_type)
455   - lexemes = Lexeme.objects.filter(entry=entry, part_of_speech=cr_type.to_pos)
456   - lexemes_data = [
457   - {
458   - 'homonym_number': l.homonym_number,
459   - 'lip_data': l.lip_data(),
460   - } for l in lexemes.order_by('homonym_number')
461   - ]
462   - return {'lexemes': lexemes_data}
  483 + cr_type = CrossReferenceType.objects.get(pk=cr_type)
  484 + lexemes = Lexeme.objects.filter(entry=entry, part_of_speech=cr_type.to_pos)
  485 + lexemes_data = [
  486 + {
  487 + 'homonym_number': l.homonym_number,
  488 + 'lip_data': l.lip_data(),
  489 + } for l in lexemes.order_by('homonym_number')
  490 + ]
  491 + return {'lexemes': lexemes_data}
463 492  
464 493  
465 494 @render('new_action_row.html')
466 495 @ajax(method='get', login_required=True, encode_result=False)
467 496 def new_action_row(request):
468   - form = ActionFieldForm(prefix='action_NUM')
469   - return {'form': form}
  497 + form = ActionFieldForm(prefix='action_NUM')
  498 + return {'form': form}
  499 +
470 500  
471 501 @ajax(method='get', login_required=True)
472 502 def dynamic_action_fields(request, field_name):
473   - action_form, value_form = dict(ACTION_FIELDS)[field_name][1:3]
474   - return {
475   - 'action': action_form()['action'].as_widget(),
476   - 'value': value_form(request)['value'].as_widget(),
477   - }
  503 + action_form, value_form = dict(ACTION_FIELDS)[field_name][1:3]
  504 + return {
  505 + 'action': action_form()['action'].as_widget(),
  506 + 'value': value_form(request)['value'].as_widget(),
  507 + }
  508 +
478 509  
479 510 @ajax(method='post', login_required=True)
480 511 def execute_group_actions(request, actions, filters):
481   - if not request.user.has_perm('dictionary.change_lexeme'):
482   - raise AjaxError('access denied')
483   - if isinstance(filters, basestring):
484   - filters = json.loads(filters)
485   - query = JqGridQuery(
486   - filters=filters, sort_rules=[], mask='', user=request.user)
487   - pk_list = get_pk_list(query)
488   - lexemes = Lexeme.objects.filter(pk__in=pk_list)
489   - for l in lexemes:
490   - for action in actions:
491   - field = action['field']
492   - if field == 'status':
493   - # action['type'] == 'set'
494   - l.status = action['value']
495   - elif field == 'using_vocabulary':
496   - vocab = Vocabulary.objects.get(pk=action['value'])
497   - if action['type'] == 'add':
498   - vocab.add_lexeme(l)
499   - else: # 'remove'
500   - if vocab != l.owner_vocabulary:
501   - vocab.remove_lexeme(l)
502   - else: # field == 'lexeme_qualifier'
503   - qual = Qualifier.objects.get(pk=action['value'])
504   - # a co jeśli koliduje z innym?
505   - if action['type'] == 'add':
506   - l.qualifiers.add(qual) #add
507   - else:
508   - l.qualifiers.remove(qual) #add
509   - l.save()
510   - #print repr(actions), repr(filters)
511   - return {}
  512 + if not request.user.has_perm('dictionary.change_lexeme'):
  513 + raise AjaxError('access denied')
  514 + if isinstance(filters, basestring):
  515 + filters = json.loads(filters)
  516 + query = JqGridQuery(
  517 + filters=filters, sort_rules=[], mask='', user=request.user)
  518 + pk_list = get_pk_list(query)
  519 + lexemes = Lexeme.objects.filter(pk__in=pk_list)
  520 + for l in lexemes:
  521 + for action in actions:
  522 + field = action['field']
  523 + if field == 'status':
  524 + # action['type'] == 'set'
  525 + l.status = action['value']
  526 + elif field == 'using_vocabulary':
  527 + vocab = Vocabulary.objects.get(pk=action['value'])
  528 + if action['type'] == 'add':
  529 + vocab.add_lexeme(l)
  530 + else: # 'remove'
  531 + if vocab != l.owner_vocabulary:
  532 + vocab.remove_lexeme(l)
  533 + else: # field == 'lexeme_qualifier'
  534 + qual = Qualifier.objects.get(pk=action['value'])
  535 + # a co jeśli koliduje z innym?
  536 + if action['type'] == 'add':
  537 + l.qualifiers.add(qual) #add
  538 + else:
  539 + l.qualifiers.remove(qual) #add
  540 + l.save()
  541 + #print repr(actions), repr(filters)
  542 + return {}
512 543  
513 544  
514 545 @ajax(method='post')
515 546 def save_columns(request, col_model, col_names, remap):
516   - request.session['colModel'] = col_model
517   - request.session['colNames'] = col_names
518   - request.session['remap'] = remap
519   - return {}
  547 + request.session['colModel'] = col_model
  548 + request.session['colNames'] = col_names
  549 + request.session['remap'] = remap
  550 + return {}
520 551  
521 552  
522 553 @ajax(method='post')
523 554 def add_vocabulary(request, name):
524   - if not request.user.has_perm('dictionary.manage_vocabulary'):
525   - raise AjaxError('access denied')
526   - vocab = Vocabulary.objects.create(id=name)
527   - vocab.managers.add(request.user) #add
528   - return {}
  555 + if not request.user.has_perm('dictionary.manage_vocabulary'):
  556 + raise AjaxError('access denied')
  557 + vocab = Vocabulary.objects.create(id=name)
  558 + vocab.managers.add(request.user) #add
  559 + return {}
529 560  
530 561 # nieużywane
531 562 @ajax(method='get')
532 563 def vocabulary_permissions(request, vocab_id):
533   - if not request.user.has_perm('dictionary.manage_vocabulary'):
534   - raise AjaxError('access denied')
535   - vocab = Vocabulary.objects.get(id=vocab_id)
536   - return {
537   - 'managers': list(vocab.all_managers().values_list('pk', flat=True)),
538   - 'viewers': list(vocab.all_viewers().values_list('pk', flat=True)),
539   - 'editors': list(vocab.editors.values_list('pk', flat=True)),
540   - }
  564 + if not request.user.has_perm('dictionary.manage_vocabulary'):
  565 + raise AjaxError('access denied')
  566 + vocab = Vocabulary.objects.get(id=vocab_id)
  567 + return {
  568 + 'managers': list(vocab.all_managers().values_list('pk', flat=True)),
  569 + 'viewers': list(vocab.all_viewers().values_list('pk', flat=True)),
  570 + 'editors': list(vocab.editors.values_list('pk', flat=True)),
  571 + }
  572 +
541 573  
542 574 @ajax(method='post')
543 575 def set_vocabulary_permission(request, name, vocab_id, perm, on):
544   - if not request.user.has_perm('dictionary.manage_vocabulary'):
545   - raise AjaxError('access denied')
546   - vocab = Vocabulary.objects.get(id=name)
547   - user = User.objects.get(pk=vocab_id)
548   - if perm == 'view':
549   - related_manager = vocab.viewers
550   - elif perm == 'change':
551   - related_manager = vocab.editors
552   - else: # type == 'manage'
553   - related_manager = vocab.managers
554   - if on:
555   - related_manager.add(user) #add
556   - else:
557   - related_manager.remove(user) #add
558   - return {}
559 576 \ No newline at end of file
  577 + if not request.user.has_perm('dictionary.manage_vocabulary'):
  578 + raise AjaxError('access denied')
  579 + vocab = Vocabulary.objects.get(id=name)
  580 + user = User.objects.get(pk=vocab_id)
  581 + if perm == 'view':
  582 + related_manager = vocab.viewers
  583 + elif perm == 'change':
  584 + related_manager = vocab.editors
  585 + else: # type == 'manage'
  586 + related_manager = vocab.managers
  587 + if on:
  588 + related_manager.add(user) #add
  589 + else:
  590 + related_manager.remove(user) #add
  591 + return {}
560 592 \ No newline at end of file
... ...
dictionary/ajax_pattern_view.py
... ... @@ -2,44 +2,44 @@
2 2  
3 3 from common.util import json_encode
4 4 from dictionary.models import Pattern, Ending, BaseFormLabel, PatternType, \
5   - editable_qualifiers, readonly_vocabularies
  5 + editable_qualifiers, readonly_vocabularies
6 6 from dictionary.forms import PatternEditForm, PatternTypeForm, QualifierForm
7 7 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery
8 8 from common.decorators import render, ajax, AjaxError, render_template
9 9  
10 10  
11 11 class PatternGrid(JqGridAjax):
12   - model = Pattern
13   - search_field = 'name'
14   -
15   - @staticmethod
16   - def filter_special_case(filter, lookup, negated, queryset):
17   - field = filter['field']
18   - if field == 'part_of_speech':
19   - field = 'type__lexical_class__symbol'
20   - elif field == 'type':
21   - field = 'type__symbol'
22   - return False, field, queryset
23   -
24   - @staticmethod
25   - def apply_mask(patterns, mask, sort_rules):
26   - return patterns.filter(name__istartswith=mask)
27   -
28   - @staticmethod
29   - def response_row(pattern):
30   - return [
31   - pattern.name,
32   - pattern.type.symbol,
33   - pattern.type.lexical_class.symbol,
34   - ]
  12 + model = Pattern
  13 + search_field = 'name'
  14 +
  15 + @staticmethod
  16 + def filter_special_case(filter, lookup, negated, queryset):
  17 + field = filter['field']
  18 + if field == 'part_of_speech':
  19 + field = 'type__lexical_class__symbol'
  20 + elif field == 'type':
  21 + field = 'type__symbol'
  22 + return False, field, queryset
  23 +
  24 + @staticmethod
  25 + def apply_mask(patterns, mask, sort_rules):
  26 + return patterns.filter(name__istartswith=mask)
  27 +
  28 + @staticmethod
  29 + def response_row(pattern):
  30 + return [
  31 + pattern.name,
  32 + pattern.type.symbol,
  33 + pattern.type.lexical_class.symbol,
  34 + ]
35 35  
36 36  
37 37 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu
38 38 @ajax(method='get')
39 39 def find_id(request, id, sort_rules, mask, filters=None):
40   - query = JqGridQuery(
41   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
42   - return PatternGrid.find_id(id, query)
  40 + query = JqGridQuery(
  41 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  42 + return PatternGrid.find_id(id, query)
43 43  
44 44  
45 45 # Zapytanie o id oraz indeks wiersza przy danym sortowaniu
... ... @@ -47,104 +47,109 @@ def find_id(request, id, sort_rules, mask, filters=None):
47 47 # 'selected_id' < 0, jeśli takiego nie ma
48 48 @ajax(method='get')
49 49 def get_location(request, sort_rules, filters=None, mask=''):
50   - query = JqGridQuery(
51   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
52   - return PatternGrid.get_location(query)
  50 + query = JqGridQuery(
  51 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  52 + return PatternGrid.get_location(query)
53 53  
54 54  
55 55 @ajax(method='get')
56 56 def get_patterns(request, page, rows, sort_rules, filters=None, mask='',
57 57 target_page=0, totalrows=0):
58   - request.session['pattern-sort_rules'] = json_encode(sort_rules)
59   - request.session['pattern-filters'] = json_encode(filters)
60   - page = target_page or page
61   - limit = totalrows or rows
62   - query = JqGridQuery(
63   - filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
64   - return PatternGrid.get_page(page, limit, query)
  58 + request.session['pattern-sort_rules'] = json_encode(sort_rules)
  59 + request.session['pattern-filters'] = json_encode(filters)
  60 + page = target_page or page
  61 + limit = totalrows or rows
  62 + query = JqGridQuery(
  63 + filters=filters, sort_rules=sort_rules, mask=mask, user=request.user)
  64 + return PatternGrid.get_page(page, limit, query)
65 65  
66 66  
67 67 @render_template('pattern_edit_form.html')
68 68 @ajax(method='get', template='pattern_edit_form.html')
69 69 def pattern_edit_form(request, id):
70   - if not request.user.has_perm('dictionary.view_pattern'):
71   - raise AjaxError('access denied')
72   - to_return = {}
73   - p = Pattern.objects.get(pk=id)
74   - editable = request.user.has_perm('dictionary.change_pattern')
75   - to_return['form'] = PatternEditForm(instance=p, editable=editable)
76   - to_return['type_form'] = PatternTypeForm(instance=p.type, editable=editable)
77   - to_return['id'] = p.pk
78   - to_return['editable'] = editable
79   - bfls = p.type.base_form_labels()
80   - ending_groups = dict((bfl, []) for bfl in bfls)
81   - endings = p.endings.order_by('base_form_label', 'index')
82   - for e in endings:
83   - ro_qualifers = e.qualifiers.filter(
84   - vocabulary__in=readonly_vocabularies(request.user))
85   - q_form = QualifierForm(
86   - qualified=e, user=request.user, editable=editable, prefix='end%s' % e.pk)
87   - ending_groups[e.base_form_label].append((e, ro_qualifers, q_form))
88   - to_return['ending_groups'] = ending_groups
89   - return to_return
  70 + if not request.user.has_perm('dictionary.view_pattern'):
  71 + raise AjaxError('access denied')
  72 + to_return = {}
  73 + p = Pattern.objects.get(pk=id)
  74 + editable = request.user.has_perm('dictionary.change_pattern')
  75 + to_return['pattern'] = p
  76 + to_return['form'] = PatternEditForm(instance=p, editable=editable)
  77 + to_return['type_form'] = PatternTypeForm(instance=p.type, editable=editable)
  78 + to_return['editable'] = editable
  79 + bfls = p.type.base_form_labels()
  80 + ending_groups = dict((bfl, []) for bfl in bfls)
  81 + endings = p.endings.order_by('base_form_label', 'index')
  82 + for e in endings:
  83 + ro_qualifers = e.qualifiers.filter(
  84 + vocabulary__in=readonly_vocabularies(request.user))
  85 + q_form = QualifierForm(
  86 + qualified=e, user=request.user, editable=editable,
  87 + prefix='end%s' % e.pk)
  88 + ending_groups[e.base_form_label].append((e, ro_qualifers, q_form))
  89 + to_return['ending_groups'] = ending_groups
  90 + return to_return
90 91  
91 92  
92 93 # mogłoby iść przez js_vars...
93 94 @render('ending_row.html')
94 95 @ajax(method='get', encode_result=False)
95   -def new_ending_row(request):
96   - ending = {'string': '', 'id': 'add-NUM'}
97   - form = QualifierForm(user=request.user, prefix='add-NUM')
98   - return {'ending': ending, 'editable': True, 'form': form}
  96 +def new_ending_row(request, pattern_id):
  97 + p = Pattern.objects.get(id=pattern_id)
  98 + ending = {'string': '', 'id': 'add-NUM'}
  99 + form = QualifierForm(user=request.user, prefix='add-NUM')
  100 + return {'ending': ending, 'editable': True, 'form': form, 'pattern': p}
99 101  
100 102  
101 103 @ajax(method='post')
102 104 def update_pattern(request, form_data):
103   - if not request.user.has_perm('dictionary.change_pattern'):
104   - raise AjaxError('access denied')
105   - form_dict = dict((x['name'], x['value']) for x in form_data)
106   - p = Pattern.objects.get(pk=form_dict['id'])
107   - form = PatternEditForm(data=form_dict, instance=p)
108   - type_form = PatternTypeForm(data=form_dict)
109   - if type_form.is_valid():
110   - type_qs = PatternType.objects.filter(
111   - symbol=type_form.cleaned_data['symbol'],
112   - lexical_class=type_form.cleaned_data['lexical_class'])
113   - else:
114   - raise AjaxError('invalid data')
115   - if form.is_valid() and len(type_qs) == 1:
116   - form.save()
117   - p.type = type_qs[0]
118   - p.save()
119   - for ending_pk in form_dict['deleted']:
120   - Ending.objects.get(pk=int(ending_pk)).delete()
121   - qualifiers = editable_qualifiers(request.user)
122   - for bfl_endings in form_dict['ending_list']:
123   - endings_data = bfl_endings['endings']
124   - bfl = BaseFormLabel.objects.get(symbol=bfl_endings['base_form_label'])
125   - endings = []
126   - for index, ending_data in zip(range(1, len(endings_data) + 1), endings_data):
127   - quals = set(int(q) for q in ending_data['qualifiers'])
128   - if ending_data['id'] == 'add':
129   - ending = Ending.objects.create(
130   - pattern=p, base_form_label=bfl, string=ending_data['string'],
131   - index=index)
132   - else:
133   - ending = Ending.objects.get(pk=int(ending_data['id']))
134   - ending.index = index
135   - ending.string = ending_data['string']
136   - ending.save()
137   - for qualifier in qualifiers:
138   - qualifier.set_for(ending, qualifier.pk in quals)
139   - endings.append(ending)
140   - else:
141   - raise AjaxError('invalid data')
142   - return {}
  105 + if not request.user.has_perm('dictionary.change_pattern'):
  106 + raise AjaxError('access denied')
  107 + form_dict = dict((x['name'], x['value']) for x in form_data)
  108 + p = Pattern.objects.get(pk=form_dict['id'])
  109 + form = PatternEditForm(data=form_dict, instance=p)
  110 + type_form = PatternTypeForm(data=form_dict)
  111 + if type_form.is_valid():
  112 + type_qs = PatternType.objects.filter(
  113 + symbol=type_form.cleaned_data['symbol'],
  114 + lexical_class=type_form.cleaned_data['lexical_class'])
  115 + else:
  116 + raise AjaxError('invalid data')
  117 + if form.is_valid() and len(type_qs) == 1:
  118 + form.save()
  119 + p.type = type_qs[0]
  120 + p.save()
  121 + for ending_pk in form_dict['deleted']:
  122 + Ending.objects.get(pk=int(ending_pk)).delete()
  123 + qualifiers = editable_qualifiers(request.user)
  124 + for bfl_endings in form_dict['ending_list']:
  125 + endings_data = bfl_endings['endings']
  126 + bfl = BaseFormLabel.objects.get(
  127 + symbol=bfl_endings['base_form_label'])
  128 + endings = []
  129 + for index, ending_data in zip(range(1, len(endings_data) + 1),
  130 + endings_data):
  131 + quals = set(int(q) for q in ending_data['qualifiers'])
  132 + if ending_data['id'] == 'add':
  133 + ending = Ending.objects.create(
  134 + pattern=p, base_form_label=bfl,
  135 + string=ending_data['string'],
  136 + index=index)
  137 + else:
  138 + ending = Ending.objects.get(pk=int(ending_data['id']))
  139 + ending.index = index
  140 + ending.string = ending_data['string']
  141 + ending.save()
  142 + for qualifier in qualifiers:
  143 + qualifier.set_for(ending, qualifier.pk in quals)
  144 + endings.append(ending)
  145 + else:
  146 + raise AjaxError('invalid data')
  147 + return {}
143 148  
144 149  
145 150 @ajax(method='post')
146 151 def save_columns(request, col_model, col_names, remap):
147   - request.session['pattern-colModel'] = col_model
148   - request.session['pattern-colNames'] = col_names
149   - request.session['pattern-remap'] = remap
150   - return {}
  152 + request.session['pattern-colModel'] = col_model
  153 + request.session['pattern-colNames'] = col_names
  154 + request.session['pattern-remap'] = remap
  155 + return {}
... ...
dictionary/ajax_prompter.py
... ... @@ -3,82 +3,84 @@
3 3 from common.decorators import render, ajax, AjaxError
4 4 from common.util import suffix, cut_end
5 5 from dictionary.models import Lexeme, LexemeInflectionPattern, Pattern, \
6   - InflectionCharacteristic, prepare_table, visible_vocabularies, get_root, \
7   - ClassificationValue, Classification, filter_visible_lips
  6 + InflectionCharacteristic, prepare_table, visible_vocabularies, get_root, \
  7 + ClassificationValue, Classification, filter_visible_lips
8 8 from dictionary.pattern_blacklist import blacklist
9 9  
10 10 commonness = Classification.objects.get(name=u'pospolitość')
11 11  
12 12 LIP_ROWS = 10
13 13  
  14 +
14 15 def make_list(user, entry, pos, ic, cvs, bl_check):
15   - lips = LexemeInflectionPattern.objects.distinct()
16   - lips = filter_visible_lips(lips, user)
17   - lips = lips.filter(
18   - lexeme__part_of_speech__symbol=pos).exclude(lexeme__status='cand')
19   - if ic:
20   - lips = lips.filter(inflection_characteristic=ic)
21   - if cvs:
22   - lips = lips.filter(lexeme__classificationvalue__in=cvs)
23   - else:
24   - lips = lips.exclude(lexeme__classificationvalue=None)
25   - lips = lips.order_by('lexeme__entry')
26   - feature_sets = set()
27   - bad_inflections = set()
28   - chosen_lips = []
29   - for suf_len in xrange(len(entry), 0, -1):
30   - suf = suffix(entry, suf_len)
31   - suf_lips = lips.filter(lexeme__entry__endswith=suf)
32   - if suf_len < len(entry):
33   - suf1 = suffix(entry, suf_len + 1)
34   - suf_lips = suf_lips.exclude(lexeme__entry__endswith=suf1)
35   - for p0, ic0 in bad_inflections:
36   - suf_lips.exclude(pattern=p0, inflection_characteristic=ic0)
37   - for p0, ic0 in feature_sets:
38   - suf_lips = suf_lips.exclude(
39   - pattern=p0, inflection_characteristic=ic0)
40   - for lip in suf_lips:
41   - #lip = suf_lips[0]
42   - p = lip.pattern
43   - #suf_lips = suf_lips.exclude(pattern=p)
44   - if p.name in blacklist and bl_check: continue
45   - if ic:
46   - l_ic = ic
47   - else:
48   - l_ic = lip.inflection_characteristic
49   - if (p, l_ic) in bad_inflections: continue
50   - if (p, l_ic) in feature_sets: continue
51   - if cvs:
52   - l_cvs = lip.lexeme.classification_values(commonness) & cvs
53   - else:
54   - l_cvs = lip.lexeme.classification_values(commonness)
55   - if get_root(entry, pos, p, l_ic) is not None:
56   - l_root = lip.lexeme.get_root(p, l_ic)
57   - l_end = lip.lexeme.entry[len(l_root):]
58   - l_entry = u'%s·%s' % (l_root, l_end)
59   - if len(l_end) < len(suf):
60   - suf = suffix(l_entry, suf_len + 1)
61   - chosen_lips.append((lip, l_cvs, cut_end(l_entry, suf), suf))
62   - feature_sets.add((p, l_ic))
  16 + lips = LexemeInflectionPattern.objects.distinct()
  17 + lips = filter_visible_lips(lips, user)
  18 + lips = lips.filter(
  19 + lexeme__part_of_speech__symbol=pos).exclude(lexeme__status='cand')
  20 + if ic:
  21 + lips = lips.filter(inflection_characteristic=ic)
  22 + if cvs:
  23 + lips = lips.filter(lexeme__classificationvalue__in=cvs)
  24 + else:
  25 + lips = lips.exclude(lexeme__classificationvalue=None)
  26 + lips = lips.order_by('lexeme__entry')
  27 + feature_sets = set()
  28 + bad_inflections = set()
  29 + chosen_lips = []
  30 + for suf_len in xrange(len(entry), 0, -1):
  31 + suf = suffix(entry, suf_len)
  32 + suf_lips = lips.filter(lexeme__entry__endswith=suf)
  33 + if suf_len < len(entry):
  34 + suf1 = suffix(entry, suf_len + 1)
  35 + suf_lips = suf_lips.exclude(lexeme__entry__endswith=suf1)
  36 + for p0, ic0 in bad_inflections:
  37 + suf_lips.exclude(pattern=p0, inflection_characteristic=ic0)
  38 + for p0, ic0 in feature_sets:
  39 + suf_lips = suf_lips.exclude(
  40 + pattern=p0, inflection_characteristic=ic0)
  41 + for lip in suf_lips:
  42 + #lip = suf_lips[0]
  43 + p = lip.pattern
  44 + #suf_lips = suf_lips.exclude(pattern=p)
  45 + if p.name in blacklist and bl_check: continue
  46 + if ic:
  47 + l_ic = ic
  48 + else:
  49 + l_ic = lip.inflection_characteristic
  50 + if (p, l_ic) in bad_inflections: continue
  51 + if (p, l_ic) in feature_sets: continue
  52 + if cvs:
  53 + l_cvs = lip.lexeme.classification_values(commonness) & cvs
  54 + else:
  55 + l_cvs = lip.lexeme.classification_values(commonness)
  56 + if get_root(entry, pos, p, l_ic) is not None:
  57 + l_root = lip.lexeme.get_root(p, l_ic)
  58 + l_end = lip.lexeme.entry[len(l_root):]
  59 + l_entry = u'%s·%s' % (l_root, l_end)
  60 + if len(l_end) < len(suf):
  61 + suf = suffix(l_entry, suf_len + 1)
  62 + chosen_lips.append((lip, l_cvs, cut_end(l_entry, suf), suf))
  63 + feature_sets.add((p, l_ic))
  64 + if len(chosen_lips) == LIP_ROWS:
  65 + break
  66 + else:
  67 + bad_inflections.add((p, l_ic))
63 68 if len(chosen_lips) == LIP_ROWS:
64   - break
65   - else:
66   - bad_inflections.add((p, l_ic))
67   - if len(chosen_lips) == LIP_ROWS:
68   - break
69   - return chosen_lips
  69 + break
  70 + return chosen_lips
  71 +
70 72  
71 73 @ajax(method='get', template='prompter_list.html')
72 74 def prompter_list(request, entry, pos_id, ic_id, commonness_ids,
73 75 ic_check, cv_check, bl_check):
74   - if ic_check:
75   - ic = InflectionCharacteristic.objects.get(pk=ic_id)
76   - else:
77   - ic = None
78   - if cv_check: # and commonness not in ('undefined', 'None'):
79   - cvs = ClassificationValue.objects.filter(pk__in=commonness_ids)
80   - else:
81   - cvs = None
82   - lips = make_list(request.user, entry, pos_id, ic, cvs, bl_check)
83   - # zakładamy, że symbol == pk
84   - return {'lips': lips}
  76 + if ic_check:
  77 + ic = InflectionCharacteristic.objects.get(pk=ic_id)
  78 + else:
  79 + ic = None
  80 + if cv_check: # and commonness not in ('undefined', 'None'):
  81 + cvs = ClassificationValue.objects.filter(pk__in=commonness_ids)
  82 + else:
  83 + cvs = None
  84 + lips = make_list(request.user, entry, pos_id, ic, cvs, bl_check)
  85 + # zakładamy, że symbol == pk
  86 + return {'lips': lips}
... ...
dictionary/export.py
... ... @@ -7,32 +7,33 @@ from common.util import debug, flatten
7 7 from dictionary.models import CrossReferenceType, ClassificationValue, LexemeAttributeValue
8 8  
9 9 ADJPREDYKATYWNE = [
10   - u'ciekaw',
11   - u'godzien',
12   - u'gotów',
13   - u'łaskaw',
14   - u'świadom',
15   - u'winien',
16   - u'zdrów',
17   -# wątpliwe:
18   - u'dłużen',
19   - u'miłościw',
20   - u'praw',
21   - u'wesół',
22   - u'żyw',
  10 + u'ciekaw',
  11 + u'godzien',
  12 + u'gotów',
  13 + u'łaskaw',
  14 + u'świadom',
  15 + u'winien',
  16 + u'zdrów',
  17 + # wątpliwe:
  18 + u'dłużen',
  19 + u'miłościw',
  20 + u'praw',
  21 + u'wesół',
  22 + u'żyw',
23 23 ]
24 24  
25 25 REFL_TRANSLATION = {
26   - u'—': 'nonrefl',
27   - u'się': 'refl',
28   - u'sobie': 'refl',
29   - u'się/sobie': 'refl',
30   - u'(się)': 'refl.nonrefl',
31   - u'(sobie)': 'refl.nonrefl',
  26 + u'—': 'nonrefl',
  27 + u'się': 'refl',
  28 + u'sobie': 'refl',
  29 + u'się/sobie': 'refl',
  30 + u'(się)': 'refl.nonrefl',
  31 + u'(sobie)': 'refl.nonrefl',
32 32 }
33 33  
  34 +
34 35 def qualifier_clause(q_id):
35   - return '''not exists (
  36 + return '''not exists (
36 37 select * from kwalifikatory_leksemow where lexeme_id = l.id and
37 38 qualifier_id = %(q)d) and not exists (
38 39 select * from kwalifikatory_odmieniasiow where qualifier_id = %(q)d and
... ... @@ -40,8 +41,9 @@ def qualifier_clause(q_id):
40 41 select * from kwalifikatory_zakonczen where qualifier_id = %(q)d and
41 42 ending_id = z.id) and ''' % {'q': q_id}
42 43  
  44 +
43 45 def magic_qualifier_clause():
44   - return '''and not (tag like %s and exists (
  46 + return '''and not (tag like %s and exists (
45 47 select kw.id
46 48 from kwalifikatory kw
47 49 join kwalifikatory_leksemow kwl on kw.id = kwl.qualifier_id
... ... @@ -49,45 +51,45 @@ def magic_qualifier_clause():
49 51  
50 52  
51 53 def export_lexemes(data=None, output_file=None):
52   - if not data:
53   - data = {
54   - 'vocabs': ['PoliMorf'],
55   - 'antivocabs': [],
56   - 'variant': 'Morfeusz',
57   - 'excluding_qualifiers': [],
58   - 'magic_qualifiers': [],
59   - 'refl': False,
60   - 'commonness': False,
61   - }
62   - if output_file is None:
63   - output_file = sys.stdout
64   - vocabs_placeholders = ', '.join('%s' for v in data['vocabs'])
  54 + if not data:
  55 + data = {
  56 + 'vocabs': ['PoliMorf'],
  57 + 'antivocabs': [],
  58 + 'variant': 'Morfeusz',
  59 + 'excluding_qualifiers': [],
  60 + 'magic_qualifiers': [],
  61 + 'refl': False,
  62 + 'commonness': False,
  63 + }
  64 + if output_file is None:
  65 + output_file = sys.stdout
  66 + vocabs_placeholders = ', '.join('%s' for v in data['vocabs'])
65 67  
66   - if data['antivocabs']:
67   - antivocabs_placeholders = ', '.join('%s' for v in data['antivocabs'])
68   - antivocabs_clause = '''not exists (
  68 + if data['antivocabs']:
  69 + antivocabs_placeholders = ', '.join('%s' for v in data['antivocabs'])
  70 + antivocabs_clause = '''not exists (
69 71 select * from leksemy_w_slownikach ls2 where ls2.l_id = l.id
70 72 and ls2.slownik in (%s)) and''' % antivocabs_placeholders
71   - else:
72   - antivocabs_clause = ''
  73 + else:
  74 + antivocabs_clause = ''
73 75  
74   - qualifier_clauses = ''.join(
75   - qualifier_clause(q_id) for q_id in data['excluding_qualifiers'])
76   - magic_qualifier_clauses = ''.join(
77   - magic_qualifier_clause() for pattern, q_id in data['magic_qualifiers'])
  76 + qualifier_clauses = ''.join(
  77 + qualifier_clause(q_id) for q_id in data['excluding_qualifiers'])
  78 + magic_qualifier_clauses = ''.join(
  79 + magic_qualifier_clause() for pattern, q_id in data['magic_qualifiers'])
78 80  
79   - crtypes = ['comadv', 'comadj', 'gerver', 'pactver', 'ppasver']
80   - crtype_ids = CrossReferenceType.objects.filter(
81   - symbol__in=crtypes).values_list('pk', flat=True)
  81 + crtypes = ['comadv', 'comadj', 'gerver', 'pactver', 'ppasver']
  82 + crtype_ids = CrossReferenceType.objects.filter(
  83 + symbol__in=crtypes).values_list('pk', flat=True)
82 84  
83   - cv_ids = ClassificationValue.objects.filter(
84   - classification__name=u'pospolitość').values_list('pk', flat=True)
  85 + cv_ids = ClassificationValue.objects.filter(
  86 + classification__name=u'pospolitość').values_list('pk', flat=True)
85 87  
86   - refls = dict(LexemeAttributeValue.objects.filter(
87   - attribute__name=u'zwrotność').values_list('pk', 'value'))
  88 + refls = dict(LexemeAttributeValue.objects.filter(
  89 + attribute__name=u'zwrotność').values_list('pk', 'value'))
88 90  
89   - cursor = connection.cursor()
90   - query = """
  91 + cursor = connection.cursor()
  92 + query = """
91 93 select distinct haslo, prefiks||rdzen||zak||sufiks, l.pos, ch.charfl, tag,
92 94 l.id as leksem_id, refl.attribute_value_id %(clas_field)s
93 95 from leksemy l
... ... @@ -133,46 +135,46 @@ def export_lexemes(data=None, output_file=None):
133 135 --and g.haslo < 'b'
134 136 order by haslo, leksem_id
135 137 """ % {
136   - 'vocabs': vocabs_placeholders,
137   - 'antivocabs': antivocabs_clause,
138   - 'x_qual': qualifier_clauses,
139   - 'magic': magic_qualifier_clauses,
140   - 'crtype_ids': ', '.join(str(pk) for pk in crtype_ids), # brzydko, oj tam
141   - 'clas_field': ', classification_value_id' if data['commonness'] else '',
142   - 'clas_join':
143   - 'left outer join dictionary_lexemecv wkl '
144   - 'on (wkl.lexeme_id=l.id and wkl.classification_value_id in (%s))'
145   - % ', '.join(str(pk) for pk in cv_ids) if data['commonness'] else '',
146   - 'refl':
147   - 'refl.attribute_value_id in (%s)'
148   - % ', '.join(str(pk) for pk in refls),
  138 + 'vocabs': vocabs_placeholders,
  139 + 'antivocabs': antivocabs_clause,
  140 + 'x_qual': qualifier_clauses,
  141 + 'magic': magic_qualifier_clauses,
  142 + 'crtype_ids': ', '.join(str(pk) for pk in crtype_ids), # brzydko, oj tam
  143 + 'clas_field': ', classification_value_id' if data['commonness'] else '',
  144 + 'clas_join':
  145 + 'left outer join dictionary_lexemecv wkl '
  146 + 'on (wkl.lexeme_id=l.id and wkl.classification_value_id in (%s))'
  147 + % ', '.join(str(pk) for pk in cv_ids) if data['commonness'] else '',
  148 + 'refl':
  149 + 'refl.attribute_value_id in (%s)'
  150 + % ', '.join(str(pk) for pk in refls),
149 151 }
150   - params_part = (list(data['vocabs']) + list(data['antivocabs']) +
151   - [data['variant']])
152   - params = params_part + flatten(data['magic_qualifiers']) + params_part
153   - cursor.execute(query, params)
154   - refl = data['refl']
155   - cv_table = dict(ClassificationValue.objects.values_list('id', 'label'))
156   - for row in cursor:
157   - if data['commonness']:
158   - entry, form, pos, _ic, tag, _id, refl_id, cv_id = row
159   - else:
160   - entry, form, pos, _ic, tag, _id, refl_id = row
161   - form = form.lstrip('+') # odmienne postfiksy
162   - if tag == 'adja':
163   - form = form.rstrip('+')
164   - if tag == 'adjc':
165   - if form not in ADJPREDYKATYWNE:
166   - tag = "adj:sg:nom:m1.m2.m3:pos|adj:sg:acc:m3:pos"
167   - if refl and pos in ('v', 'pact', 'ger'):
168   - if refl_id in refls:
169   - tag += ':' + REFL_TRANSLATION[refls[refl_id]]
170   - else:
171   - debug(entry, u'Nieznana zwrotność: %s' % refl_id)
172   - if data['commonness']:
173   - cv = cv_table[cv_id] if cv_id else ''
174   - output_file.write((u'%s\t%s\t%s\t%s\n' %
175   - (form, entry, tag, cv)).encode('utf-8'))
176   - else:
177   - output_file.write((u'%s\t%s\t%s\n' %
178   - (form, entry, tag)).encode('utf-8'))
  152 + params_part = (list(data['vocabs']) + list(data['antivocabs']) +
  153 + [data['variant']])
  154 + params = params_part + flatten(data['magic_qualifiers']) + params_part
  155 + cursor.execute(query, params)
  156 + refl = data['refl']
  157 + cv_table = dict(ClassificationValue.objects.values_list('id', 'label'))
  158 + for row in cursor:
  159 + if data['commonness']:
  160 + entry, form, pos, _ic, tag, _id, refl_id, cv_id = row
  161 + else:
  162 + entry, form, pos, _ic, tag, _id, refl_id = row
  163 + form = form.lstrip('+') # odmienne postfiksy
  164 + if tag == 'adja':
  165 + form = form.rstrip('+')
  166 + if tag == 'adjc':
  167 + if form not in ADJPREDYKATYWNE:
  168 + tag = "adj:sg:nom:m1.m2.m3:pos|adj:sg:acc:m3:pos"
  169 + if refl and pos in ('v', 'pact', 'ger'):
  170 + if refl_id in refls:
  171 + tag += ':' + REFL_TRANSLATION[refls[refl_id]]
  172 + else:
  173 + debug(entry, u'Nieznana zwrotność: %s' % refl_id)
  174 + if data['commonness']:
  175 + cv = cv_table[cv_id] if cv_id else ''
  176 + output_file.write((u'%s\t%s\t%s\t%s\n' %
  177 + (form, entry, tag, cv)).encode('utf-8'))
  178 + else:
  179 + output_file.write((u'%s\t%s\t%s\n' %
  180 + (form, entry, tag)).encode('utf-8'))
... ...