Source code for scipost.fields

__copyright__ = "Copyright © Stichting SciPost (SciPost Foundation)"
__license__ = "AGPL v3"

import json
import requests

from django import forms
from django.core.exceptions import ValidationError
from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.utils.encoding import force_text

from .widgets import ReCaptcha


[docs]class ChoiceArrayField(ArrayField): """ A field that allows us to store an array of choices. Uses Django 1.9's postgres ArrayField and a MultipleChoiceField for its formfield. """
[docs] def formfield(self, **kwargs): defaults = { "form_class": forms.MultipleChoiceField, "widget": forms.CheckboxSelectMultiple, "choices": self.base_field.choices, } defaults.update(kwargs) return super(ArrayField, self).formfield(**defaults)
[docs]class ReCaptchaField(forms.CharField): default_error_messages = { "captcha_invalid": "Incorrect, please try again.", "captcha_error": "Error verifying input, please try again.", } def __init__(self, use_ssl=None, attrs=None, *args, **kwargs): """ ReCaptchaField can accepts attributes which is a dictionary of attributes to be passed to the ReCaptcha widget class. The widget will loop over any options added and create the RecaptchaOptions JavaScript variables as specified in https://developers.google.com/recaptcha/docs/display#render_param """ if attrs is None: attrs = {} public_key = settings.RECAPTCHA_PUBLIC_KEY self.use_ssl = getattr(settings, "RECAPTCHA_USE_SSL", True) self.widget = ReCaptcha(public_key=public_key, attrs=attrs) self.required = True self.verify_url = "https://www.recaptcha.net/recaptcha/api/siteverify" super().__init__(*args, **kwargs)
[docs] def clean(self, values): super().clean(values[0]) recaptcha_response = force_text(values[0]) if not self.required: return data = { "secret": settings.RECAPTCHA_PRIVATE_KEY, "response": recaptcha_response, } r = requests.post( self.verify_url, data=data, headers={ "Content-type": "application/x-www-form-urlencoded", "User-agent": "reCAPTCHA Python", }, ) try: r.raise_for_status() response = r.json() catpcha_success = response.get("success", False) except (requests.exceptions.HTTPError, requests.exceptions.Timeout): raise ValidationError(self.error_messages["captcha_error"]) if not catpcha_success: raise ValidationError(self.error_messages["captcha_invalid"]) return values[0]
[docs]class UserModelChoiceField(forms.ModelChoiceField):
[docs] def label_from_instance(self, obj): return "{}, {} ({})".format(obj.last_name, obj.first_name, obj.email)