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,19 +4,21 @@ from django.contrib.auth.models import User, Group
4 from common.decorators import ajax 4 from common.decorators import ajax
5 from dictionary.models import Vocabulary 5 from dictionary.models import Vocabulary
6 6
  7 +
7 @ajax(method='post') 8 @ajax(method='post')
8 def set_group(request, user_id, group_id, set): 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 @ajax(method='post') 19 @ajax(method='post')
18 def save_default_owner(request, vocab_id): 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,35 +3,38 @@
3 import random 3 import random
4 import string 4 import string
5 from django.forms import * 5 from django.forms import *
6 -from django.utils.translation import ugettext_lazy as _  
7 from django.contrib.auth.forms import PasswordResetForm 6 from django.contrib.auth.forms import PasswordResetForm
8 from django.contrib.auth.models import User 7 from django.contrib.auth.models import User
9 from accounts.models import UserSettings 8 from accounts.models import UserSettings
10 9
  10 +
11 class AddUserForm(ModelForm): 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 class SettingsForm(ModelForm): 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 #-*- coding:utf-8 -*- 1 #-*- coding:utf-8 -*-
2 2
3 from django.contrib.auth.models import Permission, Group 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 class Command(BaseCommand): 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 def get_permission(codename): 15 def get_permission(codename):
15 - return Permission.objects.get(codename=codename) 16 + return Permission.objects.get(codename=codename)
  17 +
16 18
17 def create_groups(): 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,92 +5,97 @@ from django.core.management.base import BaseCommand, CommandError
5 from dictionary.models import Vocabulary 5 from dictionary.models import Vocabulary
6 from accounts.models import UserSettings 6 from accounts.models import UserSettings
7 7
  8 +
8 class Command(BaseCommand): 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 def create_users(): 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,15 +3,16 @@
3 from django.contrib.auth.models import User 3 from django.contrib.auth.models import User
4 from django.core.management.base import BaseCommand 4 from django.core.management.base import BaseCommand
5 5
  6 +
6 class Command(BaseCommand): 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 def dummy_passwords(): 15 def dummy_passwords():
15 - for user in User.objects.all():  
16 - user.set_password(user.username)  
17 - user.save()  
18 \ No newline at end of file 16 \ No newline at end of file
  17 + for user in User.objects.all():
  18 + user.set_password(user.username)
  19 + user.save()
19 \ No newline at end of file 20 \ No newline at end of file
accounts/models.py
@@ -6,45 +6,48 @@ from dictionary.models import Vocabulary @@ -6,45 +6,48 @@ from dictionary.models import Vocabulary
6 6
7 MANAGER_GROUPS = ('Obserwator', 'Leksykograf', 'Superleksykograf') 7 MANAGER_GROUPS = ('Obserwator', 'Leksykograf', 'Superleksykograf')
8 8
  9 +
