def test_basic_iter(self): class TestForm(forms.Form): first_name = forms.CharField(label='First name', required=False) last_name = forms.CharField(label='Last name') phone = forms.CharField(label='Phone') cell = forms.CharField(label='Cell') fax = forms.CharField(label='Fax') fbm = FieldBlockManager( ('names', 'Names', ('first_name', 'last_name')), ('details', 'Details', ('cell', 'phone', 'fax')), ) form = TestForm() with self.assertNoException(): blocks_list = [*fbm.build(form)] self.assertEqual(2, len(blocks_list)) names_group = blocks_list[0] self.assertIsInstance(names_group, tuple) self.assertEqual(2, len(names_group)) self.assertEqual('Names', names_group[0]) details_group = blocks_list[1] self.assertEqual('Details', details_group[0])
def test_new01(self): class TestForm(forms.Form): first_name = forms.CharField(label='First name') last_name = forms.CharField(label='Last name') phone = forms.CharField(label='Phone') cell = forms.CharField(label='Cell') fax = forms.CharField(label='Fax') fbm1 = FieldBlockManager( ('names', 'Names', ('last_name', 'first_name')), ) fbm2 = fbm1.new(('details', 'Details', ('cell', 'phone', 'fax')), ) self.assertIsInstance(fbm2, FieldBlockManager) self.assertIsNot(fbm2, fbm1) form = TestForm() blocks = fbm2.build(form) with self.assertNoException(): names_group = blocks['names'] self.assertEqual('Names', names_group[0]) self.assertListEqual( ['last_name', 'first_name'], [bfield.name for bfield, required in names_group[1]]) with self.assertNoException(): details_group = blocks['details'] self.assertEqual('Details', details_group[0]) self.assertListEqual( ['cell', 'phone', 'fax'], [bfield.name for bfield, required in details_group[1]])
def test_basic_get_item(self): class TestForm(forms.Form): first_name = forms.CharField(label='First name', required=False) last_name = forms.CharField(label='Last name') phone = forms.CharField(label='Phone') cell = forms.CharField(label='Cell') fax = forms.CharField(label='Fax') fbm = FieldBlockManager( ('names', 'Names', ('first_name', 'last_name')), ('details', 'Details', ['cell', 'phone', 'fax']), ) form = TestForm() blocks = fbm.build(form) with self.assertNoException(): names_group = blocks['names'] self.assertIsInstance(names_group, tuple) self.assertEqual(2, len(names_group)) self.assertEqual('Names', names_group[0]) items = names_group[1] self.assertIsInstance(items, list) self.assertEqual(2, len(items)) # -- item1 = items[0] self.assertIsInstance(item1, tuple) self.assertEqual(2, len(item1)) self.assertIs(item1[1], False) bound_field1 = item1[0] self.assertIsInstance(bound_field1, BoundField) self.assertEqual('first_name', bound_field1.name) self.assertEqual('id_first_name', bound_field1.auto_id) # -- bfield2, required2 = items[1] self.assertEqual('last_name', bfield2.name) self.assertIs(required2, True) # -- with self.assertNoException(): details_group = blocks['details'] self.assertEqual('Details', details_group[0]) self.assertListEqual( ['cell', 'phone', 'fax'], # The order of the block info is used [bfield.name for bfield, required in details_group[1]]) # --- with self.assertRaises(KeyError): __ = blocks['names'] # Already pop
def test_new03(self): "Extend parent wildcard => error." fbm1 = FieldBlockManager(('names', 'Names', '*'), ) with self.assertRaises(ValueError) as cm: __ = fbm1.new( ('names', 'Names', ['cell']), ('details', 'Details', ('phone', 'fax')), ) self.assertEqual( 'You cannot extend a wildcard (see the form-block with category "names")', str(cm.exception))
def test_invalid_field01(self): class TestForm(forms.Form): last_name = forms.CharField(label='Last name') fbm = FieldBlockManager(('names', 'Names', ('invalid', 'last_name')), ) form = TestForm() with self.assertNoException(): blocks = fbm.build(form) with self.assertNoException(): group = blocks['names'] self.assertListEqual(['last_name'], [bfield.name for bfield, required in group[1]])
class CustomFormGroupForm(CremeModelForm): name = forms.CharField(label=_('Name'), max_length=100) cells = CustomFormCellsField(label=_('Fields')) blocks = FieldBlockManager( { 'id': 'name', 'label': 'Name', 'fields': ('name',), }, { 'id': 'cells', 'label': 'Fields', 'fields': ('cells',), }, ) class Meta: model = CustomFormConfigItem fields = () def __init__(self, descriptor, *args, **kwargs): super().__init__(*args, **kwargs) self.descriptor = descriptor registry = descriptor.build_cell_registry() class FinalCellExtraFieldsField(CFormCellExtraFieldsField): cell_class = registry[EntityCellCustomFormExtra.type_id] cells_f = self.fields['cells'] cells_f.field_classes = { *cells_f.field_classes, FinalCellExtraFieldsField, } cells_f.cell_registry = registry
class CampaignAddListForm(CremeForm): messaging_lists = MultiCreatorEntityField(label=_('Lists'), required=False, model=MessagingList) # error_messages = { # 'already_linked': _('Following lists are already related to this campaign: %(lists)s'), # } blocks = FieldBlockManager(('general', _('Messaging lists'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.campaign = entity self.fields['messaging_lists'].q_filter = ~Q( id__in=[*entity.lists.values_list('id', flat=True)], ) # # In fact duplicate is not a problem with django's m2m # def clean_lists(self): # messaging_lists = self.cleaned_data['messaging_lists'] # current_lists = frozenset(self.campaign.lists.values_list('pk', flat=True)) # duplicate = [mlist for mlist in messaging_lists if mlist.id in current_lists] # # if duplicate: # raise ValidationError( # self.error_messages['already_linked'], # params={'lists': ', '.join(mlist.name for mlist in duplicate)}, # code='already_linked', # ) # # return messaging_lists def save(self): add_mlist = self.campaign.lists.add for mlist in self.cleaned_data['messaging_lists']: add_mlist(mlist)
class MailingListAddRecipientsForm(CremeForm): recipients = MultiEmailField( label=_('Recipients'), help_text=_('Write a valid e-mail address per line.'), ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Recipients'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def save(self): ml = self.ml recipients = self.cleaned_data['recipients'] existing = frozenset( EmailRecipient.objects.filter( ml=ml, address__in=recipients).values_list('address', flat=True)) create = EmailRecipient.objects.create for address in recipients: if address not in existing: create(ml=ml, address=address)
class AddContactsFromFilterForm(_AddPersonsFromFilterForm): blocks = FieldBlockManager(('general', _('Contacts recipients'), '*')) person_model = Contact def get_persons_m2m(self): return self.ml.contacts
class AddOrganisationsFromFilterForm(_AddPersonsFromFilterForm): blocks = FieldBlockManager(('general', _('Organisations recipients'), '*')) person_model = Organisation def get_persons_m2m(self): return self.ml.organisations
class AddChildForm(CremeForm): child = CreatorEntityField(label=_('List'), model=MailingList) error_messages = { 'own_child': _("A list can't be its own child"), 'in_parents': _('List already in the parents'), 'in_children': _('List already in the children'), } blocks = FieldBlockManager(('general', _('Child mailing list'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def clean_child(self): child = self.cleaned_data['child'] ml = self.ml if ml.id == child.id: raise ValidationError(self.error_messages['own_child'], code='own_child') if ml.already_in_parents(child.id): raise ValidationError(self.error_messages['in_parents'], code='in_parents') if ml.already_in_children(child.id): raise ValidationError(self.error_messages['in_children'], code='in_children') return child def save(self): self.ml.children.add(self.cleaned_data['child'])
class UserRoleCredentialsGeneralStep(CredentialsGeneralStep): blocks = FieldBlockManager( ('general', _('First credentials: main information'), '*'), ( 'actions', _('First credentials: actions'), ['can_view', 'can_change', 'can_delete', 'can_link', 'can_unlink'], ), ) def __init__(self, role, *args, **kwargs): self.role = role super().__init__(*args, **kwargs) fields = self.fields fields['can_view'] = forms.CharField( label=fields['can_view'].label, required=False, widget=creme_widgets.Label, initial=_('Yes'), ) def clean_can_view(self): return True def _get_allowed_apps(self): return self.role.allowed_apps def save(self, commit=False, *args, **kwargs): self.instance.role = self.role return super().save(commit=commit, *args, **kwargs)
class MessagingListAddRecipientsForm(CremeForm): # TODO: see for phonelist widget recipients = PhoneListField( widget=Textarea, label=_('Recipients'), help_text=_('One phone number per line'), ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Recipients'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.messaging_list = entity def save(self): messaging_list = self.messaging_list recipients = self.cleaned_data['recipients'] existing = frozenset( Recipient.objects.filter( messaging_list=messaging_list, phone__in=recipients, ).values_list('phone', flat=True) ) create = Recipient.objects.create for number in recipients: if number not in existing: create(messaging_list=messaging_list, phone=number)
class RelationTypeCreateForm(CremeForm): subject_ctypes = _CTypesField() subject_properties = _PropertyTypesField(help_text=_('The subject must have all the selected properties.')) subject_predicate = CharField(label=_('Subject => object')) subject_is_copiable = BooleanField(label=_('Direct relationship is copiable'), initial=True, required=False, help_text=_('Are the relationships with this type copied ' 'when the subject entity is cloned?' ), ) subject_min_display = BooleanField(label=_("Display once on the subject's page"), required=False, help_text=_('Do not display in the «Relationships» block (detail-view of ' 'subject) when it is already displayed by another block.' ), ) object_predicate = CharField(label=_('Object => subject')) object_is_copiable = BooleanField(label=_('Symmetrical relationship is copiable'), initial=True, required=False, help_text=_('Are the relationships with this type copied ' 'when the object entity is cloned?' ), ) object_min_display = BooleanField(label=_("Display once on the subject's page"), required=False, help_text=_('Do not display in the «Relationships» block (detail-view of ' 'object) when it is already displayed by another block.' ), ) object_ctypes = _CTypesField() object_properties = _PropertyTypesField(help_text=_('The object must have all the selected properties.')) blocks = FieldBlockManager(('subject', _('Subject'), ('subject_ctypes', 'subject_properties')), ('predicate', _('Verb/Predicate'), ('subject_predicate', 'subject_is_copiable', 'subject_min_display', 'object_predicate', 'object_is_copiable', 'object_min_display', ) ), ('object', _('Object'), ('object_ctypes', 'object_properties')), ) def __init__(self, instance=None, *args, **kwargs): super().__init__(*args, **kwargs) def save(self, pk_subject='creme_config-subject_userrelationtype', pk_object='creme_config-object_userrelationtype', generate_pk=True, *args, **kwargs ): get_data = self.cleaned_data.get subject_ctypes = [ct.model_class() for ct in get_data('subject_ctypes')] object_ctypes = [ct.model_class() for ct in get_data('object_ctypes')] return RelationType.create((pk_subject, get_data('subject_predicate'), subject_ctypes, get_data('subject_properties')), (pk_object, get_data('object_predicate'), object_ctypes, get_data('object_properties')), is_custom=True, generate_pk=generate_pk, is_copiable=(get_data('subject_is_copiable'), get_data('object_is_copiable')), minimal_display=(get_data('subject_min_display'), get_data('object_min_display')), )
class AddContactsFromFilterForm(AddPersonsFromFilterForm): blocks = FieldBlockManager({ 'id': 'general', 'label': _('Contacts recipients'), 'fields': '*', }) person_model = Contact def get_persons_m2m(self): return self.messaging_list.contacts
class UserRoleCredentialsFilterStep(CredentialsFilterStep): blocks = FieldBlockManager( ('general', _('First credentials: filter'), ('name', 'use_or')), ('conditions', _('First credentials: conditions'), '*'), ) def __init__(self, role, *args, **kwargs): super().__init__(*args, **kwargs) self.role = role # NB: not currently used, but facilitate extending
def test_wildcard03(self): "Several wildcards => error." class TestForm(forms.Form): first_name = forms.CharField(label='First name') last_name = forms.CharField(label='Last name') phone = forms.CharField(label='Phone') cell = forms.CharField(label='Cell') fbm = FieldBlockManager( ('names', 'Names', '*'), ('details', 'Details', '*'), ) with self.assertRaises(ValueError) as cm: __ = fbm.build(TestForm()) self.assertEqual('Only one wildcard is allowed: {}'.format(TestForm), str(cm.exception))
class AddOrganisationsFromFilterForm(_AddPersonsFromFilterForm): blocks = FieldBlockManager({ 'id': 'general', 'label': _('Organisations recipients'), 'fields': '*', }) person_model = Organisation def get_persons_m2m(self): return self.ml.organisations
class MailingListAddCSVForm(CremeForm): recipients = FileField(label=_('Recipients'), help_text=_( 'A file containing one e-mail address per line ' '(eg:[email protected] without quotation marks).')) blocks = FieldBlockManager({ 'id': 'general', 'label': _('CSV file'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity @staticmethod def filter_mail_chunk(value): # result = smart_text(value.strip()) result = smart_str(value.strip()) try: validate_email(result) except ValidationError: result = None return result def save(self ): # TODO: factorise with MailingListAddRecipientsForm.save() ?? ml = self.ml create = EmailRecipient.objects.create filter_ = EmailRecipient.objects.filter uploaded_file = self.cleaned_data['recipients'] # TODO: genexpr def addresses(): for line in uploaded_file: address = self.filter_mail_chunk(line) if address: yield address for recipients in chunktools.iter_as_chunk(addresses(), 256): recipients = frozenset(recipients) existing = frozenset( filter_(ml=ml, address__in=recipients).values_list('address', flat=True)) for address in recipients: if address not in existing: create(ml=ml, address=address)
def test_wildcard02(self): "Wildcard in second group." class TestForm(forms.Form): first_name = forms.CharField(label='First name', required=False) last_name = forms.CharField(label='Last name') phone = forms.CharField(label='Phone') cell = forms.CharField(label='Cell') fax = forms.CharField(label='Fax') fbm = FieldBlockManager( ('names', 'Names', '*'), ('details', 'Details', ('phone', 'fax', 'cell')), ) blocks = fbm.build(TestForm()) self.assertListEqual( ['first_name', 'last_name'], [bfield.name for bfield, required in blocks['names'][1]]) self.assertListEqual( ['phone', 'fax', 'cell'], [bfield.name for bfield, required in blocks['details'][1]])
class _SegmentForm(_AuxForm): name = CharField(label=_('Name'), max_length=100) error_messages = { 'duplicated_name': _('A segment with this name already exists'), 'duplicated_property': _('A property with the name «%(name)s» already exists'), } blocks = FieldBlockManager({ 'id': 'general', 'label': _('General information'), 'fields': ['name', 'product', 'place', 'price', 'promotion'], }) class Meta: model = MarketSegmentDescription exclude = (*_AuxForm.Meta.exclude, 'segment') # TODO: factorise with market_segment.MarketSegmentForm def clean_name(self): name = self.cleaned_data['name'] ptype_text = MarketSegment.generate_property_text(name) instance = self.instance segments = MarketSegment.objects.filter(name=name) ptypes = CremePropertyType.objects.filter(text=ptype_text) if instance.pk: segment = instance.segment segments = segments.exclude(pk=segment.pk) ptypes = ptypes.exclude(pk=segment.property_type_id) if segments.exists(): raise ValidationError( self.error_messages['duplicated_name'], code='duplicated_name', ) if ptypes.exists(): raise ValidationError( self.error_messages['duplicated_property'], params={'name': ptype_text}, code='duplicated_property', ) return name
class EmailTemplateAddAttachment(CremeForm): attachments = MultiCreatorEntityField(label=_('Attachments'), required=False, model=Document) blocks = FieldBlockManager(('general', _('Attachments'), '*')) def __init__(self, entity, *args, **kwargs): # super(EmailTemplateAddAttachment, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs) self.template = entity def save(self): attachments = self.template.attachments for attachment in self.cleaned_data['attachments']: attachments.add(attachment)
class CampaignAddMLForm(CremeForm): mailing_lists = MultiCreatorEntityField(label=_('Lists'), required=False, model=get_mailinglist_model()) blocks = FieldBlockManager(('general', _('Mailing lists'), '*')) def __init__(self, entity, *args, **kwargs): # super(CampaignAddMLForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs) self.campaign = entity # self.fields['mailing_lists'].q_filter = {'~id__in': list(entity.mailing_lists.values_list('id', flat=True))} self.fields['mailing_lists'].q_filter = \ ~Q(id__in=list(entity.mailing_lists.values_list('id', flat=True))) def save(self): add_ml = self.campaign.mailing_lists.add for ml in self.cleaned_data['mailing_lists']: add_ml(ml)
class AddOrganisationsForm(CremeForm): # TODO: factorise recipients = MultiCreatorEntityField( label=_('Organisations'), required=False, model=Organisation, ) # other filter (name + email)?? blocks = FieldBlockManager(('general', _('Organisations recipients'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def save(self): organisations = self.ml.organisations # TODO: check if email if ok ???? for organisation in self.cleaned_data['recipients']: organisations.add(organisation)
class AddContactsForm(CremeForm): recipients = MultiCreatorEntityField( label=_('Contacts'), required=False, model=Contact, ) # other filter (name + email)?? blocks = FieldBlockManager(('general', _('Contacts recipients'), '*')) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.ml = entity def save(self): contacts = self.ml.contacts # TODO: check if email if ok ???? for contact in self.cleaned_data['recipients']: contacts.add(contact)
class UserRoleCredentialsStep(AddCredentialsForm): blocks = FieldBlockManager(('general', _('First credentials'), '*')) def __init__(self, allowed_app_names, *args, **kwargs): self.allowed_app_names = allowed_app_names # super(UserRoleCredentialsStep, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs) self.fields['can_view'] = CharField( label=_('Can view'), required=False, widget=Label, initial=_('Yes'), ) def _get_allowed_apps(self): return self.allowed_app_names def clean_can_view(self): return True
class BrickDetailviewLocationsAddForm(_BrickDetailviewLocationsForm): role = ModelChoiceField( label=_('Role'), queryset=UserRole.objects.none(), empty_label=None, required=False, ) # TODO: manage Meta.fields in '*' blocks = FieldBlockManager( ('general', _('Configuration'), ('role', 'hat', 'top', 'left', 'right', 'bottom'))) def __init__(self, *args, **kwargs): # super(BrickDetailviewLocationsAddForm, self).__init__(*args, **kwargs) super().__init__(*args, **kwargs) fields = self.fields role_f = fields['role'] used_role_ids = set( BrickDetailviewLocation.objects.filter( content_type=self.ct).exclude(role__isnull=True, superuser=False).values_list( 'role', flat=True)) try: used_role_ids.remove(None) except KeyError: role_f.empty_label = '*{}*'.format(ugettext( 'Superuser')) # NB: browser can ignore <em> tag in <option>... role_f.queryset = UserRole.objects.exclude(pk__in=used_role_ids) hat_f = fields.get('hat') if hat_f: hat_f.initial = hat_f.choices[0][0] def save(self, *args, **kwargs): self.role = role = self.cleaned_data['role'] self.superuser = (role is None) # super(BrickDetailviewLocationsAddForm, self).save(*args, **kwargs) super().save(*args, **kwargs)
class CampaignAddListForm(CremeForm): messaging_lists = MultiCreatorEntityField( label=_('Lists'), required=False, model=MessagingList, ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Messaging lists'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.campaign = entity self.fields['messaging_lists'].q_filter = ~Q( id__in=[*entity.lists.values_list('id', flat=True)], ) def save(self): add_mlist = self.campaign.lists.add for mlist in self.cleaned_data['messaging_lists']: add_mlist(mlist)
class AddContactsForm(CremeForm): # TODO: other filter (name + email) ? recipients = MultiCreatorEntityField( label=_('Contacts'), required=False, model=Contact, ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Contacts recipients'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.messaging_list = entity def save(self): contacts = self.messaging_list.contacts # TODO: check if email if ok ???? for contact in self.cleaned_data['recipients']: contacts.add(contact)
class EmailTemplateAddAttachment(CremeForm): attachments = MultiCreatorEntityField( label=_('Attachments'), required=False, model=get_document_model(), ) blocks = FieldBlockManager({ 'id': 'general', 'label': _('Attachments'), 'fields': '*', }) def __init__(self, entity, *args, **kwargs): super().__init__(*args, **kwargs) self.template = entity def save(self): add = self.template.attachments.add for attachment in self.cleaned_data['attachments']: add(attachment)