Commit 68957fea187ef209cfcaa5d4a300e882f09190e8
0 parents
Initial commit.
Showing
704 changed files
with
200055 additions
and
0 deletions
Too many changes to show.
To preserve performance only 28 of 704 files are displayed.
INSTALL
0 → 100644
1 | +++ a/INSTALL | |
1 | +Slowal installation guide: | |
2 | +To run Slowal you will need at least: | |
3 | + - python (tested on 2.7 version); | |
4 | + - django with django-registration (tested on version 0.7) and django-extensions packages; | |
5 | + - database system (tested on PostgreSQL 9.1); | |
6 | + - morphological analyser Morfeusz (http://sgjp.pl/morfeusz/). | |
7 | + | |
8 | + Slowal can be installed on production server as any other Django application. Comprehensive tutorial for setting Django on production server can be found at: http://bailey.st/blog/2012/05/02/ubuntu-django-postgresql-and-nginx-a-rock-solid-web-stack/. Tutorial can also be helpful for setting database for Slowal project. | |
9 | + | |
10 | +Installation: | |
11 | + 1) Change database_data.py file to get connection to yours database (see: http://bailey.st/blog/2012/05/02/ubuntu-django-postgresql-and-nginx-a-rock-solid-web-stack/ for hints). | |
12 | +When you are creating database it is important to make database coding 'utf8' and locale Polish. | |
13 | +In PostgreSQL such database would be created by command: | |
14 | +>>> createdb databaseName -E UTF8 -T template0 -l pl_PL.utf8 | |
15 | + 2) If you want to run Slowal in the domain subfolder change SITE_PREFIX = '' value to other, for example SITE_PREFIX = '/Slowal' | |
16 | + 3) Create database table running: | |
17 | +>>> python manage.py syncdb | |
18 | +command in the main folder of project. Remember to create superuser it will help you in managing database and give access to all Slowal functionalities. | |
19 | + 4) Fill database with initial values running: | |
20 | +>>> python manage.py import_models | |
21 | +command in the main folder of project. | |
22 | + 5) Create default user groups running: | |
23 | +>>> python manage.py create_groups.py | |
24 | +command in the main folder of project. | |
25 | + 6) Slowal is ready to run. | |
26 | + | |
27 | +Slowal was tested on Safari, Opera, Firefox and Chrome web browsers. Working on Internet Explorer compatibility is still in progress | |
... | ... |
LICENSE
0 → 100644
1 | +++ a/LICENSE | |
1 | +Copyright (c) 2012, Bartłomiej Nitoń | |
2 | +All rights reserved. | |
3 | + | |
4 | +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | |
5 | + | |
6 | + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. | |
7 | + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
8 | + | |
9 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
... | ... |
__init__.py
0 → 100644
1 | +++ a/__init__.py | |
... | ... |
accounts/__init__.py
0 → 100644
1 | +++ a/accounts/__init__.py | |
... | ... |
accounts/admin.py
0 → 100644
1 | +++ a/accounts/admin.py | |
1 | +#-*- coding:utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +#THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +#WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +#PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +#ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +#TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +#HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +#NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +#POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.contrib import admin | |
24 | +from django.contrib.sessions.models import Session | |
25 | + | |
26 | +from models import AnonymousUserProfile, RealizedLemma, GroupSettings, \ | |
27 | + RealizedPhraseology, RealizedPhraseologyBinding, \ | |
28 | + RealizedSemantics, UserSettings, UserStats | |
29 | + | |
30 | +class RealizedLemmaAdmin(admin.ModelAdmin): | |
31 | + search_fields = ('lemma__entry',) | |
32 | + list_filter = ('status', 'paid', 'lemma__vocabulary', 'bonus', 'counted',) | |
33 | + | |
34 | +class RealizedPhraseologyAdmin(admin.ModelAdmin): | |
35 | + search_fields = ('lemma__entry',) | |
36 | + list_filter = ('status', 'paid', 'lemma__vocabulary', 'bonus', 'counted',) | |
37 | + | |
38 | +class RealizedSemanticsAdmin(admin.ModelAdmin): | |
39 | + search_fields = ('entry__name',) | |
40 | + list_filter = ('status', 'bonus', ) | |
41 | + | |
42 | +class UserStatsAdmin(admin.ModelAdmin): | |
43 | + exclude = ('lemma_real_history', 'phraseology_real_history', | |
44 | + 'bind_phraseology_frames_history') | |
45 | + | |
46 | +admin.site.register(UserSettings) | |
47 | +admin.site.register(UserStats, UserStatsAdmin) | |
48 | +admin.site.register(RealizedLemma, RealizedLemmaAdmin) | |
49 | +admin.site.register(RealizedPhraseology, RealizedPhraseologyAdmin) | |
50 | +admin.site.register(RealizedSemantics, RealizedSemanticsAdmin) | |
51 | +admin.site.register(GroupSettings) | |
52 | +admin.site.register(RealizedPhraseologyBinding) | |
53 | +admin.site.register(AnonymousUserProfile) | |
54 | + | |
55 | +admin.site.register(Session) | |
... | ... |
accounts/forms.py
0 → 100644
1 | +++ a/accounts/forms.py | |
1 | +#-*- coding:utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.forms import ModelForm | |
24 | +from accounts.models import UserSettings | |
25 | + | |
26 | +class SettingsForm(ModelForm): | |
27 | + class Meta: | |
28 | + model = UserSettings | |
29 | + fields = ['incremental_search', 'notes_per_page'] | |
... | ... |
accounts/models.py
0 → 100644
1 | +++ a/accounts/models.py | |
1 | +#-*- coding:utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.db.models import * | |
24 | +from django.contrib.auth.models import User, Group | |
25 | +from django.core.validators import MinValueValidator, MaxValueValidator | |
26 | + | |
27 | +from dictionary.models import Entry, Frame, Message, Lemma, Lemma_Status, Vocabulary | |
28 | +from semantics.models import SemanticFrame | |
29 | + | |
30 | +MANAGER_GROUPS = (u'Gość', u'Leksykograf', u'Superleksykograf', u'Administrator', u'Gość+', u'Frazeolog') | |
31 | + | |
32 | +def manager_groups(): | |
33 | + return Group.objects.filter(name__in=MANAGER_GROUPS) | |
34 | + | |
35 | +class UserStats(Model): | |
36 | + user = OneToOneField(User, related_name='user_stats') | |
37 | + # oplaty za prace leksykograficzne | |
38 | + lemma_real_history = ManyToManyField('RealizedLemma', db_table='zrealizowane_hasla', | |
39 | + blank=True, null=True, related_name='user_stats') | |
40 | + # oplaty za prace leksykograficzne | |
41 | + phraseology_real_history = ManyToManyField('RealizedPhraseology', db_table='prace_frazeologiczne', | |
42 | + blank=True, null=True, related_name='user_stats') | |
43 | + # oplaty za prace leksykograficzne | |
44 | + bind_phraseology_frames_history = ManyToManyField('RealizedPhraseologyBinding', db_table='powiazania_frazeologiczne', | |
45 | + blank=True, null=True, related_name='user_stats') | |
46 | + # !NOWE! oplaty za prace semantyczne | |
47 | + semantics_real_history = ManyToManyField('RealizedSemantics', db_table='prace_semantyczne', | |
48 | + blank=True, null=True, related_name='user_stats') | |
49 | + # kwota uiszczona | |
50 | + paid_cash = FloatField(db_column='kwota_uiszczona', default = 0.0) | |
51 | + | |
52 | + def __unicode__(self): | |
53 | + return '%s' % (self.user) | |
54 | + | |
55 | + def made_phraseologic_empty_entries_count(self): | |
56 | + return self.phraseology_real_history.filter(status__type__sym_name='ready_f', | |
57 | + paid=False, | |
58 | + new_frames=0, | |
59 | + reused_frames=0).count() | |
60 | + | |
61 | + def checked_phraseologic_empty_entries_count(self): | |
62 | + return self.phraseology_real_history.filter(status__type__sym_name='checked_f', | |
63 | + paid=False, | |
64 | + corr_frames=0, | |
65 | + ncorr_frames=0, | |
66 | + bonus=False).count() | |
67 | + | |
68 | +def can_modify_phraseology_only(user, phraseologic): | |
69 | + return phraseologic and user.has_perm('dictionary.add_phraseologic_frames') | |
70 | + | |
71 | +class RealizedLemma(Model): | |
72 | + """Model representing realized and confirmed frames by user.""" | |
73 | + # wykonane haslo | |
74 | + lemma = ForeignKey(Lemma, db_column='wykonane_haslo', related_name='realized_lemmas') | |
75 | + # wynagrodzenie za haslo | |
76 | + cash = FloatField(db_column='wynagrodzenie', default = 0.0) | |
77 | + # czy wykonanie hasla zostalo juz wynagrodzone | |
78 | + paid = BooleanField(db_column='oplacono', default=False) | |
79 | + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci | |
80 | + counted = BooleanField(db_column='przeliczono', default=False) | |
81 | + # czy oplata jest bonusem dla leksykografa | |
82 | + bonus = BooleanField(db_column='bonus', default=False) | |
83 | + #wlasciwie wykonane schematy (wypelniane dla leksykografa) | |
84 | + prop_frames = PositiveIntegerField(db_column='poprawne_ramki', | |
85 | + default = 0) | |
86 | + # niewlasciwie wykonane schematy (wypelniane dla leksykografa) | |
87 | + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki', | |
88 | + default = 0) | |
89 | + # poprawione schematy (wypelniane dla superleksykografa) | |
90 | + corr_frames = PositiveIntegerField(db_column='poprawione_ramki', | |
91 | + default = 0) | |
92 | + # poprawione schematy (wypelniane dla superleksykografa) | |
93 | + made_frames = PositiveIntegerField(db_column='wykonane_ramki', | |
94 | + default = 0) | |
95 | + # schematy niepoprawiane (wypelniane dla supeleksykografa) | |
96 | + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki', | |
97 | + default = 0) | |
98 | + date = DateTimeField(auto_now_add=True, db_column='data_zmiany') | |
99 | + # statusu hasla za przejscie do ktorego otrzymano oplate | |
100 | + status = ForeignKey(Lemma_Status, related_name='realized_lemmas', | |
101 | + blank=True, null=True) | |
102 | + | |
103 | + def __unicode__(self): | |
104 | + return '%s: %f' % (self.lemma.entry, self.cash) | |
105 | + | |
106 | +class RealizedPhraseology(Model): | |
107 | + """Model representing realized phraseology work.""" | |
108 | + # wykonane haslo | |
109 | + lemma = ForeignKey(Lemma, db_column='haslo', related_name='realized_phraseology') | |
110 | + # wynagrodzenie za haslo | |
111 | + cash = FloatField(db_column='wynagrodzenie', default = 0.0) | |
112 | + # czy praca zostala juz oplacona | |
113 | + paid = BooleanField(db_column='oplacono', default=False) | |
114 | + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci | |
115 | + counted = BooleanField(db_column='przeliczono', default=False) | |
116 | + # czy oplata jest bonusem | |
117 | + bonus = BooleanField(db_column='bonus', default=False) | |
118 | + # stworzone nowe schematy frazeologiczne | |
119 | + new_frames = PositiveIntegerField(db_column='nowe_ramki', | |
120 | + default = 0) | |
121 | + # schematy pochodzace z podpowiedzi lub juz wczesniej istniejace dla danego lematu | |
122 | + reused_frames = PositiveIntegerField(db_column='ponownie_uzyte_ramki', | |
123 | + default = 0) | |
124 | + #wlasciwie wykonane schematy (wypelniane dla frazeologa) | |
125 | + prop_frames = PositiveIntegerField(db_column='poprawne_ramki', | |
126 | + default = 0) | |
127 | + # niewlasciwie wykonane schematy (wypelniane dla frazeologa) | |
128 | + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki', | |
129 | + default = 0) | |
130 | + # poprawione schematy (wypelniane dla superfrazeologa) | |
131 | + corr_frames = PositiveIntegerField(db_column='poprawione_ramki', | |
132 | + default = 0) | |
133 | + # schematy niepoprawiane (wypelniane dla superfrazeologa) | |
134 | + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki', | |
135 | + default = 0) | |
136 | + # data podliczenia pracy | |
137 | + date = DateTimeField(auto_now_add=True, db_column='data_zmiany') | |
138 | + # statusu hasla za przejscie do ktorego otrzymano oplate | |
139 | + status = ForeignKey(Lemma_Status, related_name='realized_phraseology', | |
140 | + blank=True, null=True) | |
141 | + | |
142 | + def __unicode__(self): | |
143 | + return '%s: %f' % (self.lemma.entry, self.cash) | |
144 | + | |
145 | +class RealizedPhraseologyBinding(Model): | |
146 | + """Model representing realized phraseology work.""" | |
147 | + # wykonane haslo | |
148 | + main_entry = ForeignKey(Entry, db_column='glowne_haslo', | |
149 | + related_name='realized_phraseology_bindings__main') | |
150 | + phraseologic_frame = ForeignKey(Frame, db_column='ramka_frazeologiczna', | |
151 | + related_name='realized_phraseology_bindings__binded') | |
152 | + binded_entry = ForeignKey(Entry, db_column='przypisane_haslo', | |
153 | + related_name='realized_phraseology_bindings') | |
154 | + cash = FloatField(db_column='wynagrodzenie', default = 0.0) | |
155 | + # czy praca zostala juz oplacona | |
156 | + paid = BooleanField(db_column='oplacono', default=False) | |
157 | + # ta oplata zostala juz podliczona na pewnym etapie i nie nalezy zmieniac jej wartosci | |
158 | + counted = BooleanField(db_column='przeliczono', default=False) | |
159 | + # data podliczenia pracy | |
160 | + date = DateTimeField(auto_now_add=True, db_column='data_zmiany') | |
161 | + | |
162 | + def __unicode__(self): | |
163 | + return u'%s: %f' % (self.phraseologic_frame, self.cash) | |
164 | + | |
165 | +class UserSettings(Model): | |
166 | + user = OneToOneField(User, related_name='user_settings') | |
167 | + incremental_search = BooleanField( | |
168 | + default=False, | |
169 | + verbose_name=u'wyszukiwanie przyrostowe', | |
170 | + help_text=u'Wyszukiwanie odbywa się automatycznie w miarę wpisywania ' | |
171 | + u'szukanego hasła. Sugerujemy wyłączenie w wypadku wolnego ' | |
172 | + u'połączenia internetowego.') | |
173 | + filter_search = BooleanField( | |
174 | + default=True, | |
175 | + verbose_name=u'wyszukiwanie przez filtrowanie', | |
176 | + help_text=u'Wyszukiwanie powoduje zawężenie listy haseł do pasujących ' | |
177 | + u'do zapytania.') | |
178 | + notes_per_page = PositiveSmallIntegerField(default=40, | |
179 | + db_column='wiadomosci_na_strone', | |
180 | + verbose_name=u'Notatki na stronę', | |
181 | + help_text=u'Liczba notatek na stronę w skrzynce odbiorczej użytkownika.', | |
182 | + validators=[ | |
183 | + MaxValueValidator(100), | |
184 | + MinValueValidator(10)] | |
185 | + ) | |
186 | + | |
187 | + def has_new_messages(self): | |
188 | + lemmas_new_msg = self.user.lemmas.filter(messages__new=True).filter(messages__private=False) | |
189 | + if len(lemmas_new_msg) > 0: | |
190 | + return True; | |
191 | + return False; | |
192 | + | |
193 | + def new_notes_number(self): | |
194 | + new_notes = Message.objects.filter(recipient=self.user, private=False, new=True) | |
195 | + return len(new_notes) | |
196 | + | |
197 | + def change_all_lemmas(self): | |
198 | + return self.user.has_perm('dictionary.change_all_lemmas') | |
199 | + | |
200 | + def view_lemma(self): | |
201 | + return self.user.has_perm('dictionary.view_lemma') | |
202 | + | |
203 | + def view_realizations(self): | |
204 | + return self.user.has_perm('dictionary.view_realizations') | |
205 | + | |
206 | + def view_notes(self): | |
207 | + return self.user.has_perm('dictionary.view_notes') | |
208 | + | |
209 | + def add_notes(self): | |
210 | + return self.user.has_perm('dictionary.add_notes') | |
211 | + | |
212 | + def change_lemmas(self): | |
213 | + return self.user.has_perm('dictionary.change_lemmas') | |
214 | + | |
215 | + def change_lemma_status(self): | |
216 | + return self.user.has_perm('dictionary.change_lemma_status') | |
217 | + | |
218 | + def manages_vocabulary(self): | |
219 | + return self.user.has_perm('dictionary.manage_vocabulary') | |
220 | + | |
221 | + def download_vocabulary(self): | |
222 | + return self.user.has_perm('dictionary.download_vocabulary') | |
223 | + | |
224 | + def view_vocab_stats(self): | |
225 | + return self.user.has_perm('dictionary.view_vocab_stats') | |
226 | + | |
227 | + def edit_semantic_frames(self): | |
228 | + return self.user.has_perm('semantics.edit_frames') | |
229 | + | |
230 | + class Meta: | |
231 | + permissions = ( | |
232 | + ('create_admin', u'Może nadawać dowolne role'), | |
233 | + ) | |
234 | + | |
235 | +class GroupSettings(Model): | |
236 | + """Group settings model.""" | |
237 | + group = OneToOneField(Group, related_name='group_settings') | |
238 | + abort_statuses = ManyToManyField(Lemma_Status, blank=True, | |
239 | + related_name='group_settings_abort') | |
240 | + next_statuses = ManyToManyField(Lemma_Status, blank=True, | |
241 | + related_name='group_settings_next') | |
242 | + active_statuses = ManyToManyField(Lemma_Status, blank=True, | |
243 | + related_name='group_settings_active') | |
244 | + priority = PositiveIntegerField(db_column='priorytet') | |
245 | + | |
246 | + def __unicode__(self): | |
247 | + return '%s' % self.group.name | |
248 | + | |
249 | +class AnonymousUserProfile(Model): | |
250 | + """Anonymous user settings.""" | |
251 | + user_template = ForeignKey(User, db_column='szablon_uzytkownika', | |
252 | + related_name='anonymous_user_settings') | |
253 | + selected = BooleanField(db_column='wybrana', default=False) | |
254 | + visible_statuses = ManyToManyField(Lemma_Status, blank=True, | |
255 | + related_name='anonymous_user_profiles') | |
256 | + | |
257 | + def visible_vocabularies(self): | |
258 | + if self.user_template.has_perm('dictionary.view_all_lemmas'): | |
259 | + return Vocabulary.objects.all() | |
260 | + else: | |
261 | + return self.user_template.visible_vocabularies.all() | |
262 | + | |
263 | + def __unicode__(self): | |
264 | + return unicode(self.user_template) | |
265 | + | |
266 | +def get_anon_user(): | |
267 | + return AnonymousUserProfile.objects.get(selected=True).user_template | |
268 | + | |
269 | +def get_anon_profile(): | |
270 | + return AnonymousUserProfile.objects.get(selected=True) | |
271 | + | |
272 | +def filtering_mode(user): | |
273 | + return user.usersettings.filter_search | |
274 | + | |
275 | +# !NOWE! | |
276 | +class RealizedSemantics(Model): | |
277 | + """Model representing realized semantic work.""" | |
278 | + # wykonane haslo | |
279 | + entry = ForeignKey(Entry, db_column='haslo', | |
280 | + related_name='realized_semantics') | |
281 | + # ramy semantyczne w momencie zapisu pracy | |
282 | + frames = ManyToManyField(SemanticFrame, db_table='ramy_semantyczne', | |
283 | + blank=True, null=True, related_name='realized_semantics') | |
284 | + # wynagrodzenie za haslo | |
285 | + cash = FloatField(db_column='wynagrodzenie', default=0.0) | |
286 | + # czy oplata jest bonusem dla semantyka | |
287 | + bonus = BooleanField(db_column='bonus', default=False) | |
288 | + # wlasciwie wykonane ramki (wypelniane dla semantyka) | |
289 | + prop_frames = PositiveIntegerField(db_column='poprawne_ramki', | |
290 | + default=0) | |
291 | + # niewlasciwie wykonane ramki (wypelniane dla semantyka) | |
292 | + wrong_frames = PositiveIntegerField(db_column='niepoprawne_ramki', | |
293 | + default=0) | |
294 | + # wykonane ramki (wypelniane dla semantyka) | |
295 | + made_frames = PositiveIntegerField(db_column='wykonane_ramki', | |
296 | + default=0) | |
297 | + # poprawione ramki (wypelniane dla supersemantyka) | |
298 | + corr_frames = PositiveIntegerField(db_column='poprawione_ramki', | |
299 | + default=0) | |
300 | + # ramki niepoprawiane (wypelniane dla supersemantyka) | |
301 | + ncorr_frames = PositiveIntegerField(db_column='niepoprawione_ramki', | |
302 | + default=0) | |
303 | + date = DateTimeField(auto_now_add=True, db_column='data_zmiany') | |
304 | + # statusu hasla za przejscie do ktorego otrzymano oplate | |
305 | + status = ForeignKey(Lemma_Status, related_name='realized_semantics', | |
306 | + blank=True, null=True) | |
307 | + | |
308 | + def __unicode__(self): | |
309 | + return '%s: %f' % (self.entry.name, self.cash) | |
... | ... |
accounts/templates/registration/login.html
0 → 100644
1 | +++ a/accounts/templates/registration/login.html | |
1 | +{% extends "base.html" %} | |
2 | +{% load i18n %} | |
3 | +{% load url from future %} | |
4 | + | |
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 %} | |
11 | + | |
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 %} | |
19 | + | |
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> </label><input type="submit" value="{% trans 'Log in' %}" /> | |
25 | + </div> | |
26 | +</form> | |
27 | + | |
28 | +<script type="text/javascript"> | |
29 | +document.getElementById('id_username').focus() | |
30 | +</script> | |
31 | +</div> | |
32 | +{% endblock %} | |
... | ... |
accounts/templates/registration/logout.html
0 → 100644
1 | +++ a/accounts/templates/registration/logout.html | |
1 | +{% extends "base.html" %} | |
2 | +{% load i18n %} | |
3 | +{% load url from future %} | |
4 | + | |
5 | +{% block content %} | |
6 | + | |
7 | +<p>{% trans "Thanks for spending some quality time with the Web site today." %}</p> | |
8 | + | |
9 | +<p><a href="{% url 'auth_login' %}">{% trans 'Log in again' %}</a></p> | |
10 | + | |
11 | +{% endblock %} | |
... | ... |
accounts/templates/registration/password_change_done.html
0 → 100644
1 | +++ a/accounts/templates/registration/password_change_done.html | |
1 | +{% extends "base.html" %} | |
2 | +{% load i18n %} | |
3 | +{% load url from future %} | |
4 | + | |
5 | +{% block userlinks %}{% trans 'Change password' %} / <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %} | |
6 | + | |
7 | +{% block title %}{% trans 'Password change successful' %}{% endblock %} | |
8 | + | |
9 | +{% block content %} | |
10 | + | |
11 | +<h1>{% trans 'Password change successful' %}</h1> | |
12 | + | |
13 | +<p>{% trans 'Your password was changed.' %}</p> | |
14 | + | |
15 | +{% endblock %} | |
... | ... |
accounts/templates/registration/password_change_form.html
0 → 100644
1 | +++ a/accounts/templates/registration/password_change_form.html | |
1 | +{% extends "base.html" %} | |
2 | +{% load i18n %} | |
3 | +{% load url from future %} | |
4 | +{% block userlinks %}{% trans 'Change password' %} / <a href="{% url 'auth_logout' %}">{% trans 'Log out' %}</a>{% endblock %} | |
5 | + | |
6 | +{% block title %}{% trans 'Password change' %}{% endblock %} | |
7 | + | |
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> | |
48 | + | |
49 | +{% endblock %} | |
... | ... |
accounts/templates/settings.html
0 → 100644
1 | +++ a/accounts/templates/settings.html | |
1 | +<!-- | |
2 | +Copyright (c) 2012, Bartłomiej Nitoń | |
3 | +All rights reserved. | |
4 | + | |
5 | +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | |
6 | + | |
7 | + Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. | |
8 | + Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
9 | + | |
10 | +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
11 | +--> | |
12 | + | |
13 | +{% extends "base.html" %} | |
14 | +{% load url from future %} | |
15 | + | |
16 | +{% block title %}Ustawienia{% endblock %} | |
17 | + | |
18 | +{% block content %} | |
19 | +<h1>Ustawienia użytkownika</h1> | |
20 | +<form method="post" action=""> | |
21 | + {{ form.as_p }} | |
22 | + {% csrf_token %} | |
23 | + <input type="hidden" name="next" value="{{ next }}"/> | |
24 | + <button type="submit"> | |
25 | + Zapisz | |
26 | + </button> | |
27 | +</form> | |
28 | +<p> | |
29 | + <a href="{% url 'auth_password_change' %}">Zmiana hasła</a> | |
30 | +</p> | |
31 | +{% endblock %} | |
... | ... |
accounts/tests.py
0 → 100644
1 | +++ a/accounts/tests.py | |
1 | +""" | |
2 | +This file demonstrates writing tests using the unittest module. These will pass | |
3 | +when you run "manage.py test". | |
4 | + | |
5 | +Replace this with more appropriate tests for your application. | |
6 | +""" | |
7 | + | |
8 | +from django.test import TestCase | |
9 | + | |
10 | + | |
11 | +class SimpleTest(TestCase): | |
12 | + def test_basic_addition(self): | |
13 | + """ | |
14 | + Tests that 1 + 1 always equals 2. | |
15 | + """ | |
16 | + self.assertEqual(1 + 1, 2) | |
... | ... |
accounts/views.py
0 → 100644
1 | +++ a/accounts/views.py | |
1 | +#-*- coding:utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.http import HttpResponseRedirect | |
24 | +from django.contrib.auth.decorators import login_required | |
25 | +from common.decorators import render | |
26 | +from accounts.forms import SettingsForm | |
27 | +from accounts.models import UserSettings | |
28 | + | |
29 | +@login_required | |
30 | +@render() | |
31 | +def settings(request): | |
32 | + user_settings, created = UserSettings.objects.get_or_create(user=request.user) | |
33 | + if request.method == 'POST': | |
34 | + form = SettingsForm(data=request.POST, instance=user_settings) | |
35 | + if form.is_valid(): | |
36 | + form.save() | |
37 | + return HttpResponseRedirect(request.POST['next']) | |
38 | + else: | |
39 | + form = SettingsForm(instance=user_settings) | |
40 | + return {'form': form, 'next': request.META.get('HTTP_REFERER', '')} | |
41 | + | |
... | ... |
common/__init__.py
0 → 100644
1 | +++ a/common/__init__.py | |
... | ... |
common/context_processors.py
0 → 100644
1 | +++ a/common/context_processors.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
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 {} | |
9 | + | |
10 | +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 {} | |
... | ... |
common/decorators.py
0 → 100644
1 | +++ a/common/decorators.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +from functools import wraps | |
4 | +from inspect import getargspec | |
5 | +from django.http import HttpResponse | |
6 | +from django.utils.simplejson import loads as json_decode, dumps as json_encode | |
7 | +from django.utils.functional import curry | |
8 | +from django.conf import settings | |
9 | +from django.shortcuts import render_to_response | |
10 | +from django.template import RequestContext, generic_tag_compiler, Node | |
11 | +from django.template import TemplateSyntaxError, Variable | |
12 | +from common.util import stringify_keys | |
13 | +from django.db import transaction | |
14 | + | |
15 | +class AjaxError(Exception): | |
16 | + pass | |
17 | + | |
18 | +def json_decode_fallback(value): | |
19 | + try: | |
20 | + return json_decode(value) | |
21 | + except ValueError: | |
22 | + return value | |
23 | + | |
24 | +def ajax(login_required=False, method=None, encode_result=True): | |
25 | + def decorator(fun): | |
26 | + @wraps(fun) | |
27 | + def ajax_view(request): | |
28 | + kwargs = {} | |
29 | + request_params = None | |
30 | + if method == 'post': | |
31 | + request_params = request.POST | |
32 | + elif method == 'get': | |
33 | + request_params = request.GET | |
34 | + fun_params, xx, fun_kwargs, xxxx = getargspec(fun) | |
35 | + if request_params: | |
36 | + request_params = dict((key, json_decode_fallback(value)) | |
37 | + for key, value in request_params.iteritems() | |
38 | + if fun_kwargs or key in fun_params) | |
39 | + kwargs.update(stringify_keys(request_params)) | |
40 | + res = None | |
41 | + if login_required and not request.user.is_authenticated(): | |
42 | + res = {'result': 'logout'} | |
43 | + if not res: | |
44 | + try: | |
45 | + res = fun(request, **kwargs) | |
46 | + except AjaxError as e: | |
47 | + res = {'result': e.args[0]} | |
48 | + transaction.rollback() | |
49 | + if encode_result: | |
50 | + if 'result' not in res: | |
51 | + res['result'] = 'ok' | |
52 | + return HttpResponse(json_encode(res), mimetype='application/json') | |
53 | + else: | |
54 | + return res | |
55 | + return ajax_view | |
56 | + return decorator | |
57 | + | |
58 | +def render(template=None, mimetype=None): | |
59 | + mimetype = mimetype or settings.DEFAULT_CONTENT_TYPE | |
60 | + template1 = template | |
61 | + def decorator(func): | |
62 | + template = template1 # no cóż... | |
63 | + if not template: | |
64 | + template = func.__name__ + '.html' | |
65 | + @wraps(func) | |
66 | + def renderer(request, *args, **kw): | |
67 | + output = func(request, *args, **kw) | |
68 | + if isinstance(output, (list, tuple)): | |
69 | + return render_to_response(output[1], output[0], | |
70 | + RequestContext(request), mimetype=mimetype) | |
71 | + elif isinstance(output, dict): | |
72 | + return render_to_response(template, output, | |
73 | + RequestContext(request), mimetype=mimetype) | |
74 | + return output | |
75 | + return renderer | |
76 | + return decorator | |
77 | + | |
78 | +def simple_tag(register, takes_context=False): | |
79 | + def decorator(func): | |
80 | + params, xx, xxx, defaults = getargspec(func) | |
81 | + if takes_context: | |
82 | + if params[0] == 'context': | |
83 | + params = params[1:] | |
84 | + else: | |
85 | + raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'") | |
86 | + | |
87 | + class SimpleNode(Node): | |
88 | + def __init__(self, vars_to_resolve): | |
89 | + self.vars_to_resolve = map(Variable, vars_to_resolve) | |
90 | + | |
91 | + def render(self, context): | |
92 | + resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] | |
93 | + if takes_context: | |
94 | + args = [context] + resolved_vars | |
95 | + else: | |
96 | + args = resolved_vars | |
97 | + try: | |
98 | + return func(*args) | |
99 | + except Exception as e: | |
100 | + raise | |
101 | + return type(e).__name__+': '+str(e) | |
102 | + | |
103 | + compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) | |
104 | + compile_func.__doc__ = func.__doc__ | |
105 | + register.tag(getattr(func, "_decorated_function", func).__name__, compile_func) | |
106 | + return func | |
107 | + return decorator | |
... | ... |
common/js_to_obj.py
0 → 100644
1 | +++ a/common/js_to_obj.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2014, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from dictionary.common_func import sortArguments, sortPositions | |
24 | +from dictionary.models import Argument, Frame, Frame_Char_Model, \ | |
25 | + Frame_Characteristic, Position, PositionCategory, \ | |
26 | + sortFrameChars, sortPosCatsAsStrTab | |
27 | + | |
28 | +def jsFrameToObj(frame, lemma_entry): | |
29 | + # szukanie charakterystyk schematu | |
30 | + frame_characteristic_objs = [] | |
31 | + frame_char_models = Frame_Char_Model.objects.order_by('priority') | |
32 | + for i in range(len(frame_char_models)): | |
33 | + frame_char_value = frame_char_models[i].frame_char_values.get(value=frame['characteristics'][i]) | |
34 | + frame_char_type = frame_char_models[i].model_name | |
35 | + try: | |
36 | + frame_char_obj = Frame_Characteristic.objects.get(type=frame_char_type, value=frame_char_value) | |
37 | + except Frame_Characteristic.DoesNotExist: | |
38 | + frame_char_obj = Frame_Characteristic(type=frame_char_type, value=frame_char_value) | |
39 | + frame_char_obj.save() | |
40 | + frame_characteristic_objs.append(frame_char_obj) | |
41 | + | |
42 | + positions_objs = [] | |
43 | + for position in frame['positions']: | |
44 | + if len(position['arguments']) > 0: | |
45 | + pos_obj = jsPosToObj(position) | |
46 | + positions_objs.append(pos_obj) | |
47 | + | |
48 | + sorted_positions = [] | |
49 | + sorted_pos_dict = sortPositions(positions_objs) | |
50 | + last_pos_dict = None | |
51 | + for pos_dict in sorted_pos_dict: | |
52 | + sorted_positions.append(pos_dict['position']) | |
53 | + | |
54 | + sort_pos_str_tab = [] | |
55 | + for sort_pos in sorted_positions: | |
56 | + sort_pos_str_tab.append(sort_pos.text_rep) | |
57 | + | |
58 | + text_rep = u'%s:%s' % (':'.join(frame['characteristics']), | |
59 | + '+'.join(sort_pos_str_tab)) | |
60 | + | |
61 | + try: | |
62 | + frame_obj = Frame.objects.get(text_rep=text_rep) | |
63 | + except Frame.DoesNotExist: | |
64 | + frame_obj = Frame(text_rep=text_rep) | |
65 | + frame_obj.save() | |
66 | + last_pos_obj = None | |
67 | + pos_obj_count = 0 | |
68 | + for pos_obj in sorted_positions: | |
69 | + same_pos_db = Position.objects.filter(text_rep=pos_obj.text_rep).order_by('id') | |
70 | + if not last_pos_obj or last_pos_obj.text_rep != pos_obj.text_rep: | |
71 | + pos_obj_count = 1 | |
72 | + frame_obj.positions.add(same_pos_db[0]) | |
73 | + else: | |
74 | + pos_obj_count = pos_obj_count + 1 | |
75 | + if pos_obj_count <= len(same_pos_db): | |
76 | + same_pos_obj = same_pos_db[pos_obj_count-1] | |
77 | + frame_obj.positions.add(same_pos_obj) | |
78 | + else: | |
79 | + same_pos_obj = Position(text_rep=pos_obj.text_rep) | |
80 | + same_pos_obj.save() | |
81 | + for category in pos_obj.categories.all(): | |
82 | + same_pos_obj.categories.add(category) | |
83 | + for arg in pos_obj.arguments.all(): | |
84 | + same_pos_obj.arguments.add(arg) | |
85 | + frame_obj.positions.add(same_pos_obj) | |
86 | + last_pos_obj = pos_obj | |
87 | + for frame_char in frame_characteristic_objs: | |
88 | + frame_obj.characteristics.add(frame_char) | |
89 | + if frame_obj.has_phraseologic_arguments(): | |
90 | + frame_obj.phraseologic = True | |
91 | + frame_obj.save() | |
92 | + | |
93 | + return frame_obj | |
94 | + | |
95 | +def jsPosToObj(position, pos_idx=0): | |
96 | + categories = [] | |
97 | + for category in position['categories']: | |
98 | + categories.append(category) | |
99 | + categories = sortPosCatsAsStrTab(categories) | |
100 | + arguments_objs = [] | |
101 | + for arg in position['arguments']: | |
102 | + arguments_objs.append(jsArgToObj(arg)) | |
103 | + argument_objs = sortArguments(arguments_objs) | |
104 | + args_str_tab = [] | |
105 | + last_arg_obj = None | |
106 | + for arg_obj in argument_objs: | |
107 | + if not last_arg_obj or last_arg_obj.text_rep != arg_obj.text_rep: | |
108 | + args_str_tab.append(arg_obj.text_rep) | |
109 | + last_arg_obj = arg_obj | |
110 | + pos_text_rep = '%s{%s}' % (','.join(categories),';'.join(args_str_tab)) | |
111 | + same_positions = Position.objects.filter(text_rep=pos_text_rep) | |
112 | + if len(same_positions) > 0: | |
113 | + pos_obj = same_positions[pos_idx] | |
114 | + else: | |
115 | + pos_obj = Position(text_rep=pos_text_rep) | |
116 | + pos_obj.save() | |
117 | + for category in categories: | |
118 | + category_obj = PositionCategory.objects.get(category=category) | |
119 | + pos_obj.categories.add(category_obj) | |
120 | + for arg_obj in argument_objs: | |
121 | + pos_obj.arguments.add(arg_obj) | |
122 | + return pos_obj | |
123 | + | |
124 | +def jsArgToObj(argument): | |
125 | + arg_obj = Argument.objects.get(text_rep=argument['text_rep']) | |
126 | + return arg_obj | |
127 | + | |
128 | +def frameObjToSerializableDict(lemma, frame): | |
129 | + frame_opinion = '' | |
130 | + frame_opinions_tab = lemma.frame_opinions.filter(frame__text_rep=frame.text_rep) | |
131 | + if frame_opinions_tab: | |
132 | + frame_opinion = frame_opinions_tab[0].value.value | |
133 | + | |
134 | + frame_dict = { 'id' : frame.id, | |
135 | + 'text_rep' : frame.text_rep, | |
136 | + 'characteristics' : [], | |
137 | + 'positions' : [], | |
138 | + 'opinion' : frame_opinion, | |
139 | + 'error' : False, | |
140 | + 'tooltip' : '', | |
141 | + 'is_phraseologic' : frame.phraseologic} | |
142 | + | |
143 | + sorted_pos_dict = sortPositions(frame.positions.all()) | |
144 | + for position in sorted_pos_dict: | |
145 | + categories_str_tab = [] | |
146 | + for category in position['position'].categories.all(): | |
147 | + categories_str_tab.append(category.category) | |
148 | + categories_str_tab = sortPosCatsAsStrTab(categories_str_tab) | |
149 | + | |
150 | + position_dict = {'id' : position['position'].id, | |
151 | + 'text_rep' : position['position'].text_rep, | |
152 | + 'categories': categories_str_tab, | |
153 | + 'arguments' : [], | |
154 | + 'error' : False, | |
155 | + 'tooltip' : ''} | |
156 | + | |
157 | + for argument in position['arguments']: | |
158 | + argument_dict = { 'id' : argument.id, | |
159 | + 'text_rep': argument.text_rep, | |
160 | + 'type' : argument.type, | |
161 | + 'error' : False, | |
162 | + 'tooltip' : ''} | |
163 | + position_dict['arguments'].append(argument_dict) | |
164 | + | |
165 | + frame_dict['positions'].append(position_dict) | |
166 | + | |
167 | + frame_char_objs = sortFrameChars(frame.characteristics.all()) | |
168 | + for char in frame_char_objs: | |
169 | + frame_dict['characteristics'].append(char.value.value) | |
170 | + | |
171 | + return frame_dict | |
... | ... |
common/morfeusz.py
0 → 100644
1 | +++ a/common/morfeusz.py | |
1 | +# encoding=UTF-8 | |
2 | + | |
3 | +# Copyright © 2007, 2008, 2010, 2011 Jakub Wilk <jwilk@jwilk.net> | |
4 | +# | |
5 | +# Permission is hereby granted, free of charge, to any person obtaining a copy | |
6 | +# of this software and associated documentation files (the “Softwareâ€), to deal | |
7 | +# in the Software without restriction, including without limitation the rights | |
8 | +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
9 | +# copies of the Software, and to permit persons to whom the Software is | |
10 | +# furnished to do so, subject to the following conditions: | |
11 | +# | |
12 | +# The above copyright notice and this permission notice shall be included in | |
13 | +# all copies or substantial portions of the Software. | |
14 | +# | |
15 | +# THE SOFTWARE IS PROVIDED “AS ISâ€, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
16 | +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
17 | +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
18 | +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
19 | +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
20 | +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
21 | +# SOFTWARE. | |
22 | + | |
23 | +''' | |
24 | +Bindings for Morfeusz_, a Polish morphological analyser. | |
25 | + | |
26 | +.. _Morfeusz: | |
27 | + http://sgjp.pl/morfeusz/ | |
28 | +''' | |
29 | + | |
30 | +from __future__ import with_statement | |
31 | + | |
32 | +import collections | |
33 | +import ctypes | |
34 | +import sys | |
35 | + | |
36 | +py3k = sys.version_info >= (3, 0) | |
37 | + | |
38 | +if py3k: | |
39 | + import _thread as thread | |
40 | +else: | |
41 | + import thread | |
42 | +if not py3k: | |
43 | + from itertools import izip as zip | |
44 | + | |
45 | +if py3k: | |
46 | + unicode = str | |
47 | + | |
48 | +__author__ = 'Jakub Wilk <jwilk@jwilk.net>' | |
49 | +__version__ = '0.3300' | |
50 | +__all__ = ['analyse', 'about', 'expand_tags', 'ATTRIBUTES', 'VALUES'] | |
51 | + | |
52 | +ATTRIBUTES = ''' | |
53 | +subst=number case gender | |
54 | +depr=number case gender | |
55 | +adj=number case gender degree | |
56 | +adja= | |
57 | +adjc= | |
58 | +adjp= | |
59 | +adv=degree | |
60 | +num=number case gender accommodability | |
61 | +numcol=number case gender accommodability | |
62 | +ppron12=number case gender person accentability | |
63 | +ppron3=number case gender person accentability post_prepositionality | |
64 | +siebie=case | |
65 | +fin=number person aspect | |
66 | +bedzie=number person aspect | |
67 | +aglt=number person aspect vocalicity | |
68 | +praet=number gender aspect agglutination | |
69 | +impt=number person aspect | |
70 | +imps=aspect | |
71 | +inf=aspect | |
72 | +pcon=aspect | |
73 | +pant=aspect | |
74 | +ger=number case gender aspect negation | |
75 | +pact=number case gender aspect negation | |
76 | +ppas=number case gender aspect negation | |
77 | +winien=number gender aspect | |
78 | +pred= | |
79 | +prep=case vocalicity | |
80 | +conj= | |
81 | +comp= | |
82 | +brev=fullstoppedness | |
83 | +burk= | |
84 | +interj= | |
85 | +qub=vocalicity | |
86 | +xxs=number case gender | |
87 | +xxx= | |
88 | +interp= | |
89 | +ign= | |
90 | +sp= | |
91 | +''' | |
92 | +ATTRIBUTES = \ | |
93 | +dict( | |
94 | + (key, tuple(values.split())) | |
95 | + for line in ATTRIBUTES.splitlines() if line | |
96 | + for (key, values) in (line.split('=', 1),) | |
97 | +) | |
98 | + | |
99 | +VALUES = ''' | |
100 | +number=sg pl | |
101 | +case=nom gen dat acc inst loc voc | |
102 | +gender=m1 m2 m3 f n1 n2 p1 p2 p3 | |
103 | +person=pri sec ter | |
104 | +degree=pos comp sup | |
105 | +aspect=imperf perf | |
106 | +negation=aff neg | |
107 | +accentability=akc nakc | |
108 | +post_prepositionality=npraep praep | |
109 | +accommodability=congr rec | |
110 | +agglutination=agl nagl | |
111 | +vocalicity=nwok wok | |
112 | +fullstoppedness=pun npun | |
113 | +''' | |
114 | +VALUES = \ | |
115 | +dict( | |
116 | + (key, tuple(values.split())) | |
117 | + for line in VALUES.splitlines() if line | |
118 | + for (key, values) in (line.split('=', 1),) | |
119 | +) | |
120 | + | |
121 | +libmorfeusz = ctypes.CDLL('libmorfeusz.so.0') | |
122 | + | |
123 | +MORFOPT_ENCODING = 1 | |
124 | +MORFEUSZ_UTF_8 = 8 | |
125 | + | |
126 | +MORFOPT_WHITESPACE = 2 | |
127 | +MORFEUSZ_SKIP_WHITESPACE = 0 | |
128 | +MORFEUSZ_KEEP_WHITESPACE = 2 | |
129 | + | |
130 | +libmorfeusz.morfeusz_set_option(MORFOPT_ENCODING, MORFEUSZ_UTF_8) | |
131 | +libmorfeusz_lock = thread.allocate_lock() | |
132 | + | |
133 | +class InterpEdge(ctypes.Structure): | |
134 | + _fields_ = \ | |
135 | + ( | |
136 | + ('i', ctypes.c_int), | |
137 | + ('j', ctypes.c_int), | |
138 | + ('_orth', ctypes.c_char_p), | |
139 | + ('_base', ctypes.c_char_p), | |
140 | + ('_tags', ctypes.c_char_p) | |
141 | + ) | |
142 | + | |
143 | + if py3k: | |
144 | + @property | |
145 | + def tags(self): | |
146 | + if self._tags is not None: | |
147 | + return self._tags.decode('UTF-8') | |
148 | + else: | |
149 | + @property | |
150 | + def tags(self): | |
151 | + return self._tags | |
152 | + | |
153 | + @property | |
154 | + def orth(self): | |
155 | + if self._orth is not None: | |
156 | + return self._orth.decode('UTF-8') | |
157 | + | |
158 | + @property | |
159 | + def base(self): | |
160 | + if self._base is not None: | |
161 | + return self._base.decode('UTF-8') | |
162 | + | |
163 | +libmorfeusz_analyse = libmorfeusz.morfeusz_analyse | |
164 | +libmorfeusz_analyse.restype = ctypes.POINTER(InterpEdge) | |
165 | +libmorfeusz_about = libmorfeusz.morfeusz_about | |
166 | +libmorfeusz_about.restype = ctypes.c_char_p | |
167 | + | |
168 | +def expand_tags(tags, expand_dot=True, expand_underscore=True): | |
169 | + | |
170 | + if tags is None: | |
171 | + yield | |
172 | + return | |
173 | + tags = str(tags) | |
174 | + for tag in tags.split('|'): | |
175 | + tag = tag.split(':') | |
176 | + pos = tag.pop(0) | |
177 | + chunks = [(pos,)] | |
178 | + chunks += \ | |
179 | + ( | |
180 | + VALUES[attribute] if chunk == '_' and expand_underscore | |
181 | + else chunk.split('.') | |
182 | + for chunk, attribute in zip(tag, ATTRIBUTES[pos]) | |
183 | + ) | |
184 | + | |
185 | + if not expand_dot: | |
186 | + yield ':'.join('.'.join(values) for values in chunks) | |
187 | + continue | |
188 | + | |
189 | + def expand_chunks(i): | |
190 | + if i >= len(chunks): | |
191 | + yield () | |
192 | + else: | |
193 | + tail = tuple(expand_chunks(i + 1)) | |
194 | + for chunk_variant in chunks[i]: | |
195 | + for tail_variant in tail: | |
196 | + yield (chunk_variant,) + tail_variant | |
197 | + | |
198 | + for x in expand_chunks(0): | |
199 | + yield ':'.join(x) | |
200 | + | |
201 | +_expand_tags = expand_tags | |
202 | + | |
203 | +def _dont_expand_tags(s, **kwargs): | |
204 | + return [s] | |
205 | + | |
206 | +def analyse(text, expand_tags=True, expand_dot=True, expand_underscore=True, dag=False, keep_whitespace=False): | |
207 | + ''' | |
208 | + Analyse the text. | |
209 | + ''' | |
210 | + expand_tags = _expand_tags if expand_tags else _dont_expand_tags | |
211 | + text = unicode(text) | |
212 | + text = text.encode('UTF-8') | |
213 | + analyse = _analyse_as_dag if dag else _analyse_as_list | |
214 | + return analyse( | |
215 | + text=text, | |
216 | + expand_tags=expand_tags, | |
217 | + expand_dot=expand_dot, | |
218 | + expand_underscore=expand_underscore, | |
219 | + keep_whitespace=keep_whitespace | |
220 | + ) | |
221 | + | |
222 | +def _analyse_as_dag(text, expand_tags, expand_dot, expand_underscore, keep_whitespace): | |
223 | + result = [] | |
224 | + with libmorfeusz_lock: | |
225 | + if keep_whitespace: | |
226 | + if libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_KEEP_WHITESPACE) != 1: | |
227 | + raise NotImplementedError("This version of Morfeusz doesn't support keep_whitespace") | |
228 | + for edge in libmorfeusz_analyse(text): | |
229 | + if edge.i == -1: | |
230 | + break | |
231 | + for tag in expand_tags(edge.tags, expand_dot=expand_dot, expand_underscore=expand_underscore): | |
232 | + result += [(edge.i, edge.j, (edge.orth, edge.base, tag))] | |
233 | + if keep_whitespace: | |
234 | + libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_SKIP_WHITESPACE) | |
235 | + return result | |
236 | + | |
237 | +def _analyse_as_list(text, expand_tags, expand_dot, expand_underscore, keep_whitespace): | |
238 | + dag = collections.defaultdict(list) | |
239 | + with libmorfeusz_lock: | |
240 | + if keep_whitespace: | |
241 | + if libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_KEEP_WHITESPACE) != 1: | |
242 | + raise NotImplementedError("This version of Morfeusz doesn't support keep_whitespace") | |
243 | + for edge in libmorfeusz_analyse(text): | |
244 | + if edge.i == -1: | |
245 | + break | |
246 | + for tag in expand_tags(edge.tags, expand_dot=expand_dot, expand_underscore=expand_underscore): | |
247 | + dag[edge.i] += [((edge.orth, edge.base, tag), edge.j)] | |
248 | + if keep_whitespace: | |
249 | + libmorfeusz.morfeusz_set_option(MORFOPT_WHITESPACE, MORFEUSZ_SKIP_WHITESPACE) | |
250 | + def expand_dag(i): | |
251 | + nexts = dag[i] | |
252 | + if not nexts: | |
253 | + yield [] | |
254 | + else: | |
255 | + for head, j in nexts: | |
256 | + for tail in expand_dag(j): | |
257 | + yield [head] + tail | |
258 | + return list(expand_dag(0)) | |
259 | + | |
260 | +def about(): | |
261 | + ''' | |
262 | + Return a string containing information on authors and version of the | |
263 | + underlying library. | |
264 | + ''' | |
265 | + about = libmorfeusz_about() | |
266 | + try: | |
267 | + return about.decode('UTF-8') | |
268 | + except UnicodeError: | |
269 | + return about.decode('ISO-8859-2') | |
270 | + | |
271 | +# vim:ts=4 sw=4 et | |
... | ... |
common/templates/error.html
0 → 100644
common/templates/message.html
0 → 100644
common/templates/navigation.html
0 → 100644
common/templatetags/__init__.py
0 → 100644
1 | +++ a/common/templatetags/__init__.py | |
... | ... |
common/templatetags/get.py
0 → 100644
1 | +++ a/common/templatetags/get.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.template import Library | |
24 | + | |
25 | +register = Library() | |
26 | + | |
27 | +@register.filter | |
28 | +def get(dict, arg): | |
29 | + return dict[arg] | |
0 | 30 | \ No newline at end of file |
... | ... |
common/templatetags/ingroup.py
0 → 100644
1 | +++ a/common/templatetags/ingroup.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +#Copyright (c) 2012, Bartłomiej Nitoń | |
4 | +#All rights reserved. | |
5 | + | |
6 | +#Redistribution and use in source and binary forms, with or without modification, are permitted provided | |
7 | +#that the following conditions are met: | |
8 | + | |
9 | +# Redistributions of source code must retain the above copyright notice, this list of conditions and | |
10 | +# the following disclaimer. | |
11 | +# Redistributions in binary form must reproduce the above copyright notice, this list of conditions | |
12 | +# and the following disclaimer in the documentation and/or other materials provided with the distribution. | |
13 | + | |
14 | +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED | |
15 | +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | |
16 | +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR | |
17 | +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED | |
18 | +# TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |
20 | +# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
21 | +# POSSIBILITY OF SUCH DAMAGE. | |
22 | + | |
23 | +from django.template import Library | |
24 | + | |
25 | +register = Library() | |
26 | + | |
27 | +@register.filter | |
28 | +def ingroup(user, group): | |
29 | + return group in user.groups.all() | |
... | ... |
common/templatetags/json.py
0 → 100644
1 | +++ a/common/templatetags/json.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +from django.core.serializers import serialize | |
4 | +from django.db.models.query import QuerySet | |
5 | +from django.utils import simplejson | |
6 | +from django.utils.safestring import mark_safe | |
7 | +from django.template import Library | |
8 | + | |
9 | +register = Library() | |
10 | + | |
11 | +@register.filter | |
12 | +def jsonify(object): | |
13 | + if isinstance(object, QuerySet): | |
14 | + return serialize('json', object) | |
15 | + return mark_safe(simplejson.dumps(object)) | |
... | ... |
common/templatetags/script.py
0 → 100644
1 | +++ a/common/templatetags/script.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | +from django import template | |
3 | + | |
4 | +register = template.Library() | |
5 | + | |
6 | +@register.simple_tag | |
7 | +def script(): | |
8 | + return '<script type="text/javascript"> /* <![CDATA[ */' | |
9 | + | |
10 | +@register.simple_tag | |
11 | +def endscript(): | |
12 | + return '/* ]]> */ </script>' | |
... | ... |
common/util.py
0 → 100644
1 | +++ a/common/util.py | |
1 | +# -*- coding: utf-8 -*- | |
2 | + | |
3 | +import re | |
4 | +from htmlentitydefs import name2codepoint | |
5 | +from django.utils.encoding import smart_unicode, force_unicode | |
6 | +from django.conf.urls import defaults | |
7 | +from django.http import HttpResponseRedirect, Http404 | |
8 | + | |
9 | +from dictionary.models import Argument, Arg_Possibility, PositionCategory | |
10 | + | |
11 | + | |
12 | +def error_redirect(request, error, url='/'): | |
13 | + request.session['error'] = error | |
14 | + return HttpResponseRedirect(url) | |
15 | + | |
16 | +def message_redirect(request, message, url='/'): | |
17 | + request.session['message'] = message | |
18 | + return HttpResponseRedirect(url) | |
19 | + | |
20 | +def make_form(request, form_class, *args, **kwargs): | |
21 | + if request.POST.get('det', '') == form_class.base_fields['det'].initial: | |
22 | + return form_class(*args, data=request.POST, files=request.FILES, **kwargs) | |
23 | + else: | |
24 | + return form_class(*args, **kwargs) | |
25 | + | |
26 | +def invert(l): | |
27 | + return dict((e,nr) for (nr,e) in enumerate(l)) | |
28 | + | |
29 | +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 | |
37 | + | |
38 | +def url(regex, view, **kwargs): | |
39 | + if 'name' not in kwargs: | |
40 | + kwargs['name'] = view | |
41 | + return defaults.url(regex, view, **kwargs) | |
42 | + | |
43 | +def stringify_keys(dictionary): | |
44 | + return dict((keyword.encode('ascii'), value) | |
45 | + for keyword, value in dictionary.iteritems()) | |
46 | + | |
47 | +# copypasta ze standardowego modułu bisect | |
48 | +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 | |
60 | + | |
61 | +def triple_arg_poss(arg, positions_cats_ls): | |
62 | + possibilities = [] | |
63 | + if arg: | |
64 | + try: # TODO czy dobrze jest pomijac takie nieistniejace, argumenty | |
65 | + arg_obj = Argument.objects.get(text_rep=arg) | |
66 | + # jesli argument nie posiada atrybutow (np. refl) i jego atrybuty nie wystepuja tylko jako realizacje to ok | |
67 | + if arg_obj.atributes.count() == 0 or arg_obj.has_real_only_parameter(): | |
68 | + pass | |
69 | + else: | |
70 | + return possibilities | |
71 | + except Argument.DoesNotExist: | |
72 | + return possibilities | |
73 | + for poss_cat in positions_cats_ls: | |
74 | + if poss_cat: | |
75 | + try: | |
76 | + possibility = Arg_Possibility.objects.get(argument=arg_obj, | |
77 | + position_category__category=poss_cat) | |
78 | + except Arg_Possibility.DoesNotExist: | |
79 | + position_category_obj = PositionCategory.objects.get(category=poss_cat) | |
80 | + possibility = Arg_Possibility(argument=arg_obj, | |
81 | + position_category=position_category_obj) | |
82 | + possibility.save() | |
83 | + possibilities.append(possibility) | |
84 | + else: | |
85 | + try: | |
86 | + possibility = Arg_Possibility.objects.get(argument=arg_obj, | |
87 | + position_category=None) | |
88 | + except Arg_Possibility.DoesNotExist: | |
89 | + possibility = Arg_Possibility(argument=arg_obj) | |
90 | + possibility.save() | |
91 | + possibilities.append(possibility) | |
92 | + return possibilities | |
... | ... |