9 def manager_groups(): 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 class UserSettings(Model): 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 def filtering_mode(user): 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,32 +2,33 @@
2 {% load ingroup %} 2 {% load ingroup %}
3 3
4 {% block extrahead %} 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 {% endblock %} 7 {% endblock %}
7 8
8 {% block title %}Role użytkowników{% endblock %} 9 {% block title %}Role użytkowników{% endblock %}
9 10
10 {% block content %} 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 {% endfor %} 32 {% endfor %}
30 - </tr>  
31 - {% endfor %}  
32 - </table> 33 + </table>
33 {% endblock %} 34 {% endblock %}
accounts/templates/registration/activate.html
@@ -4,10 +4,11 @@ @@ -4,10 +4,11 @@
4 4
5 {% block content %} 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 {% endblock %} 14 {% endblock %}
accounts/templates/registration/login.html
@@ -3,32 +3,35 @@ @@ -3,32 +3,35 @@
3 {% load url from future %} 3 {% load url from future %}
4 4
5 {% block content %} 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 {% endblock %} 37 {% endblock %}
accounts/templates/registration/logout.html
@@ -4,8 +4,8 @@ @@ -4,8 +4,8 @@
4 4
5 {% block content %} 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 {% endblock %} 11 {% endblock %}
accounts/templates/registration/password_change_done.html
@@ -2,14 +2,15 @@ @@ -2,14 +2,15 @@
2 {% load i18n %} 2 {% load i18n %}
3 {% load url from future %} 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 {% block title %}{% trans 'Password change successful' %}{% endblock %} 8 {% block title %}{% trans 'Password change successful' %}{% endblock %}
8 9
9 {% block content %} 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 {% endblock %} 16 {% endblock %}
accounts/templates/registration/password_change_form.html
1 {% extends "base.html" %} 1 {% extends "base.html" %}
2 {% load i18n %} 2 {% load i18n %}
3 {% load url from future %} 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 {% block title %}{% trans 'Password change' %}{% endblock %} 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 {% endblock %} 57 {% endblock %}
accounts/templates/registration/password_reset_complete.html
@@ -5,10 +5,10 @@ @@ -5,10 +5,10 @@
5 5
6 {% block content %} 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 {% endblock %} 14 {% endblock %}
accounts/templates/registration/password_reset_confirm.html
@@ -5,26 +5,32 @@ @@ -5,26 +5,32 @@
5 5
6 {% block content %} 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 {% endblock %} 36 {% endblock %}
accounts/templates/registration/password_reset_done.html
@@ -5,8 +5,8 @@ @@ -5,8 +5,8 @@
5 5
6 {% block content %} 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 {% endblock %} 12 {% endblock %}
accounts/templates/registration/password_reset_email.html
1 {% load i18n %}{% load url from future %}{% autoescape off %} 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 {% endautoescape %} 21 {% endautoescape %}
accounts/templates/registration/password_reset_form.html
@@ -5,13 +5,15 @@ @@ -5,13 +5,15 @@
5 5
6 {% block content %} 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 {% endblock %} 19 {% endblock %}
accounts/templates/registration/registration_complete.html
@@ -3,9 +3,10 @@ @@ -3,9 +3,10 @@
3 3
4 {% block content %} 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 {% endblock %} 12 {% endblock %}
accounts/templates/registration/registration_form.html
@@ -3,36 +3,40 @@ @@ -3,36 +3,40 @@
3 {% load url from future %} 3 {% load url from future %}
4 4
5 {% block extrahead %} 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 {% endblock %} 13 {% endblock %}
14 14
15 {% block title %}{% trans 'Registration' %}{% endblock %} 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 {% endblock %} 42 {% endblock %}
accounts/templates/settings.html
@@ -4,16 +4,16 @@ @@ -4,16 +4,16 @@
4 {% block title %}Ustawienia{% endblock %} 4 {% block title %}Ustawienia{% endblock %}
5 5
6 {% block content %} 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 {% endblock %} 19 {% endblock %}
accounts/util.py
@@ -6,13 +6,15 @@ from django.contrib.auth.models import User @@ -6,13 +6,15 @@ from django.contrib.auth.models import User
6 6
7 7
8 def set_history(user): 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 def bot_history(): 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 def users_with_perm(perm): 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 \ No newline at end of file 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 \ No newline at end of file 22 \ No newline at end of file
accounts/views.py
@@ -9,43 +9,47 @@ from accounts.forms import AddUserForm, SettingsForm @@ -9,43 +9,47 @@ from accounts.forms import AddUserForm, SettingsForm
9 from accounts.models import UserSettings, manager_groups 9 from accounts.models import UserSettings, manager_groups
10 from dictionary.models import editable_vocabularies 10 from dictionary.models import editable_vocabularies
11 11
  12 +
12 @permission_required('auth.add_user') 13 @permission_required('auth.add_user')
13 @render('registration/registration_form.html') 14 @render('registration/registration_form.html')
14 def register(request): 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 @login_required 29 @login_required
28 @render() 30 @render()
29 def settings(request): 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 @permission_required('auth.add_user') 46 @permission_required('auth.add_user')
43 @render() 47 @render()
44 def manage_groups(request): 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 # -*- coding: utf-8 -*- 1 # -*- coding: utf-8 -*-
2 2
3 def error_proc(request): 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 def message_proc(request): 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,70 +15,84 @@ from common.util import stringify_keys
15 15
16 16
17 class AjaxError(Exception): 17 class AjaxError(Exception):
18 - pass 18 + pass
  19 +
19 20
20 def json_decode_fallback(value): 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 def ajax(login_required=True, method=None, encode_result=True, template=None): 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 def render(template=None, mimetype=None): 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 # żeby były linki do szablonów w PyCharm przy ajaxach 96 # żeby były linki do szablonów w PyCharm przy ajaxach
83 def render_template(t): 97 def render_template(t):
84 - return lambda x: x  
85 \ No newline at end of file 98 \ No newline at end of file
  99 + return lambda x: x
