def test_localization_of_pagination_strings(self): class Table(tables.Table): foo = tables.Column(verbose_name='my column') bar = tables.Column() class Meta: default = '---' table = Table(map(lambda x: [x, x + 100], range(40))) request = build_request('/?page=2') RequestConfig(request, paginate={'per_page': 10}).configure(table) with translation_override('en'): html = table.as_html(request) self.assertIn('previous', html) self.assertIn('next', html) with translation_override('nl'): html = table.as_html(request) self.assertIn('vorige', html) self.assertIn('volgende', html) with translation_override('fr'): html = table.as_html(request) self.assertIn('précédent', html) self.assertIn('suivant', html)
def test_localization_of_pagination_strings(self): class Table(tables.Table): foo = tables.Column(verbose_name="my column") bar = tables.Column() class Meta: default = "---" table = Table(map(lambda x: [x, x + 100], range(40))) request = build_request("/?page=2") RequestConfig(request, paginate={"per_page": 10}).configure(table) with translation_override("en"): html = table.as_html(request) self.assertIn("previous", html) self.assertIn("next", html) with translation_override("nl"): html = table.as_html(request) self.assertIn("vorige", html) self.assertIn("volgende", html) with translation_override("fr"): html = table.as_html(request) self.assertIn("précédent", html) self.assertIn("suivant", html)
def construct_change_message(form, formsets, add): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ # Evaluating `form.changed_data` prior to disabling translations is required # to avoid fields affected by localization from being included incorrectly, # e.g. where date formats differ such as MM/DD/YYYY vs DD/MM/YYYY. changed_data = form.changed_data with translation_override(None): # Deactivate translations while fetching verbose_name for form # field labels and using `field_name`, if verbose_name is not provided. # Translations will happen later on LogEntry access. changed_field_labels = _get_changed_field_labels_from_form(form, changed_data) change_message = [] if add: change_message.append({"added": {}}) elif form.changed_data: change_message.append({"changed": {"fields": changed_field_labels}}) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append( { "added": { "name": str(added_object._meta.verbose_name), "object": str(added_object), } } ) for changed_object, changed_fields in formset.changed_objects: change_message.append( { "changed": { "name": str(changed_object._meta.verbose_name), "object": str(changed_object), "fields": _get_changed_field_labels_from_form( formset.forms[0], changed_fields ), } } ) for deleted_object in formset.deleted_objects: change_message.append( { "deleted": { "name": str(deleted_object._meta.verbose_name), "object": str(deleted_object), } } ) return change_message
def test_using_Meta_model(self): # Now we'll try using a table with Meta.model class PersonTable(tables.Table): first_name = tables.Column(verbose_name="OVERRIDE") class Meta: model = Person # Issue #16 table = PersonTable(Person.objects.all()) self.assertEqual("Translation test", table.columns["trans_test"].verbose_name) self.assertEqual("Translation test lazy", table.columns["trans_test_lazy"].verbose_name) self.assertEqual("Web site", table.columns["website"].verbose_name) self.assertEqual("Birthdate", table.columns["birthdate"].verbose_name) self.assertEqual("OVERRIDE", table.columns["first_name"].verbose_name) class PersonTable(tables.Table): class Meta: model = Person table = PersonTable(Person.objects.all()) with translation_override("ua"): self.assertEqual( "Тест ленивого перекладу", table.columns["trans_test_lazy"].verbose_name )
def email_message(self, connection=None): subject = smart_text(self.subject) if self.template is not None: render_language = self.context.get('render_language', settings.LANGUAGE_CODE) context = Context(self.context) with translation_override(render_language): subject = Template(self.template.subject).render(context) message = Template(self.template.content).render(context) html_message = Template(self.template.html_content).render(context) else: subject = self.subject message = self.message html_message = self.html_message if html_message: if not message: message = BeautifulSoup(html_message).text mailmsg = EmailMultiAlternatives( subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, connection=connection, headers=self.headers) mailmsg.attach_alternative(html_message, 'text/html') else: mailmsg = EmailMessage( subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, connection=connection, headers=self.headers) for attachment in self.attachments.all(): mailmsg.attach(attachment.name, attachment.file.read()) return mailmsg
def test_using_Meta_model(self): # Now we'll try using a table with Meta.model class PersonTable(tables.Table): first_name = tables.Column(verbose_name='OVERRIDE') class Meta: model = Person # Issue #16 table = PersonTable(Person.objects.all()) self.assertEqual('Translation test', table.columns['trans_test'].verbose_name) self.assertEqual('Translation test lazy', table.columns['trans_test_lazy'].verbose_name) self.assertEqual('Web site', table.columns['website'].verbose_name) self.assertEqual('Birthdate', table.columns['birthdate'].verbose_name) self.assertEqual('OVERRIDE', table.columns['first_name'].verbose_name) class PersonTable(tables.Table): class Meta: model = Person table = PersonTable(Person.objects.all()) with translation_override('ua'): self.assertEqual('Тест ленивого перекладу', table.columns['trans_test_lazy'].verbose_name)
def test_using_Meta_model(self): # Now we'll try using a table with Meta.model class PersonTable(tables.Table): first_name = tables.Column(verbose_name='OVERRIDE') class Meta: model = Person # Issue #16 table = PersonTable(Person.objects.all()) assert 'Translation Test' == table.columns['trans_test'].verbose_name assert 'Translation Test Lazy' == table.columns[ 'trans_test_lazy'].verbose_name assert 'Web Site' == table.columns['website'].verbose_name assert 'Birthdate' == table.columns['birthdate'].verbose_name assert 'OVERRIDE' == table.columns['first_name'].verbose_name # Verbose name should be lazy if it comes from the model field and # the column was not declared explicitly class PersonTable(tables.Table): class Meta: model = Person table = PersonTable(Person.objects.all()) assert type( table.columns['trans_test_lazy'].verbose_name) is not six.text_type with translation_override('ua'): assert 'Тест Ленивого Перекладу' == table.columns[ 'trans_test_lazy'].verbose_name
def test_localization_check_in_meta(settings): class TableNoLocalize(tables.Table): name = tables.Column(verbose_name='my column') class Meta: default = '---' class TableLocalize(tables.Table): name = tables.Column(verbose_name='my column') class Meta: default = '---' localize = ('name', ) class TableUnlocalize(tables.Table): name = tables.Column(verbose_name='my column') class Meta: default = '---' unlocalize = ('name', ) class TableLocalizePrecedence(tables.Table): name = tables.Column(verbose_name='my column') class Meta: default = '---' unlocalize = ('name', ) localize = ('name', ) simple_test_data = [{'name': 1234.5}] expected_results = { None: '1234.5', False: '1234.5', True: '1{0}234,5'.format(' ') # non-breaking space } request = build_request('/') # No localize html = TableNoLocalize(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[None]) in html settings.USE_L10N = True settings.USE_THOUSAND_SEPARATOR = True with translation_override('pl'): # the same as in localization_check. # with localization and polish locale we get formatted output html = TableNoLocalize(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[True]) in html # localize html = TableLocalize(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[True]) in html # unlocalize html = TableUnlocalize(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[False]) in html # test unlocalize higher precedence html = TableLocalizePrecedence(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[False]) in html
def construct_change_message(form, formsets, add): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ changed_data = form.changed_data with translation_override(None): # Deactivate translations while fetching verbose_name for form # field labels and using `field_name`, if verbose_name is not provided. # Translations will happen later on LogEntry access. changed_field_labels = _get_changed_field_labels_from_form( form, changed_data) change_message = [] if add: change_message.append({'added': {}}) elif form.changed_data: change_message.append({'changed': {'fields': changed_field_labels}}) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append({ 'added': { 'name': str(added_object._meta.verbose_name), 'object': str(added_object), } }) for changed_object, changed_fields in formset.changed_objects: change_message.append({ 'changed': { 'name': str(changed_object._meta.verbose_name), 'object': str(changed_object), 'fields': changed_fields, } }) for deleted_object in formset.deleted_objects: change_message.append({ 'deleted': { 'name': str(deleted_object._meta.verbose_name), 'object': str(deleted_object), } }) return change_message
def _content_for_related(self): """Text to use in elastic more_like_this query.""" content = [self.title, self.content] if self.topic: with translation_override(self.locale): # use the question's locale, rather than the user's content += [pgettext("DB: products.Topic.title", self.topic.title)] return content
def test_localization_of_pagination_string(): class Table(tables.Table): foo = tables.Column(verbose_name='my column') bar = tables.Column() class Meta: default = '---' table = Table(map(lambda x: [x, x + 100], range(40))) request = build_request('/') RequestConfig(request, paginate={'per_page': 10}).configure(table) with translation_override('en'): assert 'Page 1 of 4' in table.as_html(request) with translation_override('nl'): assert 'Pagina 1 van 4' in table.as_html(request) with translation_override('it'): assert 'Pagina 1 di 4' in table.as_html(request)
def test_localization_different_locale(self): with translation_override("pl"): # with default polish locales and enabled thousand separator # 1234.5 is formatted as "1 234,5" with nbsp self.assert_cond_localized_table(True, True) # with localize = False there should be no formatting self.assert_cond_localized_table(False, False) # with localize = None and USE_L10N = True # there should be the same formatting as with localize = True self.assert_cond_localized_table(None, True)
def construct_change_message(self, request, form, formsets, add=False): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ change_message = [] if add: change_message.append( str( _('Added with fields') + ': ' + ', '.join([ f'{field.replace("_", " ")}: {form.cleaned_data.get(field) or " - "}' for field in form.changed_data ]))) elif form.changed_data: change_message.append( str( _('Changed with fields') + ': ' + ', '.join([ f'{field.replace("_", " ")}:' + str(_(" from '")) + f'{form.initial.get(field) or " - "}' + str(_("' to '")) + f'{form.cleaned_data.get(field) or " - "}' + "'" for field in form.changed_data ]))) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append( str( _('Added' + ': ' + force_text( added_object._meta.verbose_name))) + f' {force_text(added_object)} ') for index, (changed_object, changed_fields) in enumerate( formset.changed_objects): change_message.append( str( _('Changed') + ' ' + force_text(changed_object._meta.verbose_name) + f' {force_text(changed_object)}, fields: ' + ', '.join([ f'{field.replace("_", " ")}: ' + f'{formset[index].cleaned_data.get(field) or " - "}' + "'" for field in changed_fields ]))) for deleted_object in formset.deleted_objects: change_message.append( change_message.append( str( _('Deleted' + ': ' + force_text( deleted_object._meta.verbose_name))))) return change_message
def test_localization_check(settings): def get_cond_localized_table(localizeit=None): ''' helper function for defining Table class conditionally ''' class TestTable(tables.Table): name = tables.Column(verbose_name="my column", localize=localizeit) return TestTable simple_test_data = [{'name': 1234.5}] expected_results = { None: '1234.5', False: '1234.5', True: '1 234,5' # non-breaking space } request = build_request('/') # no localization html = get_cond_localized_table(None)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[None]) in html # unlocalize html = get_cond_localized_table(False)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[False]) in html settings.USE_L10N = True settings.USE_THOUSAND_SEPARATOR = True with translation_override('pl'): # with default polish locales and enabled thousand separator # 1234.5 is formatted as "1 234,5" with nbsp html = get_cond_localized_table(True)(simple_test_data).as_html( request) assert '<td class="name">{0}</td>'.format( expected_results[True]) in html # with localize = False there should be no formatting html = get_cond_localized_table(False)(simple_test_data).as_html( request) assert '<td class="name">{0}</td>'.format( expected_results[False]) in html # with localize = None and USE_L10N = True # there should be the same formatting as with localize = True html = get_cond_localized_table(None)(simple_test_data).as_html( request) assert '<td class="name">{0}</td>'.format( expected_results[True]) in html
def proposal_notify_initiator(self): """ Notify initiator about the status of the current proposal. """ action_str = PROPOSAL_ACTION_TYPES.get(self.action) action_sym = PROPOSAL_ACTION_TYPES.symbolic(self.action) status_str = PROPOSAL_STATUS_TYPES.get(self.status) recipient = self.user base_subject, base_body = PROPOSAL_NOTIFY_INITIATOR_EMAILS[self.status] email_subject = email_body = None with translation_override(recipient.prefered_language): email_kwargs = dict( username=recipient.username, action=action_str, target=self.target, adverb=pgettext_lazy(action_sym, u'to'), context=self.context, status=status_str, message=self.message, reason=self.reason, reviewer=self.reviewer.username, ) email_subject = u'{0}{1}'.format( settings.EMAIL_SUBJECT_PREFIX, base_subject.format(**email_kwargs), ) email_body = base_body.format(**email_kwargs) try: recipient.send_email( subject=email_subject, message=email_body, from_email=settings.DEFAULT_FROM_EMAIL ) except: LOGGER.exception(u'Could not send proposal notification email.') return False LOGGER.info(u'%s: sent proposal notification email to %s.', self, recipient.email) return True
def prepare_email_message(self): if self.template is not None: render_language = self.context.get('render_language', settings.LANGUAGE_CODE) _context = Context(self.context) with translation_override(render_language): subject = Template(self.template.subject).render(_context) message = Template(self.template.content).render(_context) html_message = Template( self.template.html_content).render(_context) else: subject = smart_text(self.subject) message = self.message html_message = self.html_message connection = connections[self.backend_alias or 'default'] if html_message: if not message: message = html_to_text(html_message) msg = EmailMultiAlternatives(subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) msg.attach_alternative(html_message, 'text/html') else: msg = EmailMessage(subject=subject, body=message, from_email=self.from_email, to=self.to, bcc=self.bcc, cc=self.cc, headers=self.headers, connection=connection) for attachment in self.attachments.all(): msg.attach(attachment.name, attachment.file.read(), mimetype=attachment.mimetype or None) attachment.file.close() self._cached_email_message = msg return msg
def proposal_notify_initiator(self): """ Notify initiator about the status of the current proposal. """ action_str = PROPOSAL_ACTION_TYPES.get(self.action) action_sym = PROPOSAL_ACTION_TYPES.symbolic(self.action) status_str = PROPOSAL_STATUS_TYPES.get(self.status) recipient = self.user base_subject, base_body = PROPOSAL_NOTIFY_INITIATOR_EMAILS[self.status] email_subject = email_body = None with translation_override(recipient.prefered_language): email_kwargs = dict( username=recipient.username, action=action_str, target=self.target, adverb=pgettext_lazy(action_sym, u'to'), context=self.context, status=status_str, message=self.message, reason=self.reason, reviewer=self.reviewer.username, ) email_subject = u'{0}{1}'.format( settings.EMAIL_SUBJECT_PREFIX, base_subject.format(**email_kwargs), ) email_body = base_body.format(**email_kwargs) try: recipient.send_email(subject=email_subject, message=email_body, from_email=settings.DEFAULT_FROM_EMAIL) except: LOGGER.exception(u'Could not send proposal notification email.') return False LOGGER.info(u'%s: sent proposal notification email to %s.', self, recipient.email) return True
def construct_change_message(form, formsets, add): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ change_message = [] if add: change_message.append({"added": {}}) elif form.changed_data: change_message.append({"changed": {"fields": form.changed_data}}) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append( { "added": { "name": force_text(added_object._meta.verbose_name), "object": force_text(added_object), } } ) for changed_object, changed_fields in formset.changed_objects: change_message.append( { "changed": { "name": force_text(changed_object._meta.verbose_name), "object": force_text(changed_object), "fields": changed_fields, } } ) for deleted_object in formset.deleted_objects: change_message.append( { "deleted": { "name": force_text(deleted_object._meta.verbose_name), "object": force_text(deleted_object), } } ) return change_message
def test_localization_check_in_meta_different_locale(self): class TableNoLocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" class TableLocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" localize = ("name",) class TableUnlocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" unlocalize = ("name",) class TableLocalizePrecedence(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" unlocalize = ("name",) localize = ("name",) with translation_override("pl"): # the same as in localization_check. # with localization and polish locale we get formatted output self.assert_table_localization(TableNoLocalize, True) # localize self.assert_table_localization(TableLocalize, True) # unlocalize self.assert_table_localization(TableUnlocalize, False) # test unlocalize has higher precedence self.assert_table_localization(TableLocalizePrecedence, False)
def test_localization_check_in_meta_different_locale(self): class TableNoLocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" class TableLocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" localize = ("name", ) class TableUnlocalize(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" unlocalize = ("name", ) class TableLocalizePrecedence(tables.Table): name = tables.Column(verbose_name="my column") class Meta: default = "---" unlocalize = ("name", ) localize = ("name", ) with translation_override("pl"): # the same as in localization_check. # with localization and polish locale we get formatted output self.assert_table_localization(TableNoLocalize, True) # localize self.assert_table_localization(TableLocalize, True) # unlocalize self.assert_table_localization(TableUnlocalize, False) # test unlocalize has higher precedence self.assert_table_localization(TableLocalizePrecedence, False)
def test_localization_check(settings): def get_cond_localized_table(localizeit=None): ''' helper function for defining Table class conditionally ''' class TestTable(tables.Table): name = tables.Column(verbose_name="my column", localize=localizeit) return TestTable simple_test_data = [{'name': 1234.5}] expected_results = { None: '1234.5', False: '1234.5', True: '1 234,5' # non-breaking space } request = build_request('/') # no localization html = get_cond_localized_table(None)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[None]) in html # unlocalize html = get_cond_localized_table(False)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[False]) in html settings.USE_L10N = True settings.USE_THOUSAND_SEPARATOR = True with translation_override('pl'): # with default polish locales and enabled thousand separator # 1234.5 is formatted as "1 234,5" with nbsp html = get_cond_localized_table(True)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[True]) in html # with localize = False there should be no formatting html = get_cond_localized_table(False)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[False]) in html # with localize = None and USE_L10N = True # there should be the same formatting as with localize = True html = get_cond_localized_table(None)(simple_test_data).as_html(request) assert '<td class="name">{0}</td>'.format(expected_results[True]) in html
def get_language_links(context, language_list): for lang, lang_name in language_list: with translation_override(lang): if context['page'].get('url_slugs_localized'): slug = context['page']['url_slugs_localized'].get(lang, '') else: slug = context['page'].get('url_slug', '') url = '%s/%s%s%s' % ( gettext_lazy(context['page'].get('base_url', '')), gettext_lazy(context['page'].get('url', '')), slug, gettext_lazy(context['page'].get('url_slug_operation', '')) ) yield { 'language_code': lang, 'language_name': lang_name, 'url': url }
def construct_change_message(form, formsets, add): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ change_message = [] if add: change_message.append({'added': {}}) elif form.changed_data: change_message.append({'changed': {'fields': form.changed_data}}) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append({ 'added': { 'name': force_text(added_object._meta.verbose_name), 'object': force_text(added_object), } }) for changed_object, changed_fields in formset.changed_objects: change_message.append({ 'changed': { 'name': force_text(changed_object._meta.verbose_name), 'object': force_text(changed_object), 'fields': changed_fields, } }) for deleted_object in formset.deleted_objects: change_message.append({ 'deleted': { 'name': force_text(deleted_object._meta.verbose_name), 'object': force_text(deleted_object), } }) return change_message
def construct_change_message(self, request, form, formsets, add=False): """ Construct a JSON structure describing changes from a changed object. Translations are deactivated so that strings are stored untranslated. Translation happens later on LogEntry access. """ change_message = [] if add: change_message.append({'added': form.cleaned_data}) elif form.changed_data: changed_data_detail = [] for each_changed_data in form.changed_data: before_change_data = form.initial.get(each_changed_data) after_changed_data = form.cleaned_data.get(each_changed_data) changed_detail = _('{0}: {1} to {0}: {2}').format( each_changed_data, before_change_data, after_changed_data) changed_data_detail.append(changed_detail) change_message.append({'changed': {'fields': changed_data_detail}}) if formsets: with translation_override(None): for formset in formsets: for added_object in formset.new_objects: change_message.append({ 'added': { 'name': force_text(added_object._meta.verbose_name), 'object': force_text(added_object), 'fields': model_to_dict(added_object) } }) for index, (changed_object, changed_fields) in enumerate( formset.changed_objects): changed_fields_detail = [] for each_changed_field in changed_fields: before_change_data = formset.initial_forms[ index].initial.get(each_changed_field) after_changed_data = formset.initial_forms[ index].cleaned_data.get(each_changed_field) changed_detail = _('{0}: {1} to {0}: {2}').format( each_changed_field, before_change_data, after_changed_data) changed_fields_detail.append(changed_detail) change_message.append({ 'changed': { 'name': force_text(changed_object._meta.verbose_name), 'object': force_text(changed_object), 'fields': changed_fields_detail, } }) for deleted_object in formset.deleted_objects: change_message.append({ 'deleted': { 'name': force_text(deleted_object._meta.verbose_name), 'object': force_text(deleted_object), 'fields': model_to_dict(deleted_object) } }) return change_message
def test_column_verbose_name(): ''' When using queryset data as input for a table, default to using model field verbose names rather than an autogenerated string based on the column name. However if a column does explicitly describe a verbose name, it should be used. ''' class PersonTable(tables.Table): ''' The test_colX columns are to test that the accessor is used to determine the field on the model, rather than the column name. ''' first_name = tables.Column() fn1 = tables.Column(accessor='first_name') fn2 = tables.Column(accessor='first_name.upper') fn3 = tables.Column(accessor='last_name', verbose_name='OVERRIDE') fn4 = tables.Column(accessor='last_name', verbose_name='override') last_name = tables.Column() ln1 = tables.Column(accessor='last_name') ln2 = tables.Column(accessor='last_name.upper') ln3 = tables.Column(accessor='last_name', verbose_name='OVERRIDE') region = tables.Column(accessor='occupation.region.name') r1 = tables.Column(accessor='occupation.region.name') r2 = tables.Column(accessor='occupation.region.name.upper') r3 = tables.Column(accessor='occupation.region.name', verbose_name='OVERRIDE') trans_test = tables.Column() trans_test_lazy = tables.Column() # The Person model has a ``first_name`` and ``last_name`` field, but only # the ``last_name`` field has an explicit ``verbose_name`` set. This means # that we should expect that the two columns that use the ``last_name`` # field should both use the model's ``last_name`` field's ``verbose_name``, # however both fields that use the ``first_name`` field should just use a # titlised version of the column name as the column header. table = PersonTable(Person.objects.all()) # Should be generated (capitalized column name) assert 'First Name' == table.columns['first_name'].verbose_name assert 'First Name' == table.columns['fn1'].verbose_name assert 'First Name' == table.columns['fn2'].verbose_name assert 'OVERRIDE' == table.columns['fn3'].verbose_name assert 'override' == table.columns['fn4'].verbose_name # Should use the titlised model field's verbose_name assert 'Surname' == table.columns['last_name'].verbose_name assert 'Surname' == table.columns['ln1'].verbose_name assert 'Surname' == table.columns['ln2'].verbose_name assert 'OVERRIDE' == table.columns['ln3'].verbose_name assert 'Name' == table.columns['region'].verbose_name assert 'Name' == table.columns['r1'].verbose_name assert 'Name' == table.columns['r2'].verbose_name assert 'OVERRIDE' == table.columns['r3'].verbose_name assert 'Translation Test' == table.columns['trans_test'].verbose_name assert 'Translation Test Lazy' == table.columns[ 'trans_test_lazy'].verbose_name # ------------------------------------------------------------------------- # Now we'll try using a table with Meta.model class PersonTable(tables.Table): first_name = tables.Column(verbose_name='OVERRIDE') class Meta: model = Person # Issue #16 table = PersonTable(Person.objects.all()) assert 'Translation Test' == table.columns['trans_test'].verbose_name assert 'Translation Test Lazy' == table.columns[ 'trans_test_lazy'].verbose_name assert 'Web Site' == table.columns['website'].verbose_name assert 'Birthdate' == table.columns['birthdate'].verbose_name assert 'OVERRIDE' == table.columns['first_name'].verbose_name # Verbose name should be lazy if it comes from the model field and # the column was not declared explicitly class PersonTable(tables.Table): class Meta: model = Person table = PersonTable(Person.objects.all()) assert type( table.columns['trans_test_lazy'].verbose_name) is not six.text_type with translation_override('ua'): assert 'Тест Ленивого Перекладу' == table.columns[ 'trans_test_lazy'].verbose_name