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 from common.util import uniprint
8 8 from export.lexeme_form_query import WHERE_CLAUSES, \
9 9 attr_clauses_combinations, TABLE_FROM_CLAUSES
10   -from dictionary.models import TableTemplate
  10 +from tables.models import TableTemplate
11 11  
12 12  
13 13 class Command(BaseCommand):
... ...
dictionary/management/commands/create_forms.py
... ... @@ -7,7 +7,8 @@ from django.db.transaction import atomic
7 7 from common.util import uniprint
8 8 from export.lexeme_form_query import WHERE_CLAUSES, \
9 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 14 class Command(BaseCommand):
... ...
dictionary/management/commands/stale/convert_tables.py
... ... @@ -3,7 +3,7 @@ from django.core.management import BaseCommand
3 3 from common.util import GroupDict
4 4 from dictionary.models import Cell, TableTemplate, PatternType, TableTemplate, TableCell, TableHeader, \
5 5 TableHeader, LexemeAttribute, ExportCell, InflectionCharacteristic, LexemeAttributeValue
6   -from tables.models import Variant
  6 +from tables.models import Variant, TableTemplate
7 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 5 from common.util import uniopen
6 6 from dictionary.models import TableTemplate, Cell, TableCell, PartOfSpeech, \
7 7 PatternType, InflectionCharacteristic
8   -from tables.models import Variant
  8 +from tables.models import Variant, TableTemplate
9 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 1 # -*- coding: utf-8 -*-
2 2 import json
3 3 from collections import OrderedDict
4   -from itertools import izip
5 4  
6 5 from django.conf import settings
7 6 from django.contrib.auth.models import User, Permission, AnonymousUser
... ... @@ -13,7 +12,6 @@ from accounts.util import users_with_perm
13 12 from common.models import NotDeletedManager
14 13 from common.util import no_history
15 14 from patterns.models import InflectionType, BaseFormLabel, PatternType, Pattern
16   -from tables.models import Variant
17 15 from tables.util import prepare_table
18 16  
19 17  
... ... @@ -709,6 +707,7 @@ class LexemeInflectionPattern(Model):
709 707  
710 708 def table_template(self, variant, attr_vals=None, pos=None):
711 709 part_of_speech = pos or self.lexeme.part_of_speech
  710 + from tables.models import TableTemplate
712 711 tts = TableTemplate.objects.filter(
713 712 parts_of_speech=part_of_speech, variant=variant,
714 713 pattern_types=self.pattern.type)
... ... @@ -1010,152 +1009,6 @@ class CrossReference(Model):
1010 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 1012 class Cell(Model):
1160 1013 base_form_label = ForeignKey(BaseFormLabel)
1161 1014 prefix = CharField(max_length=20, blank=True)
... ... @@ -1227,7 +1080,7 @@ class Cell(Model):
1227 1080  
1228 1081  
1229 1082 class TableCell(Cell):
1230   - table_template = ForeignKey(TableTemplate, related_name='table_cells')
  1083 + table_template = ForeignKey('tables.TableTemplate', related_name='table_cells')
1231 1084 pattern_types = ManyToManyField(PatternType)
1232 1085 genders = ManyToManyField(Gender)
1233 1086 attribute_values = ManyToManyField(
... ... @@ -1258,7 +1111,7 @@ class TableCell(Cell):
1258 1111  
1259 1112  
1260 1113 class ExportCell(Cell):
1261   - table_template = ForeignKey(TableTemplate, related_name='export_cells')
  1114 + table_template = ForeignKey('tables.TableTemplate', related_name='export_cells')
1262 1115 pattern_types = ManyToManyField(PatternType)
1263 1116 genders = ManyToManyField(Gender)
1264 1117 attribute_values = ManyToManyField(LexemeAttributeValue)
... ... @@ -1272,7 +1125,7 @@ class ExportCell(Cell):
1272 1125  
1273 1126  
1274 1127 class TableHeader(Model):
1275   - table_template = ForeignKey(TableTemplate, related_name='headers')
  1128 + table_template = ForeignKey('tables.TableTemplate', related_name='headers')
1276 1129 pattern_types = ManyToManyField(PatternType)
1277 1130 genders = ManyToManyField(Gender)
1278 1131 attribute_values = ManyToManyField(LexemeAttributeValue)
... ... @@ -1332,7 +1185,7 @@ class HomonymNumber(Model):
1332 1185 for pos in poses)
1333 1186  
1334 1187 lexeme = ForeignKey(Lexeme)
1335   - variant = ForeignKey(Variant)
  1188 + variant = ForeignKey('tables.Variant')
1336 1189 number = IntegerField()
1337 1190  
1338 1191 objects = LexemeNotDeletedManager()
... ...
export/lexeme_export.py
... ... @@ -11,9 +11,9 @@ from common.util import debug, flatten, uniprint
11 11 from export.lexeme_form_query import attr_clauses_combinations, \
12 12 EXPORT_FROM_CLAUSES, WHERE_CLAUSES
13 13 from dictionary.models import CrossReferenceType, ClassificationValue, \
14   - LexemeAttributeValue, Gender, TableTemplate, HomonymNumber, Lexeme, \
  14 + LexemeAttributeValue, Gender, HomonymNumber, Lexeme, \
15 15 LexemeAttribute, SavedExportData
16   -
  16 +from tables.models import TableTemplate
17 17  
18 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 5 from management.forms import CellRestrictionsForm, GenderForm, \
6 6 AttributeValuesForm, BaseFormLabelForm, CSSClassForm, TemplatePreviewForm, \
7 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 11 from patterns.models import BaseFormLabel, PatternType
12 12  
13 13  
... ...
management/forms.py
... ... @@ -10,7 +10,8 @@ from common.models import FlatPage
10 10 from common.util import GroupDict
11 11 from dictionary.models import Classification, ClassificationValue, Qualifier, \
12 12 QualifierExclusionClass, Lexeme, LexemeInflectionPattern, Vocabulary, \
13   - TableTemplate, Gender, LexemeAttributeValue, MultilingualText
  13 + Gender, LexemeAttributeValue, MultilingualText
  14 +from tables.models import TableTemplate
14 15 from patterns.models import BaseFormLabel, PatternType, Ending
15 16  
16 17 CSS_CLASS_CHOICES = (
... ...
tables/management/commands/export_template.py
1 1 # -*- coding: utf-8 -*-
2 2 from django.core.management.base import BaseCommand
3 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 7 class Command(BaseCommand):
... ...
tables/management/commands/export_templates.py
... ... @@ -2,7 +2,7 @@
2 2 from django.core.management.base import BaseCommand
3 3  
4 4 from common.util import uniprint, json_encode
5   -from dictionary.models import TableTemplate
  5 +from tables.models import TableTemplate
6 6 from tables.management.commands.export_template import export_template
7 7  
8 8  
... ...
tables/management/commands/import_template.py
1 1 # -*- coding: utf-8 -*-
2 2 import json
3 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 7 from patterns.models import BaseFormLabel, PatternType
8 8  
9 9  
... ...
tables/management/commands/import_templates.py
... ... @@ -3,8 +3,8 @@ import json
3 3  
4 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 8 from patterns.models import PatternType
9 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 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 13 class Variant(Model):
... ... @@ -18,3 +26,149 @@ class Variant(Model):
18 26  
19 27 class Meta:
20 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 175 \ No newline at end of file
... ...