86 \ No newline at end of file 100 \ No newline at end of file
common/forms.py
@@ -3,12 +3,14 @@ @@ -3,12 +3,14 @@
3 from django import forms 3 from django import forms
4 from django.utils.encoding import force_unicode 4 from django.utils.encoding import force_unicode
5 5
  6 +
6 def hidden_id(id): 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 # http://www.djangosnippets.org/snippets/863/ z moimi zmianami 10 # http://www.djangosnippets.org/snippets/863/ z moimi zmianami
10 class ChoiceWithOtherRenderer(forms.RadioSelect.renderer): 11 class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
11 """RadioFieldRenderer that renders its last choice with a placeholder.""" 12 """RadioFieldRenderer that renders its last choice with a placeholder."""
  13 +
12 def __init__(self, *args, **kwargs): 14 def __init__(self, *args, **kwargs):
13 super(ChoiceWithOtherRenderer, self).__init__(*args, **kwargs) 15 super(ChoiceWithOtherRenderer, self).__init__(*args, **kwargs)
14 self.choices, self.other = self.choices[:-1], self.choices[-1] 16 self.choices, self.other = self.choices[:-1], self.choices[-1]
@@ -16,17 +18,22 @@ class ChoiceWithOtherRenderer(forms.RadioSelect.renderer): @@ -16,17 +18,22 @@ class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
16 def __iter__(self): 18 def __iter__(self):
17 for input in super(ChoiceWithOtherRenderer, self).__iter__(): 19 for input in super(ChoiceWithOtherRenderer, self).__iter__():
18 yield input 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 label_for = ' for="%s"' % id if id else '' 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 yield '<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s' % ( 26 yield '<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s' % (
23 label_for, id, self.other[0], self.name, checked, self.other[1]) 27 label_for, id, self.other[0], self.name, checked, self.other[1])
24 28
  29 +
25 class ChoiceWithOtherWidget(forms.MultiWidget): 30 class ChoiceWithOtherWidget(forms.MultiWidget):
26 """MultiWidget for use with ChoiceWithOtherField.""" 31 """MultiWidget for use with ChoiceWithOtherField."""
  32 +
27 def __init__(self, choices): 33 def __init__(self, choices):
28 widgets = [ 34 widgets = [
29 - forms.RadioSelect(choices=choices, renderer=ChoiceWithOtherRenderer), 35 + forms.RadioSelect(choices=choices,
  36 + renderer=ChoiceWithOtherRenderer),
30 forms.TextInput 37 forms.TextInput
31 ] 38 ]
32 super(ChoiceWithOtherWidget, self).__init__(widgets) 39 super(ChoiceWithOtherWidget, self).__init__(widgets)
@@ -40,20 +47,25 @@ class ChoiceWithOtherWidget(forms.MultiWidget): @@ -40,20 +47,25 @@ class ChoiceWithOtherWidget(forms.MultiWidget):
40 """Format the output by substituting the "other" choice into the first widget.""" 47 """Format the output by substituting the "other" choice into the first widget."""
41 return rendered_widgets[0] % rendered_widgets[1] 48 return rendered_widgets[0] % rendered_widgets[1]
42 49
  50 +
43 class ChoiceWithOtherField(forms.MultiValueField): 51 class ChoiceWithOtherField(forms.MultiValueField):
44 """ 52 """
45 ChoiceField with an option for a user-submitted "other" value. 53 ChoiceField with an option for a user-submitted "other" value.
46 """ 54 """
  55 +
