Commit ad31813dea8a64e8157b4ec7b0d54549f6618e34
1 parent
d1ae5454
migracja TableTemplate
--HG-- branch : beta
Showing
16 changed files
with
294 additions
and
171 deletions
dictionary/management/commands/cache_form_qualifiers.py
@@ -7,7 +7,7 @@ from django.core.management.base import BaseCommand | @@ -7,7 +7,7 @@ from django.core.management.base import BaseCommand | ||
7 | from common.util import uniprint | 7 | from common.util import uniprint |
8 | from export.lexeme_form_query import WHERE_CLAUSES, \ | 8 | from export.lexeme_form_query import WHERE_CLAUSES, \ |
9 | attr_clauses_combinations, TABLE_FROM_CLAUSES | 9 | attr_clauses_combinations, TABLE_FROM_CLAUSES |
10 | -from dictionary.models import TableTemplate | 10 | +from tables.models import TableTemplate |
11 | 11 | ||
12 | 12 | ||
13 | class Command(BaseCommand): | 13 | class Command(BaseCommand): |
dictionary/management/commands/create_forms.py
@@ -7,7 +7,8 @@ from django.db.transaction import atomic | @@ -7,7 +7,8 @@ from django.db.transaction import atomic | ||
7 | from common.util import uniprint | 7 | from common.util import uniprint |
8 | from export.lexeme_form_query import WHERE_CLAUSES, \ | 8 | from export.lexeme_form_query import WHERE_CLAUSES, \ |
9 | attr_clauses_combinations, TABLE_FROM_CLAUSES | 9 | attr_clauses_combinations, TABLE_FROM_CLAUSES |
10 | -from dictionary.models import TableTemplate, Lexeme, LexemeForm | 10 | +from dictionary.models import Lexeme, LexemeForm |
11 | +from tables.models import TableTemplate | ||
11 | 12 | ||
12 | 13 | ||
13 | class Command(BaseCommand): | 14 | class Command(BaseCommand): |
dictionary/management/commands/stale/convert_tables.py
@@ -3,7 +3,7 @@ from django.core.management import BaseCommand | @@ -3,7 +3,7 @@ from django.core.management import BaseCommand | ||
3 | from common.util import GroupDict | 3 | from common.util import GroupDict |
4 | from dictionary.models import Cell, TableTemplate, PatternType, TableTemplate, TableCell, TableHeader, \ | 4 | from dictionary.models import Cell, TableTemplate, PatternType, TableTemplate, TableCell, TableHeader, \ |
5 | TableHeader, LexemeAttribute, ExportCell, InflectionCharacteristic, LexemeAttributeValue | 5 | TableHeader, LexemeAttribute, ExportCell, InflectionCharacteristic, LexemeAttributeValue |
6 | -from tables.models import Variant | 6 | +from tables.models import Variant, TableTemplate |
7 | from patterns.models import InflectionType, PatternType | 7 | from patterns.models import InflectionType, PatternType |
8 | 8 | ||
9 | 9 |
dictionary/management/commands/stale/import_variant.py
@@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand | @@ -5,7 +5,7 @@ from django.core.management.base import BaseCommand | ||
5 | from common.util import uniopen | 5 | from common.util import uniopen |
6 | from dictionary.models import TableTemplate, Cell, TableCell, PartOfSpeech, \ | 6 | from dictionary.models import TableTemplate, Cell, TableCell, PartOfSpeech, \ |
7 | PatternType, InflectionCharacteristic | 7 | PatternType, InflectionCharacteristic |
8 | -from tables.models import Variant | 8 | +from tables.models import Variant, TableTemplate |
9 | from patterns.models import BaseFormLabel, PatternType | 9 | from patterns.models import BaseFormLabel, PatternType |
10 | 10 | ||
11 | 11 |
dictionary/migrations/0014_auto_20151213_1328.py
0 → 100644
1 | +# -*- coding: utf-8 -*- | ||
2 | +from __future__ import unicode_literals | ||
3 | + | ||
4 | +from django.db import migrations, models | ||
5 | + | ||
6 | + | ||
7 | +class Migration(migrations.Migration): | ||
8 | + | ||
9 | + dependencies = [ | ||
10 | + ('dictionary', '0013_auto_20151213_1303'), | ||
11 | + ] | ||
12 | + | ||
13 | + database_operations = [ | ||
14 | + migrations.AlterModelTable('tabletemplate', 'tables_tabletemplate'), | ||
15 | + ] | ||
16 | + | ||
17 | + operations = [ | ||
18 | + migrations.SeparateDatabaseAndState( | ||
19 | + database_operations=database_operations), | ||
20 | + ] |
dictionary/migrations/0015_auto_20151213_1328.py
0 → 100644
1 | +# -*- coding: utf-8 -*- | ||
2 | +from __future__ import unicode_literals | ||
3 | + | ||
4 | +from django.db import migrations, models | ||
5 | + | ||
6 | + | ||
7 | +class Migration(migrations.Migration): | ||
8 | + | ||
9 | + dependencies = [ | ||
10 | + ('dictionary', '0014_auto_20151213_1328'), | ||
11 | + ('tables', '0002_tabletemplate'), | ||
12 | + ] | ||
13 | + | ||
14 | + state_operations = [ | ||
15 | + migrations.RemoveField( | ||
16 | + model_name='tabletemplate', | ||
17 | + name='attribute_values', | ||
18 | + ), | ||
19 | + migrations.RemoveField( | ||
20 | + model_name='tabletemplate', | ||
21 | + name='attributes', | ||
22 | + ), | ||
23 | + migrations.RemoveField( | ||
24 | + model_name='tabletemplate', | ||
25 | + name='cell_attributes', | ||
26 | + ), | ||
27 | + migrations.RemoveField( | ||
28 | + model_name='tabletemplate', | ||
29 | + name='parts_of_speech', | ||
30 | + ), | ||
31 | + migrations.RemoveField( | ||
32 | + model_name='tabletemplate', | ||
33 | + name='pattern_types', | ||
34 | + ), | ||
35 | + migrations.RemoveField( | ||
36 | + model_name='tabletemplate', | ||
37 | + name='variant', | ||
38 | + ), | ||
39 | + migrations.DeleteModel( | ||
40 | + name='TableTemplate', | ||
41 | + ), | ||
42 | + ] | ||
43 | + | ||
44 | + operations = [ | ||
45 | + migrations.AlterField( | ||
46 | + model_name='exportcell', | ||
47 | + name='table_template', | ||
48 | + field=models.ForeignKey(related_name='export_cells', to='tables.TableTemplate'), | ||
49 | + ), | ||
50 | + migrations.AlterField( | ||
51 | + model_name='tablecell', | ||
52 | + name='table_template', | ||
53 | + field=models.ForeignKey(related_name='table_cells', to='tables.TableTemplate'), | ||
54 | + ), | ||
55 | + migrations.AlterField( | ||
56 | + model_name='tableheader', | ||
57 | + name='table_template', | ||
58 | + field=models.ForeignKey(related_name='headers', to='tables.TableTemplate'), | ||
59 | + ), | ||
60 | + migrations.SeparateDatabaseAndState(state_operations=state_operations), | ||
61 | + ] |
dictionary/models.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | import json | 2 | import json |
3 | from collections import OrderedDict | 3 | from collections import OrderedDict |
4 | -from itertools import izip | ||
5 | 4 | ||
6 | from django.conf import settings | 5 | from django.conf import settings |
7 | from django.contrib.auth.models import User, Permission, AnonymousUser | 6 | from django.contrib.auth.models import User, Permission, AnonymousUser |
@@ -13,7 +12,6 @@ from accounts.util import users_with_perm | @@ -13,7 +12,6 @@ from accounts.util import users_with_perm | ||
13 | from common.models import NotDeletedManager | 12 | from common.models import NotDeletedManager |
14 | from common.util import no_history | 13 | from common.util import no_history |
15 | from patterns.models import InflectionType, BaseFormLabel, PatternType, Pattern | 14 | from patterns.models import InflectionType, BaseFormLabel, PatternType, Pattern |
16 | -from tables.models import Variant | ||
17 | from tables.util import prepare_table | 15 | from tables.util import prepare_table |
18 | 16 | ||
19 | 17 | ||
@@ -709,6 +707,7 @@ class LexemeInflectionPattern(Model): | @@ -709,6 +707,7 @@ class LexemeInflectionPattern(Model): | ||
709 | 707 | ||
710 | def table_template(self, variant, attr_vals=None, pos=None): | 708 | def table_template(self, variant, attr_vals=None, pos=None): |
711 | part_of_speech = pos or self.lexeme.part_of_speech | 709 | part_of_speech = pos or self.lexeme.part_of_speech |
710 | + from tables.models import TableTemplate | ||
712 | tts = TableTemplate.objects.filter( | 711 | tts = TableTemplate.objects.filter( |
713 | parts_of_speech=part_of_speech, variant=variant, | 712 | parts_of_speech=part_of_speech, variant=variant, |
714 | pattern_types=self.pattern.type) | 713 | pattern_types=self.pattern.type) |
@@ -1010,152 +1009,6 @@ class CrossReference(Model): | @@ -1010,152 +1009,6 @@ class CrossReference(Model): | ||
1010 | db_table = 'odsylacze' | 1009 | db_table = 'odsylacze' |
1011 | 1010 | ||
1012 | 1011 | ||
1013 | -class TableTemplate(Model): | ||
1014 | - name = TextField() | ||
1015 | - variant = ForeignKey(Variant) | ||
1016 | - parts_of_speech = ManyToManyField(PartOfSpeech) | ||
1017 | - pattern_types = ManyToManyField(PatternType) | ||
1018 | - attributes = ManyToManyField(LexemeAttribute) | ||
1019 | - attribute_values = ManyToManyField(LexemeAttributeValue) | ||
1020 | - cell_attributes = ManyToManyField(LexemeAttribute, related_name='templates') | ||
1021 | - takes_gender = BooleanField(default=False) | ||
1022 | - | ||
1023 | - def filter_cells_attr(self, cells, attr_vals): | ||
1024 | - for attr in self.cell_attributes.all(): | ||
1025 | - attr_val = [a for a in attr_vals if a.attribute == attr] | ||
1026 | - if len(attr_val) != 1: | ||
1027 | - return [] | ||
1028 | - cells = cells.filter(attribute_values=attr_val[0]) | ||
1029 | - return cells | ||
1030 | - | ||
1031 | - def filter_cells(self, pattern_type, gender, attr_vals): | ||
1032 | - if self.variant.type == Variant.TYPE_TABLE: | ||
1033 | - cells = self.table_cells.filter( | ||
1034 | - pattern_types=pattern_type).select_related('base_form_label') | ||
1035 | - else: | ||
1036 | - cells = self.export_cells.filter( | ||
1037 | - pattern_types=pattern_type).select_related('base_form_label') | ||
1038 | - if self.takes_gender and gender: | ||
1039 | - cells = cells.filter(genders=gender) | ||
1040 | - if attr_vals: | ||
1041 | - cells = self.filter_cells_attr(cells, attr_vals) | ||
1042 | - return cells | ||
1043 | - | ||
1044 | - def filter_table_headers(self, pattern_type, gender, attr_vals): | ||
1045 | - headers = self.headers.filter(pattern_types=pattern_type) | ||
1046 | - if self.takes_gender and gender: | ||
1047 | - headers = headers.filter(genders=gender) | ||
1048 | - if attr_vals: | ||
1049 | - headers = self.filter_cells_attr(headers, attr_vals) | ||
1050 | - return headers | ||
1051 | - | ||
1052 | - def render_with_pattern(self, pattern, *args, **kwargs): | ||
1053 | - base_endings = pattern.base_endings() | ||
1054 | - return self.render( | ||
1055 | - pattern.type, *args, pattern=pattern, base_endings=base_endings, | ||
1056 | - **kwargs) | ||
1057 | - | ||
1058 | - def render_with_pattern_type(self, pattern_type, *args, **kwargs): | ||
1059 | - base_endings = pattern_type.dummy_base_endings() | ||
1060 | - return prepare_table(self.render( | ||
1061 | - pattern_type, *args, base_endings=base_endings, numbers=True, | ||
1062 | - **kwargs)) | ||
1063 | - | ||
1064 | - def render(self, pattern_type, gender, attr_vals, separated=False, | ||
1065 | - numbers=False, pattern=None, **forms_kwargs): | ||
1066 | - table_cells = self.filter_cells(pattern_type, gender, attr_vals) | ||
1067 | - headers = self.filter_table_headers(pattern_type, gender, attr_vals) | ||
1068 | - if table_cells is None or headers is None: | ||
1069 | - return [] | ||
1070 | - rows = set() | ||
1071 | - last_col = 0 | ||
1072 | - for table_cell in table_cells: | ||
1073 | - rows.add(table_cell.row) | ||
1074 | - col = table_cell.col + table_cell.colspan - 1 | ||
1075 | - if col > last_col: | ||
1076 | - last_col = col | ||
1077 | - for header in headers: | ||
1078 | - rows.add(header.row) | ||
1079 | - col = header.col + header.colspan - 1 | ||
1080 | - if col > last_col: | ||
1081 | - last_col = col | ||
1082 | - if numbers: | ||
1083 | - last_col += 1 | ||
1084 | - table = [[{'type': 'empty'} for i in xrange(last_col)] for row in rows] | ||
1085 | - rows = sorted(rows) | ||
1086 | - if numbers: | ||
1087 | - for row, table_row in izip(rows, table): | ||
1088 | - table_row[0] = { | ||
1089 | - 'type': 'header', | ||
1090 | - 'label': [row], | ||
1091 | - 'css_class': 'blank', | ||
1092 | - 'rowspan': 1, | ||
1093 | - 'colspan': 1} | ||
1094 | - # słownik: nr rzędu w bazie -> rzeczywisty numer rzędu | ||
1095 | - row_translate = dict((r, i) for i, r in enumerate(rows)) | ||
1096 | - for tc in table_cells: | ||
1097 | - if numbers: | ||
1098 | - x = tc.col | ||
1099 | - else: | ||
1100 | - x = tc.col - 1 | ||
1101 | - y = row_translate[tc.row] | ||
1102 | - table_cell = table[y][x] | ||
1103 | - assert table_cell['type'] != 'span' | ||
1104 | - separator = u'·' if separated else u'' | ||
1105 | - forms = [f + (pattern,) | ||
1106 | - for f in tc.forms(separator=separator, **forms_kwargs)] | ||
1107 | - if not forms: | ||
1108 | - continue | ||
1109 | - if table_cell['type'] == 'empty': | ||
1110 | - table[y][x] = { | ||
1111 | - 'type': 'forms', | ||
1112 | - 'forms': forms, | ||
1113 | - 'rowspan': tc.rowspan, | ||
1114 | - 'colspan': tc.colspan, | ||
1115 | - } | ||
1116 | - for i in xrange(tc.colspan): | ||
1117 | - for j in xrange(tc.rowspan): | ||
1118 | - if (i, j) != (0, 0): | ||
1119 | - assert table[y + j][x + i]['type'] == 'empty' | ||
1120 | - table[y + j][x + i]['type'] = 'span' | ||
1121 | - else: | ||
1122 | - assert tc.rowspan == table_cell['rowspan'] | ||
1123 | - assert tc.colspan == table_cell['colspan'] | ||
1124 | - table_cell['forms'] += forms | ||
1125 | - for header in headers: | ||
1126 | - if numbers: | ||
1127 | - x = header.col | ||
1128 | - else: | ||
1129 | - x = header.col - 1 | ||
1130 | - y = row_translate[header.row] | ||
1131 | - assert table[y][x]['type'] == 'empty' | ||
1132 | - table[y][x] = { | ||
1133 | - 'type': 'label', | ||
1134 | - 'label': [header.label], | ||
1135 | - 'css_class': header.css_class, | ||
1136 | - 'rowspan': header.rowspan, | ||
1137 | - 'colspan': header.colspan, | ||
1138 | - } | ||
1139 | - for i in xrange(header.colspan): | ||
1140 | - for j in xrange(header.rowspan): | ||
1141 | - if (i, j) != (0, 0): | ||
1142 | - assert table[y + j][x + i]['type'] == 'empty' | ||
1143 | - table[y + j][x + i]['type'] = 'span' | ||
1144 | - if numbers: | ||
1145 | - first_row = [{ | ||
1146 | - 'type': 'header', | ||
1147 | - 'label': [col if col != 0 else ''], | ||
1148 | - 'css_class': 'blank', | ||
1149 | - 'rowspan': 1, | ||
1150 | - 'colspan': 1} for col in xrange(last_col)] | ||
1151 | - table = [first_row] + table | ||
1152 | - return [row for row in table | ||
1153 | - if not all(cell['type'] == 'empty' for cell in row)] | ||
1154 | - | ||
1155 | - def __unicode__(self): | ||
1156 | - return self.name | ||
1157 | - | ||
1158 | - | ||
1159 | class Cell(Model): | 1012 | class Cell(Model): |
1160 | base_form_label = ForeignKey(BaseFormLabel) | 1013 | base_form_label = ForeignKey(BaseFormLabel) |
1161 | prefix = CharField(max_length=20, blank=True) | 1014 | prefix = CharField(max_length=20, blank=True) |
@@ -1227,7 +1080,7 @@ class Cell(Model): | @@ -1227,7 +1080,7 @@ class Cell(Model): | ||
1227 | 1080 | ||
1228 | 1081 | ||
1229 | class TableCell(Cell): | 1082 | class TableCell(Cell): |
1230 | - table_template = ForeignKey(TableTemplate, related_name='table_cells') | 1083 | + table_template = ForeignKey('tables.TableTemplate', related_name='table_cells') |
1231 | pattern_types = ManyToManyField(PatternType) | 1084 | pattern_types = ManyToManyField(PatternType) |
1232 | genders = ManyToManyField(Gender) | 1085 | genders = ManyToManyField(Gender) |
1233 | attribute_values = ManyToManyField( | 1086 | attribute_values = ManyToManyField( |
@@ -1258,7 +1111,7 @@ class TableCell(Cell): | @@ -1258,7 +1111,7 @@ class TableCell(Cell): | ||
1258 | 1111 | ||
1259 | 1112 | ||
1260 | class ExportCell(Cell): | 1113 | class ExportCell(Cell): |
1261 | - table_template = ForeignKey(TableTemplate, related_name='export_cells') | 1114 | + table_template = ForeignKey('tables.TableTemplate', related_name='export_cells') |
1262 | pattern_types = ManyToManyField(PatternType) | 1115 | pattern_types = ManyToManyField(PatternType) |
1263 | genders = ManyToManyField(Gender) | 1116 | genders = ManyToManyField(Gender) |
1264 | attribute_values = ManyToManyField(LexemeAttributeValue) | 1117 | attribute_values = ManyToManyField(LexemeAttributeValue) |
@@ -1272,7 +1125,7 @@ class ExportCell(Cell): | @@ -1272,7 +1125,7 @@ class ExportCell(Cell): | ||
1272 | 1125 | ||
1273 | 1126 | ||
1274 | class TableHeader(Model): | 1127 | class TableHeader(Model): |
1275 | - table_template = ForeignKey(TableTemplate, related_name='headers') | 1128 | + table_template = ForeignKey('tables.TableTemplate', related_name='headers') |
1276 | pattern_types = ManyToManyField(PatternType) | 1129 | pattern_types = ManyToManyField(PatternType) |
1277 | genders = ManyToManyField(Gender) | 1130 | genders = ManyToManyField(Gender) |
1278 | attribute_values = ManyToManyField(LexemeAttributeValue) | 1131 | attribute_values = ManyToManyField(LexemeAttributeValue) |
@@ -1332,7 +1185,7 @@ class HomonymNumber(Model): | @@ -1332,7 +1185,7 @@ class HomonymNumber(Model): | ||
1332 | for pos in poses) | 1185 | for pos in poses) |
1333 | 1186 | ||
1334 | lexeme = ForeignKey(Lexeme) | 1187 | lexeme = ForeignKey(Lexeme) |
1335 | - variant = ForeignKey(Variant) | 1188 | + variant = ForeignKey('tables.Variant') |
1336 | number = IntegerField() | 1189 | number = IntegerField() |
1337 | 1190 | ||
1338 | objects = LexemeNotDeletedManager() | 1191 | objects = LexemeNotDeletedManager() |
export/lexeme_export.py
@@ -11,9 +11,9 @@ from common.util import debug, flatten, uniprint | @@ -11,9 +11,9 @@ from common.util import debug, flatten, uniprint | ||
11 | from export.lexeme_form_query import attr_clauses_combinations, \ | 11 | from export.lexeme_form_query import attr_clauses_combinations, \ |
12 | EXPORT_FROM_CLAUSES, WHERE_CLAUSES | 12 | EXPORT_FROM_CLAUSES, WHERE_CLAUSES |
13 | from dictionary.models import CrossReferenceType, ClassificationValue, \ | 13 | from dictionary.models import CrossReferenceType, ClassificationValue, \ |
14 | - LexemeAttributeValue, Gender, TableTemplate, HomonymNumber, Lexeme, \ | 14 | + LexemeAttributeValue, Gender, HomonymNumber, Lexeme, \ |
15 | LexemeAttribute, SavedExportData | 15 | LexemeAttribute, SavedExportData |
16 | - | 16 | +from tables.models import TableTemplate |
17 | 17 | ||
18 | locale.setlocale(locale.LC_ALL, 'pl_PL.utf8') | 18 | locale.setlocale(locale.LC_ALL, 'pl_PL.utf8') |
19 | 19 |
management/ajax_table_view.py
@@ -5,9 +5,9 @@ from dictionary.forms import LexemeClosedAttributeForm | @@ -5,9 +5,9 @@ from dictionary.forms import LexemeClosedAttributeForm | ||
5 | from management.forms import CellRestrictionsForm, GenderForm, \ | 5 | from management.forms import CellRestrictionsForm, GenderForm, \ |
6 | AttributeValuesForm, BaseFormLabelForm, CSSClassForm, TemplatePreviewForm, \ | 6 | AttributeValuesForm, BaseFormLabelForm, CSSClassForm, TemplatePreviewForm, \ |
7 | TemplatePreviewGenderForm | 7 | TemplatePreviewGenderForm |
8 | -from dictionary.models import TableTemplate, \ | ||
9 | - TableCell, TableHeader, ExportCell, Gender, LexemeAttributeValue | ||
10 | -from tables.models import Variant | 8 | +from dictionary.models import TableCell, TableHeader, ExportCell, Gender, \ |
9 | + LexemeAttributeValue | ||
10 | +from tables.models import Variant, TableTemplate | ||
11 | from patterns.models import BaseFormLabel, PatternType | 11 | from patterns.models import BaseFormLabel, PatternType |
12 | 12 | ||
13 | 13 |
management/forms.py
@@ -10,7 +10,8 @@ from common.models import FlatPage | @@ -10,7 +10,8 @@ from common.models import FlatPage | ||
10 | from common.util import GroupDict | 10 | from common.util import GroupDict |
11 | from dictionary.models import Classification, ClassificationValue, Qualifier, \ | 11 | from dictionary.models import Classification, ClassificationValue, Qualifier, \ |
12 | QualifierExclusionClass, Lexeme, LexemeInflectionPattern, Vocabulary, \ | 12 | QualifierExclusionClass, Lexeme, LexemeInflectionPattern, Vocabulary, \ |
13 | - TableTemplate, Gender, LexemeAttributeValue, MultilingualText | 13 | + Gender, LexemeAttributeValue, MultilingualText |
14 | +from tables.models import TableTemplate | ||
14 | from patterns.models import BaseFormLabel, PatternType, Ending | 15 | from patterns.models import BaseFormLabel, PatternType, Ending |
15 | 16 | ||
16 | CSS_CLASS_CHOICES = ( | 17 | CSS_CLASS_CHOICES = ( |
tables/management/commands/export_template.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | from django.core.management.base import BaseCommand | 2 | from django.core.management.base import BaseCommand |
3 | from common.util import json_encode, uniprint | 3 | from common.util import json_encode, uniprint |
4 | -from dictionary.models import TableTemplate | ||
5 | -from tables.models import Variant | 4 | +from tables.models import Variant, TableTemplate |
6 | 5 | ||
7 | 6 | ||
8 | class Command(BaseCommand): | 7 | class Command(BaseCommand): |
tables/management/commands/export_templates.py
@@ -2,7 +2,7 @@ | @@ -2,7 +2,7 @@ | ||
2 | from django.core.management.base import BaseCommand | 2 | from django.core.management.base import BaseCommand |
3 | 3 | ||
4 | from common.util import uniprint, json_encode | 4 | from common.util import uniprint, json_encode |
5 | -from dictionary.models import TableTemplate | 5 | +from tables.models import TableTemplate |
6 | from tables.management.commands.export_template import export_template | 6 | from tables.management.commands.export_template import export_template |
7 | 7 | ||
8 | 8 |
tables/management/commands/import_template.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | import json | 2 | import json |
3 | from django.core.management.base import BaseCommand | 3 | from django.core.management.base import BaseCommand |
4 | -from dictionary.models import TableTemplate, TableCell, \ | ||
5 | - PatternType, LexemeAttributeValue, TableHeader, ExportCell, Gender | ||
6 | -from tables.models import Variant | 4 | +from dictionary.models import TableCell, \ |
5 | + LexemeAttributeValue, TableHeader, ExportCell, Gender | ||
6 | +from tables.models import Variant, TableTemplate | ||
7 | from patterns.models import BaseFormLabel, PatternType | 7 | from patterns.models import BaseFormLabel, PatternType |
8 | 8 | ||
9 | 9 |
tables/management/commands/import_templates.py
@@ -3,8 +3,8 @@ import json | @@ -3,8 +3,8 @@ import json | ||
3 | 3 | ||
4 | from django.core.management.base import BaseCommand | 4 | from django.core.management.base import BaseCommand |
5 | 5 | ||
6 | -from dictionary.models import TableTemplate, LexemeAttribute, \ | ||
7 | - LexemeAttributeValue | 6 | +from dictionary.models import LexemeAttribute, LexemeAttributeValue |
7 | +from tables.models import TableTemplate | ||
8 | from patterns.models import PatternType | 8 | from patterns.models import PatternType |
9 | from tables.management.commands.import_template import import_template | 9 | from tables.management.commands.import_template import import_template |
10 | 10 |
tables/migrations/0002_tabletemplate.py
0 → 100644
1 | +# -*- coding: utf-8 -*- | ||
2 | +from __future__ import unicode_literals | ||
3 | + | ||
4 | +from django.db import migrations, models | ||
5 | + | ||
6 | + | ||
7 | +class Migration(migrations.Migration): | ||
8 | + | ||
9 | + dependencies = [ | ||
10 | + ('patterns', '0006_auto_20151213_1153'), | ||
11 | + ('dictionary', '0014_auto_20151213_1328'), | ||
12 | + ('tables', '0001_initial'), | ||
13 | + ] | ||
14 | + | ||
15 | + state_operations = [ | ||
16 | + migrations.CreateModel( | ||
17 | + name='TableTemplate', | ||
18 | + fields=[ | ||
19 | + ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | ||
20 | + ('name', models.TextField()), | ||
21 | + ('takes_gender', models.BooleanField(default=False)), | ||
22 | + ('attribute_values', models.ManyToManyField(to='dictionary.LexemeAttributeValue')), | ||
23 | + ('attributes', models.ManyToManyField(to='dictionary.LexemeAttribute')), | ||
24 | + ('cell_attributes', models.ManyToManyField(related_name='templates', to='dictionary.LexemeAttribute')), | ||
25 | + ('parts_of_speech', models.ManyToManyField(to='dictionary.PartOfSpeech')), | ||
26 | + ('pattern_types', models.ManyToManyField(to='patterns.PatternType')), | ||
27 | + ('variant', models.ForeignKey(to='tables.Variant')), | ||
28 | + ], | ||
29 | + ), | ||
30 | + ] | ||
31 | + | ||
32 | + operations = [ | ||
33 | + migrations.SeparateDatabaseAndState(state_operations=state_operations) | ||
34 | + ] |
tables/models.py
1 | # -*- coding: utf-8 -*- | 1 | # -*- coding: utf-8 -*- |
2 | -from django.db.models import Model, CharField | 2 | +from itertools import izip |
3 | + | ||
4 | +from django.db.models import Model, CharField, TextField, ForeignKey, \ | ||
5 | + ManyToManyField, BooleanField | ||
6 | + | ||
7 | +from dictionary.models import PartOfSpeech, LexemeAttribute, \ | ||
8 | + LexemeAttributeValue | ||
9 | +from patterns.models import PatternType | ||
10 | +from tables.util import prepare_table | ||
3 | 11 | ||
4 | 12 | ||
5 | class Variant(Model): | 13 | class Variant(Model): |
@@ -18,3 +26,149 @@ class Variant(Model): | @@ -18,3 +26,149 @@ class Variant(Model): | ||
18 | 26 | ||
19 | class Meta: | 27 | class Meta: |
20 | db_table = 'warianty' | 28 | db_table = 'warianty' |
29 | + | ||
30 | + | ||
31 | +class TableTemplate(Model): | ||
32 | + name = TextField() | ||
33 | + variant = ForeignKey(Variant) | ||
34 | + parts_of_speech = ManyToManyField(PartOfSpeech) | ||
35 | + pattern_types = ManyToManyField(PatternType) | ||
36 | + attributes = ManyToManyField(LexemeAttribute) | ||
37 | + attribute_values = ManyToManyField(LexemeAttributeValue) | ||
38 | + cell_attributes = ManyToManyField(LexemeAttribute, related_name='templates') | ||
39 | + takes_gender = BooleanField(default=False) | ||
40 | + | ||
41 | + def filter_cells_attr(self, cells, attr_vals): | ||
42 | + for attr in self.cell_attributes.all(): | ||
43 | + attr_val = [a for a in attr_vals if a.attribute == attr] | ||
44 | + if len(attr_val) != 1: | ||
45 | + return [] | ||
46 | + cells = cells.filter(attribute_values=attr_val[0]) | ||
47 | + return cells | ||
48 | + | ||
49 | + def filter_cells(self, pattern_type, gender, attr_vals): | ||
50 | + if self.variant.type == Variant.TYPE_TABLE: | ||
51 | + cells = self.table_cells.filter( | ||
52 | + pattern_types=pattern_type).select_related('base_form_label') | ||
53 | + else: | ||
54 | + cells = self.export_cells.filter( | ||
55 | + pattern_types=pattern_type).select_related('base_form_label') | ||
56 | + if self.takes_gender and gender: | ||
57 | + cells = cells.filter(genders=gender) | ||
58 | + if attr_vals: | ||
59 | + cells = self.filter_cells_attr(cells, attr_vals) | ||
60 | + return cells | ||
61 | + | ||
62 | + def filter_table_headers(self, pattern_type, gender, attr_vals): | ||
63 | + headers = self.headers.filter(pattern_types=pattern_type) | ||
64 | + if self.takes_gender and gender: | ||
65 | + headers = headers.filter(genders=gender) | ||
66 | + if attr_vals: | ||
67 | + headers = self.filter_cells_attr(headers, attr_vals) | ||
68 | + return headers | ||
69 | + | ||
70 | + def render_with_pattern(self, pattern, *args, **kwargs): | ||
71 | + base_endings = pattern.base_endings() | ||
72 | + return self.render( | ||
73 | + pattern.type, *args, pattern=pattern, base_endings=base_endings, | ||
74 | + **kwargs) | ||
75 | + | ||
76 | + def render_with_pattern_type(self, pattern_type, *args, **kwargs): | ||
77 | + base_endings = pattern_type.dummy_base_endings() | ||
78 | + return prepare_table(self.render( | ||
79 | + pattern_type, *args, base_endings=base_endings, numbers=True, | ||
80 | + **kwargs)) | ||
81 | + | ||
82 | + def render(self, pattern_type, gender, attr_vals, separated=False, | ||
83 | + numbers=False, pattern=None, **forms_kwargs): | ||
84 | + table_cells = self.filter_cells(pattern_type, gender, attr_vals) | ||
85 | + headers = self.filter_table_headers(pattern_type, gender, attr_vals) | ||
86 | + if table_cells is None or headers is None: | ||
87 | + return [] | ||
88 | + rows = set() | ||
89 | + last_col = 0 | ||
90 | + for table_cell in table_cells: | ||
91 | + rows.add(table_cell.row) | ||
92 | + col = table_cell.col + table_cell.colspan - 1 | ||
93 | + if col > last_col: | ||
94 | + last_col = col | ||
95 | + for header in headers: | ||
96 | + rows.add(header.row) | ||
97 | + col = header.col + header.colspan - 1 | ||
98 | + if col > last_col: | ||
99 | + last_col = col | ||
100 | + if numbers: | ||
101 | + last_col += 1 | ||
102 | + table = [[{'type': 'empty'} for i in xrange(last_col)] for row in rows] | ||
103 | + rows = sorted(rows) | ||
104 | + if numbers: | ||
105 | + for row, table_row in izip(rows, table): | ||
106 | + table_row[0] = { | ||
107 | + 'type': 'header', | ||
108 | + 'label': [row], | ||
109 | + 'css_class': 'blank', | ||
110 | + 'rowspan': 1, | ||
111 | + 'colspan': 1} | ||
112 | + # słownik: nr rzędu w bazie -> rzeczywisty numer rzędu | ||
113 | + row_translate = dict((r, i) for i, r in enumerate(rows)) | ||
114 | + for tc in table_cells: | ||
115 | + if numbers: | ||
116 | + x = tc.col | ||
117 | + else: | ||
118 | + x = tc.col - 1 | ||
119 | + y = row_translate[tc.row] | ||
120 | + table_cell = table[y][x] | ||
121 | + assert table_cell['type'] != 'span' | ||
122 | + separator = u'·' if separated else u'' | ||
123 | + forms = [f + (pattern,) | ||
124 | + for f in tc.forms(separator=separator, **forms_kwargs)] | ||
125 | + if not forms: | ||
126 | + continue | ||
127 | + if table_cell['type'] == 'empty': | ||
128 | + table[y][x] = { | ||
129 | + 'type': 'forms', | ||
130 | + 'forms': forms, | ||
131 | + 'rowspan': tc.rowspan, | ||
132 | + 'colspan': tc.colspan, | ||
133 | + } | ||
134 | + for i in xrange(tc.colspan): | ||
135 | + for j in xrange(tc.rowspan): | ||
136 | + if (i, j) != (0, 0): | ||
137 | + assert table[y + j][x + i]['type'] == 'empty' | ||
138 | + table[y + j][x + i]['type'] = 'span' | ||
139 | + else: | ||
140 | + assert tc.rowspan == table_cell['rowspan'] | ||
141 | + assert tc.colspan == table_cell['colspan'] | ||
142 | + table_cell['forms'] += forms | ||
143 | + for header in headers: | ||
144 | + if numbers: | ||
145 | + x = header.col | ||
146 | + else: | ||
147 | + x = header.col - 1 | ||
148 | + y = row_translate[header.row] | ||
149 | + assert table[y][x]['type'] == 'empty' | ||
150 | + table[y][x] = { | ||
151 | + 'type': 'label', | ||
152 | + 'label': [header.label], | ||
153 | + 'css_class': header.css_class, | ||
154 | + 'rowspan': header.rowspan, | ||
155 | + 'colspan': header.colspan, | ||
156 | + } | ||
157 | + for i in xrange(header.colspan): | ||
158 | + for j in xrange(header.rowspan): | ||
159 | + if (i, j) != (0, 0): | ||
160 | + assert table[y + j][x + i]['type'] == 'empty' | ||
161 | + table[y + j][x + i]['type'] = 'span' | ||
162 | + if numbers: | ||
163 | + first_row = [{ | ||
164 | + 'type': 'header', | ||
165 | + 'label': [col if col != 0 else ''], | ||
166 | + 'css_class': 'blank', | ||
167 | + 'rowspan': 1, | ||
168 | + 'colspan': 1} for col in xrange(last_col)] | ||
169 | + table = [first_row] + table | ||
170 | + return [row for row in table | ||
171 | + if not all(cell['type'] == 'empty' for cell in row)] | ||
172 | + | ||
173 | + def __unicode__(self): | ||
174 | + return self.name | ||
21 | \ No newline at end of file | 175 | \ No newline at end of file |