def get_context_data(self, *, object_list=None, **kwargs): calendars_field = self.filterset.form.fields["calendars"] subtype_field = self.filterset.form.fields["subtype"] calendars_field.widget = AutocompleteSelectMultiple( Calendar._meta.get_field("events"), self.kwargs["model_admin"].admin_site) subtype_field.widget = AutocompleteSelectMultiple( EventSubtype._meta.get_field("events"), self.kwargs["model_admin"].admin_site, ) calendars_field.queryset = Calendar.objects.all() subtype_field.queryset = EventSubtype.objects.exclude( visibility=EventSubtype.VISIBILITY_NONE) return super().get_context_data( title="Résumé des événements", opts=self.kwargs["model_admin"].model._meta, add=False, change=False, is_popup=False, save_as=False, has_add_permission=False, has_change_permission=False, has_view_permission=False, has_editable_inline_admin_formsets=False, has_delete_permission=False, show_close=False, events_by_region=self.get_grouped_events(), **self.get_admin_helpers(self.filterset.form, self.filterset.base_filters), **kwargs)
class PerimeterCombineForm(forms.Form): add_perimeters = forms.ModelMultipleChoiceField( label=_('Perimeters to add'), queryset=Perimeter.objects.all(), widget=AutocompleteSelectMultiple(Perimeter._meta, admin.AdminSite()), help_text=_('Select a list of perimeters to combines')) rm_perimeters = forms.ModelMultipleChoiceField( label=_('Perimeters to substract'), required=False, queryset=Perimeter.objects.all(), widget=AutocompleteSelectMultiple(Perimeter._meta, admin.AdminSite()), help_text=_('Those perimeters will be substracted from the ' 'combined perimeters'))
def formfield_for_manytomany(self, db_field, request, **kwargs): if not db_field.remote_field.through._meta.auto_created: return None db = kwargs.get("using") autocomplete_fields = self.get_autocomplete_fields(request) if db_field.name in autocomplete_fields: kwargs['widget'] = AutocompleteSelectMultiple( db_field if django.VERSION >= (3, 2) else db_field.remote_field, self.admin_site, using=db) elif db_field.name in self.raw_id_fields: kwargs["widget"] = widgets.AdminManyToManyRawIdWidget( db_field.remote_field, self.admin_site, using=db) elif db_field.name in list(self.filter_vertical) + list( self.filter_horizontal): kwargs["widget"] = widgets.FilteredSelectMultiple() else: kwargs.setdefault("widget", forms.SelectMultiple) if "queryset" not in kwargs: queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs["queryset"] = queryset return db_field.formfield(**kwargs)
def __init__(self, request, params, model, model_admin): self.parameter_name = '{}__{}__in'.format(self.field_name, self.field_pk) super().__init__(request, params, model, model_admin) if self.rel_model: model = self.rel_model remote_field = model._meta.get_field(self.field_name).remote_field widget = AutocompleteSelectMultiple(remote_field, model_admin.admin_site) form_field = self.get_form_field() field = form_field( queryset=self.get_queryset_for_field(model, self.field_name), widget=widget, required=False, ) self._add_media(model_admin, widget) attrs = self.widget_attrs.copy() attrs['id'] = 'id-%s-dal-filter' % self.field_name if self.is_placeholder_title: # Upper case letter P as dirty hack for bypass django2 widget force placeholder value as empty string ("") attrs['data-Placeholder'] = self.title self.rendered_widget = field.widget.render(name=self.parameter_name, value=self.value(), attrs=attrs)
class SettlementForm(forms.ModelForm): shows = forms.ModelMultipleChoiceField(queryset=FinanceInfo.objects.all(), widget=AutocompleteSelectMultiple( fake_rel_field, admin.site), required=False) class Meta: model = Settlement fields = ("season", "year", "locked", "club_budget") def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.instance.pk: self.fields["shows"].initial = self.instance.financeinfo_set.all() self.fields[ "shows"].help_text = "Shows added here will appear below when this settlement is saved." else: self.fields["shows"].disabled = True self.fields[ "shows"].help_text = "Please save this settlement once before adding shows." def save(self, *args, **kwargs): instance = super().save(*args, **kwargs) if instance.pk: self.fields['shows'].initial.update(settlement=None) self.cleaned_data['shows'].update(settlement=instance) return instance
class SnapshotActionForm(ActionForm): tags = forms.ModelMultipleChoiceField( queryset=Tag.objects.all(), required=False, widget=AutocompleteSelectMultiple( AutocompleteTags(), AutocompleteTagsAdminStub(), ), )
class Meta: model = Order exclude = [ "order_budget_total", "order_budget_labor", "order_budget_material", "order_customer_PO", "order_invoice_number" ] widgets = { "order_project": AutocompleteSelect(Order.order_project.field.remote_field, admin.site, attrs={'style': 'width: 500px'}), "order_name": forms.Textarea(attrs={ 'rows': 1, 'cols': 80 }), "order_description": forms.Textarea(attrs={ 'rows': 4, 'cols': 150 }), "order_facility": AutocompleteSelectMultiple(Order.order_facility.field.remote_field, admin.site, attrs={'style': 'width: 500px'}), "order_model_number": forms.Textarea(attrs={ 'rows': 1, 'cols': 80 }), "order_serial_number": forms.Textarea(attrs={ 'rows': 1, 'cols': 80 }), "order_customer_PO": forms.Textarea(attrs={ 'rows': 1, 'cols': 80 }), "order_invoice_number": forms.Textarea(attrs={ 'rows': 1, 'cols': 80 }), "order_internal_notes": forms.Textarea(attrs={ 'rows': 4, 'cols': 150 }), "order_client_notes": forms.Textarea(attrs={ 'rows': 4, 'cols': 150 }), }
class TrainingFormWithCSV(forms.ModelForm): attended_students = forms.ModelMultipleChoiceField( required=False, queryset=Student.objects.all(), widget=AutocompleteSelectMultiple( rel=AutocompleteStudent, admin_site=site, attrs={'data-width': '50%'} ) ) hours = forms.DecimalField(required=False, max_digits=5, decimal_places=2, min_value=0.01, max_value=999.99, initial=1) xlsx = forms.FileField(required=False, widget=forms.FileInput(attrs={'accept': '.xlsx'})) def clean(self): cleaned_data = super().clean() attendances = [] cleaned_data['attendances'] = attendances file = cleaned_data.get("xlsx", None) if file is None: return cleaned_data data = file.read() emails = [] hours = {} ws = load_workbook(filename=io.BytesIO(data), read_only=True).active for i, row in enumerate(ws): if i == 0: if len(row) != 2: raise forms.ValidationError(f"Expected 2 columns header, got {len(row)} columns") header = [row[0].value, row[1].value] if header != ["email", "hours"]: raise forms.ValidationError(f"Missing header ['email', 'hours'], got: {header}") continue if len(row) != 2: raise forms.ValidationError(f"Expected 2 columns in each row, got {len(row)} columns in row {i + 1}") email, student_hours = row[0].value, row[1].value emails.append(email) try: hours[email] = round(float(student_hours), 2) assert 0 <= hours[email] < 1000 # TODO: hardcoded constant except (AssertionError, ValueError, TypeError): raise forms.ValidationError( f"Got invalid hours value \"{student_hours}\" for email {email}, expected value in range [0,999.99]" ) students = Student.objects.select_related('user').filter(user__email__in=emails) if len(students) != len(emails): missing = set(emails) - set(map(lambda student: student.user.email, students)) raise forms.ValidationError( f"File contains {len(emails)} records. Only {len(students)} emails matched. " f"Missing students emails are: {', '.join(missing)}" ) for student in students: attendances.append((student, hours[student.user.email]))
class Meta: model = Case fields = [ 'client_name', 'client_phone', 'client_email', 'client_SID', 'referrer', 'tags' ] widgets = { 'referrer': AutocompleteSelect(rel=Tag.cases.rel, admin_site=admin_site), 'tags': AutocompleteSelectMultiple(rel=Case.tags.rel, admin_site=admin_site), }
class Meta: model = Case fields = [ 'client_name', 'client_phone', 'client_email', 'client_SID', 'client_pronouns', 'week_food', 'semester_food', 'week_housing', 'dependent', 'using_resources', 'screening_asked', 'case_question', 'referrer', 'tags' ] widgets = { 'referrer': AutocompleteSelect(rel=Tag.cases.rel, admin_site=admin_site), 'tags': AutocompleteSelectMultiple(rel=Case.tags.rel, admin_site=admin_site), }
class Meta: widgets = { 'types_of_sanctions': AutocompleteSelectMultiple( model._meta.get_field('types_of_sanctions').remote_field, admin.site, attrs={ 'data-dropdown-auto-width': 'true', 'data-width': '624px', }), 'passports': TextInput( attrs={ 'style': 'max-width: 610px; width: 100%;', 'placeholder': 'лњла135468,123456789,987654321' }), }
def formfield_for_manytomany_modified(self, db_field, request, **kwargs): """ Get a form Field for a ManyToManyField. """ # If it uses an intermediary model that isn't auto created, don't show # a field in admin. if not db_field.remote_field.through._meta.auto_created: # pylint: disable=W0212 return None db = kwargs.get('using') # pylint: disable=C0103 autocomplete_fields = self.get_autocomplete_fields(request) # just added this line... if 'widget' not in kwargs: if db_field.name in autocomplete_fields: kwargs['widget'] = AutocompleteSelectMultiple( db_field.remote_field, self.admin_site, using=db) elif db_field.name in self.raw_id_fields: kwargs['widget'] = widgets.ManyToManyRawIdWidget( db_field.remote_field, self.admin_site, using=db) elif db_field.name in [ *self.filter_vertical, *self.filter_horizontal ]: kwargs['widget'] = widgets.FilteredSelectMultiple( db_field.verbose_name, db_field.name in self.filter_vertical) if 'queryset' not in kwargs: queryset = self.get_field_queryset(db, db_field, request) if queryset is not None: kwargs['queryset'] = queryset form_field = db_field.formfield(**kwargs) if isinstance(form_field.widget, SelectMultiple) and not isinstance( form_field.widget, (CheckboxSelectMultiple, AutocompleteSelectMultiple)): msg = _( 'Hold down "Control", or "Command" on a Mac, to select more than one.' ) help_text = form_field.help_text form_field.help_text = format_lazy('{0} {1}', help_text, msg) if help_text else msg return form_field
class Meta: model = Case fields = [ 'divisions', 'client_name', 'client_email', 'client_phone', 'client_SID', 'client_pronouns', 'week_food', 'semester_food', 'week_housing', 'dependent', 'using_resources', 'screening_asked', 'case_question', 'open_date', 'incident_description', 'intake_caseworker', 'referrer', 'tags' ] widgets = { 'client_phone': PhoneNumberInternationalFallbackWidget(), 'incident_description': TinyMCE(mce_attrs=TINY_MCE_SETUP), 'intake_caseworker': forms.HiddenInput(), 'referrer': AutocompleteSelect(rel=Tag.cases.rel, admin_site=admin_site), 'tags': AutocompleteSelectMultiple(rel=Case.tags.rel, admin_site=admin_site), }
class UserNotificationForm(forms.Form): """Create a new message to send to users in the vicinity of given proposals and/or addresses. """ addresses = forms.CharField(widget=forms.Textarea(attrs={"rows": 4}), help_text=("Enter one address per line"), required=False) proposals = forms.ModelMultipleChoiceField( queryset=Proposal.objects.all(), required=False, widget=AutocompleteSelectMultiple( RelModel(Proposal), cornerwise_admin, )) title = forms.CharField(max_length=100, required=False, widget=forms.TextInput(attrs={"size": 40})) greeting = forms.CharField( initial=("You are receiving this message from the " "planning staff in %region% because you " "have subscribed to receive emails about " "development in your area. The affected " "addresses in your area are:\n%proposals%\n" "%addresses%"), widget=forms.Textarea(attrs={"rows": 4}), help_text=("Use %region% to insert the region name, " "%proposals% to insert a list of proposal " "addresses and case numbers and %addresses% " "to insert a list of addresses relevant to " "the email recipient")) message = forms.CharField(widget=TinyMCE( mce_attrs={ "width": 400, "height": 250, "content_css": urljoin(settings.STATIC_URL, "css/tinymce.css") })) notification_radius = DistanceField( min_value=D(ft=100), max_value=D(mi=20), initial=D(ft=300), label="Notify subscribers within distance") confirm = forms.CharField(initial="0", widget=forms.HiddenInput()) region = forms.ChoiceField(choices=(("Somerville, MA", "Somerville, MA"), ), initial=settings.GEO_REGION) notification_id = forms.CharField(required=False, widget=forms.HiddenInput()) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.data = self.data.copy() self.fields["notification_id"].initial = str(uuid4()) @property def confirmed(self): return self.cleaned_data["confirm"] == "1" def mark_confirm(self): self.data["confirm"] = "1" def geocode_addresses(self, addresses): addresses = list(filter(None, map(str.strip, addresses))) geocoded = geocode_tuples(addresses, region=self.cleaned_data["region"]) return split_list(tuple.__instancecheck__, geocoded) def find_matching_proposals(self, region): proposals = self.cleaned_data["proposals"] return split_list(lambda p: p.region_name == region, proposals) def clean(self): cleaned = super().clean() # Check that the Proposals are within the selected region region = cleaned["region"] if region: good_props, bad_props = self.find_matching_proposals(region) if bad_props: self.data.setlist("proposals", [p.id for p in good_props]) raise ValidationError( (f"{len(bad_props)} proposal(s) are outside {region}.")) addresses = cleaned["addresses"].split("\n") good_addrs, bad_addrs = self.geocode_addresses(addresses) # Remove bad addresses, so that they don't show up when the form is # redisplayed. self.data["addresses"] = "\n".join(addr for addr, _pt, _fmt in good_addrs) if bad_addrs: raise ValidationError(("Not all addresses were valid: " "%(addresses)s"), params={"addresses": ";".join(bad_addrs)}) if not (good_addrs or cleaned["proposals"]): raise ValidationError( "Please provide at least one address or proposal") cleaned["coded_addresses"] = good_addrs return cleaned def clean_message(self): message = self.cleaned_data["message"] return bleach.clean( message, tags=bleach.ALLOWED_TAGS + ["p", "pre", "span", "h1", "h2", "h3", "h4", "h5", "h6"], attributes=["title", "href", "style"], styles=["text-decoration", "text-align"]) def clean_notification_id(self): nid = self.cleaned_data["notification_id"] if nid and re.match(r"[0-9a-f]{32}$", nid, re.I): return nid else: return str(uuid4()) def save_data(self): notification_id = self.cleaned_data["notification_id"] red.set_expire_key(notification_key(notification_id), { "cleaned": self.cleaned_data, "data": self.data }, ttl=3600) return notification_id @staticmethod def _get_subscribers(d): return get_subscribers(d["coded_addresses"], d["proposals"], d["region"], d["notification_radius"]) def get_subscribers(self): return self._get_subscribers(self.cleaned_data) def example_greeting(self): return replace_boilerplate( self.cleaned_data["greeting"], chain(self.cleaned_data["proposals"], self.cleaned_data["coded_addresses"]), self.cleaned_data["region"])