47 def __init__(self, *args, **kwargs): 56 def __init__(self, *args, **kwargs):
48 fields = [ 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 forms.CharField(required=False) 61 forms.CharField(required=False)
51 ] 62 ]
52 widget = ChoiceWithOtherWidget(choices=kwargs['choices']) 63 widget = ChoiceWithOtherWidget(choices=kwargs['choices'])
53 kwargs.pop('choices') 64 kwargs.pop('choices')
54 self._was_required = kwargs.pop('required', True) 65 self._was_required = kwargs.pop('required', True)
55 kwargs['required'] = False 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 def compress(self, value): 70 def compress(self, value):
59 if self._was_required and (not value or value[0] in (None, '')): 71 if self._was_required and (not value or value[0] in (None, '')):
@@ -61,5 +73,6 @@ class ChoiceWithOtherField(forms.MultiValueField): @@ -61,5 +73,6 @@ class ChoiceWithOtherField(forms.MultiValueField):
61 if not value: 73 if not value:
62 return [None, u''] 74 return [None, u'']
63 return (value[0], value[1] 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 \ No newline at end of file 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 \ No newline at end of file 80 \ No newline at end of file
common/middleware.py
1 #-*- coding:utf-8 -*- 1 #-*- coding:utf-8 -*-
2 2
3 -from django.db import connection  
4 from decimal import Decimal 3 from decimal import Decimal
5 4
  5 +from django.db import connection
  6 +
6 from accounts.util import set_history 7 from accounts.util import set_history
7 8
  9 +
8 class MyMiddleware(object): 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 \ No newline at end of file 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 \ No newline at end of file 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 </p> 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 </p> 3 </p>
common/templates/navigation.html
1 {% for menu_item in menu %} 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 {% endfor %} 7 {% endfor %}
8 \ No newline at end of file 8 \ No newline at end of file
common/templatetags/format_date.py
@@ -4,10 +4,12 @@ from django.template import Library @@ -4,10 +4,12 @@ from django.template import Library
4 4
5 register = Library() 5 register = Library()
6 6
  7 +
7 @register.filter 8 @register.filter
8 def format_date(date): 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 @register.filter 13 @register.filter
12 def format_date_exact(date): 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,6 +4,7 @@ from django.template import Library
4 4
5 register = Library() 5 register = Library()
6 6
  7 +
7 @register.filter 8 @register.filter
8 def get(dict, arg): 9 def get(dict, arg):
9 - return dict[arg]  
10 \ No newline at end of file 10 \ No newline at end of file
  11 + return dict[arg]
11 \ No newline at end of file 12 \ No newline at end of file
common/templatetags/ingroup.py
@@ -4,6 +4,7 @@ from django.template import Library @@ -4,6 +4,7 @@ from django.template import Library
4 4
5 register = Library() 5 register = Library()
6 6
  7 +
7 @register.filter 8 @register.filter
8 def ingroup(user, group): 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,6 +9,7 @@ from django.template import Library
9 9
10 register = Library() 10 register = Library()
11 11
  12 +
12 @register.filter 13 @register.filter
13 def jsonify(object): 14 def jsonify(object):
14 if isinstance(object, QuerySet): 15 if isinstance(object, QuerySet):
common/templatetags/script.py
@@ -3,10 +3,12 @@ from django import template @@ -3,10 +3,12 @@ from django import template
3 3
4 register = template.Library() 4 register = template.Library()
5 5
  6 +
6 @register.simple_tag 7 @register.simple_tag
7 def script(): 8 def script():
8 - return '<script type="text/javascript"> /* <![CDATA[ */' 9 + return '<script type="text/javascript"> /* <![CDATA[ */'
  10 +
9 11
10 @register.simple_tag 12 @register.simple_tag
11 def endscript(): 13 def endscript():
12 - return '/* ]]> */ </script>' 14 + return '/* ]]> */ </script>'
common/util.py
@@ -7,96 +7,116 @@ from django.http import HttpResponseRedirect, Http404 @@ -7,96 +7,116 @@ from django.http import HttpResponseRedirect, Http404
7 7
8 8
9 def debug(entry, text): 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 def error_redirect(request, error, url='/'): 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 def message_redirect(request, message, url='/'): 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 def make_form(request, form_class, **kwargs): 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 def invert(l): 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 def generator_slice(generator, count): 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 def url(regex, view, **kwargs): 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 def stringify_keys(dictionary): 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 # copypasta ze standardowego modułu bisect 54 # copypasta ze standardowego modułu bisect
48 def bisect_left(a, x, lo=0, hi=None, cmp=None): 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 def no_history(): 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 def reverse(seq): 78 def reverse(seq):
67 - return seq[::-1] 79 + return seq[::-1]
  80 +
68 81
69 def flatten(seq): 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 def suffix(string, length): 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 def suffixes(s): 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 def cut_end(s, end): 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 def error_messages(form): 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 class GroupDict(dict): 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 def json_encode(obj): 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 def json_decode(obj): 121 def json_decode(obj):
102 - return json.loads(obj)  
103 \ No newline at end of file 122 \ No newline at end of file
  123 + return json.loads(obj)
104 \ No newline at end of file 124 \ No newline at end of file
dictionary/ajax_export.py
@@ -4,42 +4,46 @@ from common.decorators import render, ajax, AjaxError @@ -4,42 +4,46 @@ from common.decorators import render, ajax, AjaxError
4 from dictionary.forms import MagicQualifierForm 4 from dictionary.forms import MagicQualifierForm
5 from dictionary.models import SavedExportData 5 from dictionary.models import SavedExportData
6 6
  7 +
7 @render() 8 @render()
8 @ajax(method='get', encode_result=False) 9 @ajax(method='get', encode_result=False)
9 def magic_qualifier_row(request): 10 def magic_qualifier_row(request):
10 - return {'form': MagicQualifierForm(prefix='magic_NUM')} 11 + return {'form': MagicQualifierForm(prefix='magic_NUM')}
  12 +
11 13
12 @ajax(method='post') 14 @ajax(method='post')
13 def save_export_data(request, name, serialized_data, force=False): 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 else: 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 @ajax(method='get') 33 @ajax(method='get')
31 def get_export_data(request): 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 @ajax(method='post') 44 @ajax(method='post')
41 def delete_export_data(request, data_id): 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,41 +3,44 @@
3 from common.decorators import ajax, AjaxError 3 from common.decorators import ajax, AjaxError
4 from dictionary.models import SavedFilter 4 from dictionary.models import SavedFilter
5 5
  6 +
6 @ajax(method='post') 7 @ajax(method='post')
7 def save_filter(request, name, serialized_filter, super=False, force=False): 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 else: 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 @ajax(method='get') 28 @ajax(method='get')
27 def get_filters(request): 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 @ajax(method='post') 39 @ajax(method='post')
37 def delete_filter(request, id): 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,10 +4,11 @@ from common.decorators import ajax, render_template
4 from dictionary.models import History 4 from dictionary.models import History
5 from dictionary.history import lexeme_tables 5 from dictionary.history import lexeme_tables
6 6
  7 +
7 @render_template('history_table.html') 8 @render_template('history_table.html')
8 @ajax(method='get', template='history_table.html') 9 @ajax(method='get', template='history_table.html')
9 def history_table(request, lexeme_id): 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,267 +4,270 @@ import math
4 from accounts.models import filtering_mode 4 from accounts.models import filtering_mode
5 from common.decorators import render, ajax 5 from common.decorators import render, ajax
6 6
  7 +
7 class JqGridQuery(object): 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 class JqGridAjax(object): 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 \ No newline at end of file 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 \ No newline at end of file 275 \ No newline at end of file
dictionary/ajax_lexeme_jqgrid.py
@@ -2,60 +2,62 @@ @@ -2,60 +2,62 @@
2 from hashlib import md5 2 from hashlib import md5
3 3
4 from django.db.models import Count 4 from django.db.models import Count
  5 +from django.core.cache import cache
  6 +
5 from dictionary.models import Lexeme, filter_visible, visible_vocabularies, LexemeInflectionPattern, LexemeAssociation 7 from dictionary.models import Lexeme, filter_visible, visible_vocabularies, LexemeInflectionPattern, LexemeAssociation
6 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery 8 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery
7 from common.decorators import ajax 9 from common.decorators import ajax
8 from common.util import bisect_left, reverse, GroupDict, json_encode 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 field_translation = { 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 exists ( 61 exists (
60 select * from kwalifikatory_leksemow where lexeme_id = leksemy.id and 62 select * from kwalifikatory_leksemow where lexeme_id = leksemy.id and
61 qualifier_id = %s) or 63 qualifier_id = %s) or
@@ -75,200 +77,209 @@ class LexemeGrid(JqGridAjax): @@ -75,200 +77,209 @@ class LexemeGrid(JqGridAjax):
75 where o.l_id = leksemy.id and s.wariant = '1' and 77 where o.l_id = leksemy.id and s.wariant = '1' and
76 kz.qualifier_id = %s) 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 else: 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 import locale 189 import locale
  190 +
186 locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8') 191 locale.setlocale(locale.LC_ALL, 'pl_PL.UTF-8')
187 192
  193 +
188 def make_lexeme_cmp(rule): 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 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu 208 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu
202 @ajax(method='get') 209 @ajax(method='get')
203 def find_id(request, id, sort_rules, mask, filters=None): 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 # Zapytanie o id oraz indeks pierwszego wiersza przy danym sortowaniu, 215 # Zapytanie o id oraz indeks pierwszego wiersza przy danym sortowaniu,
209 # którego hasło rozpoczyna się od mask. 216 # którego hasło rozpoczyna się od mask.
210 # 'selected_id' == None, jeśli takiego nie ma 217 # 'selected_id' == None, jeśli takiego nie ma
211 @ajax(method='get') 218 @ajax(method='get')
212 def get_location(request, sort_rules, mask='', filters=None): 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 # twór Miłosza - trzeba kiedyś poprawić 224 # twór Miłosza - trzeba kiedyś poprawić
218 def cache_key(query): 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 def get_cached_lexemes(query): 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 def cache_lexemes(pk_list, query): 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 def get_pk_list(query, force_reload=False): 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 else: 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 @ajax(method='get') 264 @ajax(method='get')
254 def get_lexemes(request, page, rows, sort_rules, filters=None, mask='', 265 def get_lexemes(request, page, rows, sort_rules, filters=None, mask='',
255 target_page=0, totalrows=0, force_reload=False): 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,552 +7,584 @@ from django.db.models import Max
7 from dictionary.ajax_jqgrid import JqGridQuery 7 from dictionary.ajax_jqgrid import JqGridQuery
8 from dictionary.ajax_lexeme_jqgrid import cache_key, get_pk_list 8 from dictionary.ajax_lexeme_jqgrid import cache_key, get_pk_list
9 from dictionary.models import Lexeme, LexemeInflectionPattern, PartOfSpeech, \ 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 from dictionary.forms import LexemeEditForm, LIPEditForm, ClassificationForm, \ 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 from common.decorators import render, ajax, AjaxError, render_template 17 from common.decorators import render, ajax, AjaxError, render_template
18 from common.util import error_messages 18 from common.util import error_messages
19 19
  20 +
20 @ajax(method='get', template='inflection_tables.html') 21 @ajax(method='get', template='inflection_tables.html')
21 def get_inflection_tables(request, variant, lexeme_id): 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 @ajax(method='get', template='inflection_table.html') 36 @ajax(method='get', template='inflection_table.html')
35 def table_preview(request, lexeme_id, pattern, inflection_characteristic, 37 def table_preview(request, lexeme_id, pattern, inflection_characteristic,
36 lip_id, entry=None, pos=None): 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 @ajax(method='get', template="odm_forms.html") 68 @ajax(method='get', template="odm_forms.html")
66 def odm_forms(request, lexeme_id): 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 def attribute_forms(l, part_of_speech=None, ics=None): 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 @render_template('extra_attributes.html') 93 @render_template('extra_attributes.html')
89 @ajax(method='get', template='extra_attributes.html') 94 @ajax(method='get', template='extra_attributes.html')
90 def extra_attributes(request, lexeme_id, pos, ics): 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 @ajax(method='get') 105 @ajax(method='get')
100 def check_attributes(request, lexeme_id, pos, ics): 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 @render_template('lexeme_edit_form.html') 115 @render_template('lexeme_edit_form.html')
109 @ajax(method='get', template='lexeme_edit_form.html') 116 @ajax(method='get', template='lexeme_edit_form.html')
110 def lexeme_edit_form(request, id): 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 @ajax(method='get') 161 @ajax(method='get')
154 def check_classifications(request, owner_id, pos): 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 def make_classification_forms(lexeme, vocabulary=None, part_of_speech=None, 171 def make_classification_forms(lexeme, vocabulary=None, part_of_speech=None,
162 editable=True): 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 @render_template('classification_forms.html') 189 @render_template('classification_forms.html')
179 @ajax(method='get', template='classification_forms.html') 190 @ajax(method='get', template='classification_forms.html')
180 def classification_forms(request, lexeme_id, vocab_id, pos): 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 @render_template('lexeme_edit_form_row.html') 202 @render_template('lexeme_edit_form_row.html')
191 @ajax(method='get', template='lexeme_edit_form_row.html') 203 @ajax(method='get', template='lexeme_edit_form_row.html')
192 def new_lip_edit_row(request, lexeme_id, pos_id, num): 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 @render('cross_reference_row.html') 217 @render('cross_reference_row.html')
204 @ajax(method='get', encode_result=False) 218 @ajax(method='get', encode_result=False)
205 def new_cross_reference_row(request, id, pos_id): 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 @ajax(method='post') 228 @ajax(method='post')
214 def update_lexeme(request, form_data, mask=''): 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 else: 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 else: 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 pk = int(prefix[3:]) 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 def update_lexeme_qualifiers(lexeme, user, form_dict, form_data): 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 def get_list(form_data, name): 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 @ajax(method='post') 406 @ajax(method='post')
385 def delete_lexeme(request, lexeme_id): 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 @ajax(method='get') 423 @ajax(method='get')
401 def check_pos(request, pos_id, ic_id): 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 @ajax(method='get') 433 @ajax(method='get')
410 def check_pattern(request, pattern_name, ic_id): 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 @ajax(method='get') 444 @ajax(method='get')
420 def get_ics(request, pos_id): 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 START_ID = 1000000 450 START_ID = 1000000
425 451
  452 +
426 @ajax(method='post') 453 @ajax(method='post')
427 def create_lexeme(request, vocab_id): 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 @ajax(method='get', login_required=True) 474 @ajax(method='get', login_required=True)
447 def homonym_count(request, entry, lexeme_id): 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 @ajax(method='get', login_required=True) 481 @ajax(method='get', login_required=True)
453 def cr_homonyms(request, entry, cr_type): 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 @render('new_action_row.html') 494 @render('new_action_row.html')
466 @ajax(method='get', login_required=True, encode_result=False) 495 @ajax(method='get', login_required=True, encode_result=False)
467 def new_action_row(request): 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 @ajax(method='get', login_required=True) 501 @ajax(method='get', login_required=True)
472 def dynamic_action_fields(request, field_name): 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 @ajax(method='post', login_required=True) 510 @ajax(method='post', login_required=True)
480 def execute_group_actions(request, actions, filters): 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 @ajax(method='post') 545 @ajax(method='post')
515 def save_columns(request, col_model, col_names, remap): 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 @ajax(method='post') 553 @ajax(method='post')
523 def add_vocabulary(request, name): 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 # nieużywane 561 # nieużywane
531 @ajax(method='get') 562 @ajax(method='get')
532 def vocabulary_permissions(request, vocab_id): 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 @ajax(method='post') 574 @ajax(method='post')
543 def set_vocabulary_permission(request, name, vocab_id, perm, on): 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 \ No newline at end of file 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 \ No newline at end of file 592 \ No newline at end of file
dictionary/ajax_pattern_view.py
@@ -2,44 +2,44 @@ @@ -2,44 +2,44 @@
2 2
3 from common.util import json_encode 3 from common.util import json_encode
4 from dictionary.models import Pattern, Ending, BaseFormLabel, PatternType, \ 4 from dictionary.models import Pattern, Ending, BaseFormLabel, PatternType, \
5 - editable_qualifiers, readonly_vocabularies 5 + editable_qualifiers, readonly_vocabularies
6 from dictionary.forms import PatternEditForm, PatternTypeForm, QualifierForm 6 from dictionary.forms import PatternEditForm, PatternTypeForm, QualifierForm
7 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery 7 from dictionary.ajax_jqgrid import JqGridAjax, JqGridQuery
8 from common.decorators import render, ajax, AjaxError, render_template 8 from common.decorators import render, ajax, AjaxError, render_template
9 9
10 10
11 class PatternGrid(JqGridAjax): 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 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu 37 # Zapytanie o indeks wiersza o pewnym id przy danym sortowaniu
38 @ajax(method='get') 38 @ajax(method='get')
39 def find_id(request, id, sort_rules, mask, filters=None): 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 # Zapytanie o id oraz indeks wiersza przy danym sortowaniu 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,104 +47,109 @@ def find_id(request, id, sort_rules, mask, filters=None):
47 # 'selected_id' < 0, jeśli takiego nie ma 47 # 'selected_id' < 0, jeśli takiego nie ma
48 @ajax(method='get') 48 @ajax(method='get')
49 def get_location(request, sort_rules, filters=None, mask=''): 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 @ajax(method='get') 55 @ajax(method='get')
56 def get_patterns(request, page, rows, sort_rules, filters=None, mask='', 56 def get_patterns(request, page, rows, sort_rules, filters=None, mask='',
57 target_page=0, totalrows=0): 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 @render_template('pattern_edit_form.html') 67 @render_template('pattern_edit_form.html')
68 @ajax(method='get', template='pattern_edit_form.html') 68 @ajax(method='get', template='pattern_edit_form.html')
69 def pattern_edit_form(request, id): 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 # mogłoby iść przez js_vars... 93 # mogłoby iść przez js_vars...
93 @render('ending_row.html') 94 @render('ending_row.html')
94 @ajax(method='get', encode_result=False) 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 @ajax(method='post') 103 @ajax(method='post')
102 def update_pattern(request, form_data): 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 @ajax(method='post') 150 @ajax(method='post')
146 def save_columns(request, col_model, col_names, remap): 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,82 +3,84 @@
3 from common.decorators import render, ajax, AjaxError 3 from common.decorators import render, ajax, AjaxError
4 from common.util import suffix, cut_end 4 from common.util import suffix, cut_end
5 from dictionary.models import Lexeme, LexemeInflectionPattern, Pattern, \ 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 from dictionary.pattern_blacklist import blacklist 8 from dictionary.pattern_blacklist import blacklist
9 9
10 commonness = Classification.objects.get(name=u'pospolitość') 10 commonness = Classification.objects.get(name=u'pospolitość')
11 11
12 LIP_ROWS = 10 12 LIP_ROWS = 10
13 13
  14 +
14 def make_list(user, entry, pos, ic, cvs, bl_check): 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 if len(chosen_lips) == LIP_ROWS: 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 @ajax(method='get', template='prompter_list.html') 73 @ajax(method='get', template='prompter_list.html')
72 def prompter_list(request, entry, pos_id, ic_id, commonness_ids, 74 def prompter_list(request, entry, pos_id, ic_id, commonness_ids,
73 ic_check, cv_check, bl_check): 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,32 +7,33 @@ from common.util import debug, flatten
7 from dictionary.models import CrossReferenceType, ClassificationValue, LexemeAttributeValue 7 from dictionary.models import CrossReferenceType, ClassificationValue, LexemeAttributeValue
8 8
9 ADJPREDYKATYWNE = [ 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 REFL_TRANSLATION = { 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 def qualifier_clause(q_id): 35 def qualifier_clause(q_id):
35 - return '''not exists ( 36 + return '''not exists (
36 select * from kwalifikatory_leksemow where lexeme_id = l.id and 37 select * from kwalifikatory_leksemow where lexeme_id = l.id and
37 qualifier_id = %(q)d) and not exists ( 38 qualifier_id = %(q)d) and not exists (
38 select * from kwalifikatory_odmieniasiow where qualifier_id = %(q)d and 39 select * from kwalifikatory_odmieniasiow where qualifier_id = %(q)d and
@@ -40,8 +41,9 @@ def qualifier_clause(q_id): @@ -40,8 +41,9 @@ def qualifier_clause(q_id):
40 select * from kwalifikatory_zakonczen where qualifier_id = %(q)d and 41 select * from kwalifikatory_zakonczen where qualifier_id = %(q)d and
41 ending_id = z.id) and ''' % {'q': q_id} 42 ending_id = z.id) and ''' % {'q': q_id}
42 43
  44 +
43 def magic_qualifier_clause(): 45 def magic_qualifier_clause():
44 - return '''and not (tag like %s and exists ( 46 + return '''and not (tag like %s and exists (
45 select kw.id 47 select kw.id
46 from kwalifikatory kw 48 from kwalifikatory kw
47 join kwalifikatory_leksemow kwl on kw.id = kwl.qualifier_id 49 join kwalifikatory_leksemow kwl on kw.id = kwl.qualifier_id
@@ -49,45 +51,45 @@ def magic_qualifier_clause(): @@ -49,45 +51,45 @@ def magic_qualifier_clause():
49 51
50 52
51 def export_lexemes(data=None, output_file=None): 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 select * from leksemy_w_slownikach ls2 where ls2.l_id = l.id 71 select * from leksemy_w_slownikach ls2 where ls2.l_id = l.id
70 and ls2.slownik in (%s)) and''' % antivocabs_placeholders 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 select distinct haslo, prefiks||rdzen||zak||sufiks, l.pos, ch.charfl, tag, 93 select distinct haslo, prefiks||rdzen||zak||sufiks, l.pos, ch.charfl, tag,
92 l.id as leksem_id, refl.attribute_value_id %(clas_field)s 94 l.id as leksem_id, refl.attribute_value_id %(clas_field)s
93 from leksemy l 95 from leksemy l
@@ -133,46 +135,46 @@ def export_lexemes(data=None, output_file=None): @@ -133,46 +135,46 @@ def export_lexemes(data=None, output_file=None):
133 --and g.haslo < 'b' 135 --and g.haslo < 'b'
134 order by haslo, leksem_id 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'))