Beispiel #1
0
    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)
Beispiel #2
0
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'))
Beispiel #3
0
    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)
Beispiel #4
0
    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)
Beispiel #5
0
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
Beispiel #6
0
class SnapshotActionForm(ActionForm):
    tags = forms.ModelMultipleChoiceField(
        queryset=Tag.objects.all(),
        required=False,
        widget=AutocompleteSelectMultiple(
            AutocompleteTags(),
            AutocompleteTagsAdminStub(),
        ),
    )
Beispiel #7
0
 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
         }),
     }
Beispiel #8
0
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),
     }
Beispiel #11
0
 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'
             }),
     }
Beispiel #12
0
    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"])