Commit ad31813dea8a64e8157b4ec7b0d54549f6618e34

Authored by janek@kublik
1 parent d1ae5454

migracja TableTemplate

--HG--
branch : beta
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