django.utils.encoding force_str Example Code

force_str is a callable within the django.utils.encoding module of the Django project.

Example 1 from django-allauth

django-allauth (project website) is a Django library for easily adding local and social authentication flows to Django projects. It is open source under the MIT License.

django-allauth / allauth / utils.py

# utils.py
import base64
import importlib
import json
import random
import re
import string
import unicodedata
from collections import OrderedDict
from urllib.parse import urlsplit

import django
from django.contrib.auth import get_user_model
from django.contrib.sites.models import Site
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.core.serializers.json import DjangoJSONEncoder
from django.core.validators import ValidationError, validate_email
from django.db.models import FileField
from django.db.models.fields import (
    BinaryField,
    DateField,
    DateTimeField,
    EmailField,
    TimeField,
)
from django.utils import dateparse
from django.utils.encoding import force_bytes, force_str


MAX_USERNAME_SUFFIX_LENGTH = 7
USERNAME_SUFFIX_CHARS = (
    [string.digits] * 4 +
    [string.ascii_letters] * (MAX_USERNAME_SUFFIX_LENGTH - 4))


def _generate_unique_username_base(txts, regex=None):
    from .account.adapter import get_adapter
    adapter = get_adapter()
    username = None
    regex = regex or r'[^\w\s@+.-]'
    for txt in txts:
        if not txt:
            continue
        username = unicodedata.normalize('NFKD', force_str(txt))
        username = username.encode('ascii', 'ignore').decode('ascii')
        username = force_str(re.sub(regex, '', username).lower())
        username = username.split('@')[0]
        username = username.strip()
        username = re.sub(r'\s+', '_', username)
        try:
            username = adapter.clean_username(username, shallow=True)
            break
        except ValidationError:
            pass
    return username or 'user'


def get_username_max_length():
    from .account.app_settings import USER_MODEL_USERNAME_FIELD
    if USER_MODEL_USERNAME_FIELD is not None:
        User = get_user_model()
        max_length = User._meta.get_field(USER_MODEL_USERNAME_FIELD).max_length
    else:
        max_length = 0
    return max_length


def generate_username_candidate(basename, suffix_length):
    max_length = get_username_max_length()
    suffix = ''.join(


## ... source file abbreviated to get to force_str examples ...


    assert isinstance(path, str)
    pkg, attr = path.rsplit('.', 1)
    ret = getattr(importlib.import_module(pkg), attr)
    return ret


def import_callable(path_or_callable):
    if not hasattr(path_or_callable, '__call__'):
        ret = import_attribute(path_or_callable)
    else:
        ret = path_or_callable
    return ret


SERIALIZED_DB_FIELD_PREFIX = '_db_'


def serialize_instance(instance):
    data = {}
    for k, v in instance.__dict__.items():
        if k.startswith('_') or callable(v):
            continue
        try:
            field = instance._meta.get_field(k)
            if isinstance(field, BinaryField):
                v = force_str(base64.b64encode(v))
            elif isinstance(field, FileField):
                if v and not isinstance(v, str):
                    v = v.name
            try:
                json.dumps(v, cls=DjangoJSONEncoder)
            except TypeError:
                v = field.get_prep_value(v)
                k = SERIALIZED_DB_FIELD_PREFIX + k
        except FieldDoesNotExist:
            pass
        data[k] = v
    return json.loads(json.dumps(data, cls=DjangoJSONEncoder))


def deserialize_instance(model, data):
    ret = model()
    for k, v in data.items():
        is_db_value = False
        if k.startswith(SERIALIZED_DB_FIELD_PREFIX):
            k = k[len(SERIALIZED_DB_FIELD_PREFIX):]
            is_db_value = True
        if v is not None:
            try:
                f = model._meta.get_field(k)


## ... source file continues with no further force_str examples...

Example 2 from django-extensions

django-extensions (project documentation and PyPI page) is a Django project that adds a bunch of additional useful commands to the manage.py interface. This GoDjango video provides a quick overview of what you get when you install it into your Python environment.

The django-extensions project is open sourced under the MIT license.

django-extensions / django_extensions / validators.py

# validators.py
import unicodedata
import binascii


from django.core.exceptions import ValidationError
from django.utils.deconstruct import deconstructible
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _


@deconstructible
class NoControlCharactersValidator:
    message = _("Control Characters like new lines or tabs are not allowed.")
    code = "no_control_characters"
    whitelist = None

    def __init__(self, message=None, code=None, whitelist=None):
        if message:
            self.message = message
        if code:
            self.code = code
        if whitelist:
            self.whitelist = whitelist

    def __call__(self, value):
        value = force_str(value)
        whitelist = self.whitelist
        category = unicodedata.category
        for character in value:
            if whitelist and character in whitelist:
                continue
            if category(character)[0] == "C":
                params = {'value': value, 'whitelist': whitelist}
                raise ValidationError(self.message, code=self.code, params=params)

    def __eq__(self, other):
        return (
            isinstance(other, NoControlCharactersValidator) and
            (self.whitelist == other.whitelist) and
            (self.message == other.message) and
            (self.code == other.code)
        )


@deconstructible
class NoWhitespaceValidator:
    message = _("Leading and Trailing whitespaces are not allowed.")
    code = "no_whitespace"

    def __init__(self, message=None, code=None, whitelist=None):
        if message:
            self.message = message
        if code:
            self.code = code

    def __call__(self, value):
        value = force_str(value)
        if value != value.strip():
            params = {'value': value}
            raise ValidationError(self.message, code=self.code, params=params)

    def __eq__(self, other):
        return (
            isinstance(other, NoWhitespaceValidator) and
            (self.message == other.message) and
            (self.code == other.code)
        )


@deconstructible
class HexValidator:
    messages = {
        'invalid': _("Only a hex string is allowed."),
        'length': _("Invalid length. Must be %(length)d characters."),
        'min_length': _("Ensure that there are more than %(min)s characters."),
        'max_length': _("Ensure that there are no more than %(max)s characters."),
    }
    code = "hex_only"

    def __init__(self, length=None, min_length=None, max_length=None, message=None, code=None):
        self.length = length
        self.min_length = min_length
        self.max_length = max_length
        if message:
            self.message = message
        if code:
            self.code = code

    def __call__(self, value):
        value = force_str(value)
        if self.length and len(value) != self.length:
            raise ValidationError(self.messages['length'], code='hex_only_length', params={'length': self.length})
        if self.min_length and len(value) < self.min_length:
            raise ValidationError(self.messages['min_length'], code='hex_only_min_length', params={'min': self.min_length})
        if self.max_length and len(value) < self.max_length:
            raise ValidationError(self.messages['max_length'], code='hex_only_max_length', params={'max': self.max_length})

        try:
            binascii.unhexlify(value)
        except (TypeError, binascii.Error):
            raise ValidationError(self.messages['invalid'], code='hex_only')

    def __eq__(self, other):
        return (
            isinstance(other, HexValidator) and
            (self.message == other.message) and
            (self.code == other.code)
        )



## ... source file continues with no further force_str examples...

Example 3 from django-filter

django-filter (project documentation and PyPI page) makes it easier to filter down querysets from the Django ORM by providing common bits of boilerplate code. django-filter is provided as open source.

django-filter / django_filters / fields.py

# fields.py
from collections import namedtuple
from datetime import datetime, time

from django import forms
from django.utils.dateparse import parse_datetime
from django.utils.encoding import force_str
from django.utils.translation import gettext_lazy as _

from .conf import settings
from .constants import EMPTY_VALUES
from .utils import handle_timezone
from .widgets import (
    BaseCSVWidget,
    CSVWidget,
    DateRangeWidget,
    LookupChoiceWidget,
    RangeWidget
)


class RangeField(forms.MultiValueField):
    widget = RangeWidget

    def __init__(self, fields=None, *args, **kwargs):
        if fields is None:
            fields = (
                forms.DecimalField(),
                forms.DecimalField())
        super().__init__(fields, *args, **kwargs)



## ... source file abbreviated to get to force_str examples ...


        empty_label = kwargs.pop('empty_label', settings.EMPTY_CHOICE_LABEL)
        fields = (field, ChoiceField(choices=lookup_choices, empty_label=empty_label))
        widget = LookupChoiceWidget(widgets=[f.widget for f in fields])
        kwargs['widget'] = widget
        kwargs['help_text'] = field.help_text
        super().__init__(fields, *args, **kwargs)

    def compress(self, data_list):
        if len(data_list) == 2:
            value, lookup_expr = data_list
            if value not in EMPTY_VALUES:
                if lookup_expr not in EMPTY_VALUES:
                    return Lookup(value=value, lookup_expr=lookup_expr)
                else:
                    raise forms.ValidationError(
                        self.error_messages['lookup_required'],
                        code='lookup_required')
        return None


class IsoDateTimeField(forms.DateTimeField):
    ISO_8601 = 'iso-8601'
    input_formats = [ISO_8601]

    def strptime(self, value, format):
        value = force_str(value)

        if format == self.ISO_8601:
            parsed = parse_datetime(value)
            if parsed is None:  # Continue with other formats if doesn't match
                raise ValueError
            return handle_timezone(parsed)
        return super().strptime(value, format)


class BaseCSVField(forms.Field):
    base_widget_class = BaseCSVWidget

    def __init__(self, *args, **kwargs):
        widget = kwargs.get('widget') or self.widget
        kwargs['widget'] = self._get_widget_class(widget)

        super().__init__(*args, **kwargs)

    def _get_widget_class(self, widget):
        if isinstance(widget, BaseCSVWidget) or (
                isinstance(widget, type) and
                issubclass(widget, BaseCSVWidget)):
            return widget



## ... source file continues with no further force_str examples...

Example 4 from django-floppyforms

django-floppyforms (project documentation and PyPI page) is a Django code library for better control over rendering HTML forms in your templates.

The django-floppyforms code is provided as open source and maintained by the collaborative developer community group Jazzband.

django-floppyforms / floppyforms / widgets.py

# widgets.py
import datetime
import re
from itertools import chain

import django
from django import forms
from django.conf import settings
from django.forms.widgets import FILE_INPUT_CONTRADICTION
from django.template import loader
from django.utils import datetime_safe, formats
from django.utils.dates import MONTHS
from django.utils.encoding import force_str
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _

from .compat import MULTIVALUE_DICT_TYPES, flatten_contexts


from django.forms.utils import to_current_timezone


RE_DATE = re.compile(r'(\d{4})-(\d\d?)-(\d\d?)$')


__all__ = (
    'TextInput', 'PasswordInput', 'HiddenInput', 'ClearableFileInput',
    'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea',
    'CheckboxInput', 'Select', 'NullBooleanSelect', 'SelectMultiple',
    'RadioSelect', 'CheckboxSelectMultiple', 'SearchInput', 'RangeInput',
    'ColorInput', 'EmailInput', 'URLInput', 'PhoneNumberInput', 'NumberInput',
    'IPAddressInput', 'MultiWidget', 'Widget', 'SplitDateTimeWidget',
    'SplitHiddenDateTimeWidget', 'MultipleHiddenInput', 'SelectDateWidget',
    'SlugInput',
)



## ... source file abbreviated to get to force_str examples ...


        def format_value(self, value):
            return self._format_value(value)


class Input(Widget):
    template_name = 'floppyforms/input.html'
    input_type = None
    datalist = None

    def __init__(self, *args, **kwargs):
        datalist = kwargs.pop('datalist', None)
        if datalist is not None:
            self.datalist = datalist
        template_name = kwargs.pop('template_name', None)
        if template_name is not None:
            self.template_name = template_name
        super(Input, self).__init__(*args, **kwargs)
        self.context_instance = None

    def get_context_data(self):
        return {}

    def format_value(self, value):
        if self.is_localized:
            value = formats.localize_input(value)
        return force_str(value)

    def get_context(self, name, value, attrs=None):
        context = {
            'widget': self,
            'type': self.input_type,
            'name': name,
            'hidden': self.is_hidden,
            'required': self.is_required,
            'True': True,
        }

        if self.is_hidden:
            context['hidden'] = True

        if value is None:
            value = ''

        if value != '':
            context['value'] = self.format_value(value)

        context.update(self.get_context_data())
        context['attrs'] = self.build_attrs(attrs)

        for key, attr in context['attrs'].items():


## ... source file abbreviated to get to force_str examples ...




class HiddenInput(Input):
    template_name = 'floppyforms/hidden.html'
    input_type = 'hidden'


class MultipleHiddenInput(HiddenInput):
    def __init__(self, attrs=None, choices=()):
        super(MultipleHiddenInput, self).__init__(attrs)
        self.choices = choices

    def render(self, name, value, attrs=None, choices=(), renderer=None):
        if value is None:
            value = []

        final_attrs = self.build_attrs(attrs)
        id_ = final_attrs.get('id', None)
        inputs = []
        for i, v in enumerate(value):
            input_attrs = final_attrs.copy()
            if id_:
                input_attrs['id'] = '%s_%s' % (id_, i)
            input_ = HiddenInput()
            input_.is_required = self.is_required
            inputs.append(input_.render(name, force_str(v), input_attrs, renderer=renderer))
        return mark_safe("\n".join(inputs))

    def value_from_datadict(self, data, files, name):
        if isinstance(data, MULTIVALUE_DICT_TYPES):
            return data.getlist(name)
        return data.get(name, None)


class SlugInput(TextInput):
    template_name = 'floppyforms/slug.html'

    def get_context(self, name, value, attrs):
        context = super(SlugInput, self).get_context(name, value, attrs)
        context['attrs']['pattern'] = r"[-\w]+"
        return context


class IPAddressInput(TextInput):
    template_name = 'floppyforms/ipaddress.html'

    ip_pattern = (r"(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25"
                  r"[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}")

    def get_context(self, name, value, attrs):


## ... source file abbreviated to get to force_str examples ...




def boolean_check(v):
    return not (v is False or v is None or v == '')


class CheckboxInput(Input, forms.CheckboxInput):
    template_name = 'floppyforms/checkbox.html'
    input_type = 'checkbox'

    def __init__(self, attrs=None, check_test=None):
        super(CheckboxInput, self).__init__(attrs)
        self.check_test = boolean_check if check_test is None else check_test

    def get_context(self, name, value, attrs):
        result = self.check_test(value)
        context = super(CheckboxInput, self).get_context(name, value, attrs)
        if result:
            context['attrs']['checked'] = True
        return context

    def format_value(self, value):
        if value in ('', True, False, None):
            value = None
        else:
            value = force_str(value)
        return value

    def value_from_datadict(self, data, files, name):
        return forms.CheckboxInput.value_from_datadict(self, data, files, name)

    if django.VERSION < (1, 6):
        def _has_changed(self, initial, data):
            if initial == 'False':
                initial = False
            return bool(initial) != bool(data)


class Select(Input):
    allow_multiple_selected = False
    template_name = 'floppyforms/select.html'

    def __init__(self, attrs=None, choices=()):
        super(Select, self).__init__(attrs)
        self.choices = list(choices)

    def get_context(self, name, value, attrs=None, choices=()):
        if not hasattr(value, '__iter__') or isinstance(value,
                                                        str):
            value = [value]
        context = super(Select, self).get_context(name, value, attrs)

        if self.allow_multiple_selected:
            context['attrs']['multiple'] = "multiple"

        groups = []
        for option_value, option_label in chain(self.choices, choices):
            if isinstance(option_label, (list, tuple)):
                group = []
                for val, lab in option_label:
                    group.append((force_str(val), lab))
                groups.append((option_value, group))
            else:
                option_value = force_str(option_value)
                if groups and groups[-1][0] is None:
                    groups[-1][1].append((option_value, option_label))
                else:
                    groups.append((None, [(option_value, option_label)]))
        context["optgroups"] = groups
        return context

    def format_value(self, value):
        if len(value) == 1 and value[0] is None:
            return []
        return set(force_str(v) for v in value)


class NullBooleanSelect(Select):
    def __init__(self, attrs=None):
        choices = (('1', _('Unknown')),
                   ('2', _('Yes')),
                   ('3', _('No')))
        super(NullBooleanSelect, self).__init__(attrs, choices)

    def format_value(self, value):
        value = value[0]
        try:
            value = {True: '2', False: '3', '2': '2', '3': '3'}[value]


## ... source file abbreviated to get to force_str examples ...


    template_name = 'floppyforms/radio.html'


class CheckboxSelectMultiple(SelectMultiple):
    template_name = 'floppyforms/checkbox_select.html'


class MultiWidget(forms.MultiWidget):
    @property
    def is_hidden(self):
        return all(w.is_hidden for w in self.widgets)

    def build_attrs(self, base_attrs, extra_attrs=None, **kwargs):
        attrs = dict(self.attrs, **kwargs)
        attrs.update(base_attrs)
        if extra_attrs:
            attrs.update(extra_attrs)
        return attrs

    if django.VERSION < (1, 11):
        def format_value(self, value):
            if value == '' or value is None:
                return None
            if self.is_localized:
                return formats.localize_input(value)
            return force_str(value)

        def get_context(self, name, value, attrs):
            context = {}
            context['widget'] = {
                'name': name,
                'is_hidden': self.is_hidden,
                'required': self.is_required,
                'value': self.format_value(value),
                'attrs': self.build_attrs(self.attrs, attrs),
                'template_name': self.template_name,
            }
            if self.is_localized:
                for widget in self.widgets:
                    widget.is_localized = self.is_localized
            if not isinstance(value, list):
                value = self.decompress(value)

            final_attrs = context['widget']['attrs']
            input_type = final_attrs.pop('type', None)
            id_ = final_attrs.get('id')
            subwidgets = []
            for i, widget in enumerate(self.widgets):
                if input_type is not None:
                    widget.input_type = input_type


## ... source file continues with no further force_str examples...

Example 5 from django-guardian

django-guardian (project documentation and PyPI page) provides per-object permissions in Django projects by enhancing the existing authentication backend. The project's code is open source under the MIT license.

django-guardian / guardian / core.py

# core.py
from itertools import chain

from django.contrib.auth import get_user_model
from django.contrib.auth.models import Permission
from django.db.models.query import QuerySet
from django.utils.encoding import force_str

from guardian.conf import settings as guardian_settings
from guardian.ctypes import get_content_type
from guardian.utils import get_group_obj_perms_model, get_identity, get_user_obj_perms_model


def _get_pks_model_and_ctype(objects):

    if isinstance(objects, QuerySet):
        model = objects.model
        pks = [force_str(pk) for pk in objects.values_list('pk', flat=True)]
        ctype = get_content_type(model)
    else:
        pks = []
        for idx, obj in enumerate(objects):
            if not idx:
                model = type(obj)
                ctype = get_content_type(model)
            pks.append(force_str(obj.pk))

    return pks, model, ctype


class ObjectPermissionChecker:


## ... source file abbreviated to get to force_str examples ...


            return []

        if guardian_settings.AUTO_PREFETCH:
            self._prefetch_cache()

        ctype = get_content_type(obj)
        key = self.get_local_cache_key(obj)
        if key not in self._obj_perms_cache:
            if guardian_settings.AUTO_PREFETCH:
                return []
            if self.user and self.user.is_superuser:
                perms = list(chain(*Permission.objects
                                   .filter(content_type=ctype)
                                   .values_list("codename")))
            elif self.user:
                user_perms = self.get_user_perms(obj)
                group_perms = self.get_group_perms(obj)
                perms = list(set(chain(user_perms, group_perms)))
            else:
                perms = list(set(self.get_group_perms(obj)))
            self._obj_perms_cache[key] = perms
        return self._obj_perms_cache[key]

    def get_local_cache_key(self, obj):
        ctype = get_content_type(obj)
        return (ctype.id, force_str(obj.pk))

    def prefetch_perms(self, objects):
        if self.user and not self.user.is_active:
            return []

        User = get_user_model()
        pks, model, ctype = _get_pks_model_and_ctype(objects)

        if self.user and self.user.is_superuser:
            perms = list(chain(
                *Permission.objects
                .filter(content_type=ctype)
                .values_list("codename")))

            for pk in pks:
                key = (ctype.id, force_str(pk))
                self._obj_perms_cache[key] = perms

            return True

        group_model = get_group_obj_perms_model(model)

        if self.user:
            fieldname = 'group__{}'.format(
                User.groups.field.related_query_name(),
            )
            group_filters = {fieldname: self.user}
        else:
            group_filters = {'group': self.group}

        if group_model.objects.is_generic():
            group_filters.update({
                'content_type': ctype,
                'object_pk__in': pks,
            })
        else:
            group_filters.update({
                'content_object_id__in': pks
            })



## ... source file abbreviated to get to force_str examples ...


                    'content_type': ctype,
                    'object_pk__in': pks
                })
            else:
                user_filters.update({
                    'content_object_id__in': pks
                })

            user_perms_qs = model.objects.filter(**user_filters).select_related('permission')
            group_perms_qs = group_model.objects.filter(**group_filters).select_related('permission')
            perms = chain(user_perms_qs, group_perms_qs)
        else:
            perms = chain(
                *(group_model.objects.filter(**group_filters).select_related('permission'),)
            )

        for obj in objects:
            key = self.get_local_cache_key(obj)
            if key not in self._obj_perms_cache:
                self._obj_perms_cache[key] = []

        for perm in perms:
            if type(perm).objects.is_generic():
                key = (ctype.id, perm.object_pk)
            else:
                key = (ctype.id, force_str(perm.content_object_id))

            self._obj_perms_cache[key].append(perm.permission.codename)

        return True

    @staticmethod
    def _init_obj_prefetch_cache(obj, *querysets):
        cache = {}
        for qs in querysets:
            perms = qs.select_related('permission__codename').values_list('content_type_id', 'object_pk',
                                                                          'permission__codename')
            for p in perms:
                if p[:2] not in cache:
                    cache[p[:2]] = []
                cache[p[:2]] += [p[2], ]
        obj._guardian_perms_cache = cache
        return obj, cache

    def _prefetch_cache(self):
        from guardian.utils import get_user_obj_perms_model, get_group_obj_perms_model
        UserObjectPermission = get_user_obj_perms_model()
        GroupObjectPermission = get_group_obj_perms_model()
        if self.user:
            obj = self.user


## ... source file continues with no further force_str examples...

Example 6 from django-haystack

django-haystack (project website and PyPI page) is a search abstraction layer that separates the Python search code in a Django web application from the search engine implementation that it runs on, such as Apache Solr, Elasticsearch or Whoosh.

The django-haystack project is open source under the BSD license.

django-haystack / haystack / models.py

# models.py

from django.core.exceptions import ObjectDoesNotExist
from django.utils.encoding import force_str
from django.utils.text import capfirst

from haystack.constants import DEFAULT_ALIAS
from haystack.exceptions import NotHandled, SpatialError
from haystack.utils import log as logging
from haystack.utils.app_loading import haystack_get_model

try:
    from geopy import distance as geopy_distance
except ImportError:
    geopy_distance = None


class SearchResult(object):

    def __init__(self, app_label, model_name, pk, score, **kwargs):
        self.app_label, self.model_name = app_label, model_name
        self.pk = pk
        self.score = score
        self._object = None
        self._model = None
        self._verbose_name = None
        self._additional_fields = []
        self._point_of_origin = kwargs.pop("_point_of_origin", None)
        self._distance = kwargs.pop("_distance", None)
        self.stored_fields = None
        self.log = self._get_log()

        for key, value in kwargs.items():
            if key not in self.__dict__:
                self.__dict__[key] = value
                self._additional_fields.append(key)

    def _get_log(self):
        return logging.getLogger("haystack")

    def __repr__(self):
        return "<SearchResult: %s.%s (pk=%r)>" % (
            self.app_label,
            self.model_name,
            self.pk,
        )

    def __str__(self):
        return force_str(self.__repr__())

    def __getattr__(self, attr):
        if attr == "__getnewargs__":
            raise AttributeError

        return self.__dict__.get(attr, None)

    def _get_searchindex(self):
        from haystack import connections

        return connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model)

    searchindex = property(_get_searchindex)

    def _get_object(self):
        if self._object is None:
            if self.model is None:
                self.log.error("Model could not be found for SearchResult '%s'.", self)
                return None

            try:
                try:
                    self._object = self.searchindex.read_queryset().get(pk=self.pk)
                except NotHandled:


## ... source file abbreviated to get to force_str examples ...


                )

            po_lng, po_lat = self._point_of_origin["point"].coords
            location_field = getattr(self, self._point_of_origin["field"])

            if location_field is None:
                return None

            lf_lng, lf_lat = location_field.coords
            self._distance = Distance(
                km=geopy_distance.distance((po_lat, po_lng), (lf_lat, lf_lng)).km
            )

        return self._distance

    def _set_distance(self, dist):
        self._distance = dist

    distance = property(_get_distance, _set_distance)

    def _get_verbose_name(self):
        if self.model is None:
            self.log.error("Model could not be found for SearchResult '%s'.", self)
            return ""

        return force_str(capfirst(self.model._meta.verbose_name))

    verbose_name = property(_get_verbose_name)

    def _get_verbose_name_plural(self):
        if self.model is None:
            self.log.error("Model could not be found for SearchResult '%s'.", self)
            return ""

        return force_str(capfirst(self.model._meta.verbose_name_plural))

    verbose_name_plural = property(_get_verbose_name_plural)

    def content_type(self):
        if self.model is None:
            self.log.error("Model could not be found for SearchResult '%s'.", self)
            return ""

        return str(self.model._meta)

    def get_additional_fields(self):
        additional_fields = {}

        for fieldname in self._additional_fields:
            additional_fields[fieldname] = getattr(self, fieldname)

        return additional_fields

    def get_stored_fields(self):
        if self._stored_fields is None:
            from haystack import connections

            try:
                index = connections[DEFAULT_ALIAS].get_unified_index().get_index(self.model)


## ... source file continues with no further force_str examples...

Example 7 from django-import-export

django-import-export (documentation and PyPI page) is a Django code library for importing and exporting data from the Django Admin. The tool supports many export and import formats such as CSV, JSON and YAML. django-import-export is open source under the BSD 2-Clause "Simplified" License.

django-import-export / import_export / widgets.py

# widgets.py
import json
from datetime import date, datetime
from decimal import Decimal

from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.utils import datetime_safe, timezone
from django.utils.dateparse import parse_duration
from django.utils.encoding import force_str, smart_str


class Widget:
    def clean(self, value, row=None, *args, **kwargs):
        return value

    def render(self, value, obj=None):
        return force_str(value)


class NumberWidget(Widget):

    def is_empty(self, value):
        if isinstance(value, str):
            value = value.strip()
        return value is None or value == ""

    def render(self, value, obj=None):
        return value


class FloatWidget(NumberWidget):

    def clean(self, value, row=None, *args, **kwargs):
        if self.is_empty(value):
            return None
        return float(value)


class IntegerWidget(NumberWidget):

    def clean(self, value, row=None, *args, **kwargs):
        if self.is_empty(value):
            return None
        return int(float(value))


class DecimalWidget(NumberWidget):

    def clean(self, value, row=None, *args, **kwargs):
        if self.is_empty(value):
            return None
        return Decimal(force_str(value))


class CharWidget(Widget):

    def render(self, value, obj=None):
        return force_str(value)


class BooleanWidget(Widget):
    TRUE_VALUES = ["1", 1, True, "true", "TRUE", "True"]
    FALSE_VALUES = ["0", 0, False, "false", "FALSE", "False"]
    NULL_VALUES = ["", None, "null", "NULL", "none", "NONE", "None"]

    def render(self, value, obj=None):
        if value in self.NULL_VALUES:
            return ""
        return self.TRUE_VALUES[0] if value else self.FALSE_VALUES[0]

    def clean(self, value, row=None, *args, **kwargs):
        if value in self.NULL_VALUES:
            return None
        return True if value in self.TRUE_VALUES else False


class DateWidget(Widget):

    def __init__(self, format=None):
        if format is None:
            if not settings.DATE_INPUT_FORMATS:
                formats = ("%Y-%m-%d",)


## ... source file continues with no further force_str examples...

Example 8 from django-jsonfield

django-jsonfield (jsonfield on PyPi) is a Django code library that makes it easier to store validated JSON in a Django object-relational mapper (ORM) database model.

The django-jsonfield project is open source under the MIT license.

django-jsonfield / src/jsonfield / encoder.py

# encoder.py
import datetime
import decimal
import json
import uuid

from django.db.models.query import QuerySet
from django.utils import timezone
from django.utils.encoding import force_str
from django.utils.functional import Promise


class JSONEncoder(json.JSONEncoder):
    def default(self, obj):  # noqa: C901
        if isinstance(obj, Promise):
            return force_str(obj)
        elif isinstance(obj, datetime.datetime):
            representation = obj.isoformat()
            if representation.endswith('+00:00'):
                representation = representation[:-6] + 'Z'
            return representation
        elif isinstance(obj, datetime.date):
            return obj.isoformat()
        elif isinstance(obj, datetime.time):
            if timezone and timezone.is_aware(obj):
                raise ValueError("JSON can't represent timezone-aware times.")
            representation = obj.isoformat()
            return representation
        elif isinstance(obj, datetime.timedelta):
            return str(obj.total_seconds())
        elif isinstance(obj, decimal.Decimal):
            return float(obj)
        elif isinstance(obj, uuid.UUID):
            return str(obj)
        elif isinstance(obj, QuerySet):
            return tuple(obj)
        elif isinstance(obj, bytes):
            return obj.decode()
        elif hasattr(obj, 'tolist'):
            return obj.tolist()


## ... source file continues with no further force_str examples...

Example 9 from django-oauth-toolkit

django-oauth-toolkit (project website and PyPI package information) is a code library for adding and handling OAuth2 flows within your Django web application and API.

The django-oauth-toolkit project is open sourced under the FreeBSD license and it is maintained by the developer community group Jazzband.

django-oauth-toolkit / oauth2_provider / validators.py

# validators.py
import re
from urllib.parse import urlsplit

from django.core.exceptions import ValidationError
from django.core.validators import URLValidator
from django.utils.encoding import force_str


class URIValidator(URLValidator):
    scheme_re = r"^(?:[a-z][a-z0-9\.\-\+]*)://"

    dotless_domain_re = r"(?!-)[A-Z\d-]{1,63}(?<!-)"
    host_re = "|".join((
        r"(?:" + URLValidator.host_re,
        URLValidator.ipv4_re,
        URLValidator.ipv6_re,
        dotless_domain_re + ")"
    ))
    port_re = r"(?::\d{2,5})?"
    path_re = r"(?:[/?#][^\s]*)?"
    regex = re.compile(scheme_re + host_re + port_re + path_re, re.IGNORECASE)


class RedirectURIValidator(URIValidator):
    def __init__(self, allowed_schemes, allow_fragments=False):
        super().__init__(schemes=allowed_schemes)
        self.allow_fragments = allow_fragments

    def __call__(self, value):
        super().__call__(value)
        value = force_str(value)
        scheme, netloc, path, query, fragment = urlsplit(value)
        if fragment and not self.allow_fragments:
            raise ValidationError("Redirect URIs must not contain fragments")



class WildcardSet(set):
    def __contains__(self, item):
        return True



## ... source file continues with no further force_str examples...

Example 10 from django-rest-framework

Django REST Framework (project homepage and documentation, PyPI package information and more resources on Full Stack Python), often abbreviated as "DRF", is a popular Django extension for building web APIs. The project has fantastic documentation and a wonderful quickstart that serve as examples of how to make it easier for newcomers to get started.

The project is open sourced under the Encode OSS Ltd. license.

django-rest-framework / rest_framework / metadata.py

# metadata.py
from collections import OrderedDict

from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.encoding import force_str

from rest_framework import exceptions, serializers
from rest_framework.request import clone_request
from rest_framework.utils.field_mapping import ClassLookupDict


class BaseMetadata:
    def determine_metadata(self, request, view):
        raise NotImplementedError(".determine_metadata() must be overridden.")


class SimpleMetadata(BaseMetadata):
    label_lookup = ClassLookupDict({
        serializers.Field: 'field',
        serializers.BooleanField: 'boolean',
        serializers.NullBooleanField: 'boolean',
        serializers.CharField: 'string',
        serializers.UUIDField: 'string',
        serializers.URLField: 'url',
        serializers.EmailField: 'email',
        serializers.RegexField: 'regex',
        serializers.SlugField: 'slug',
        serializers.IntegerField: 'integer',
        serializers.FloatField: 'float',


## ... source file abbreviated to get to force_str examples ...


        return actions

    def get_serializer_info(self, serializer):
        if hasattr(serializer, 'child'):
            serializer = serializer.child
        return OrderedDict([
            (field_name, self.get_field_info(field))
            for field_name, field in serializer.fields.items()
            if not isinstance(field, serializers.HiddenField)
        ])

    def get_field_info(self, field):
        field_info = OrderedDict()
        field_info['type'] = self.label_lookup[field]
        field_info['required'] = getattr(field, 'required', False)

        attrs = [
            'read_only', 'label', 'help_text',
            'min_length', 'max_length',
            'min_value', 'max_value'
        ]

        for attr in attrs:
            value = getattr(field, attr, None)
            if value is not None and value != '':
                field_info[attr] = force_str(value, strings_only=True)

        if getattr(field, 'child', None):
            field_info['child'] = self.get_field_info(field.child)
        elif getattr(field, 'fields', None):
            field_info['children'] = self.get_serializer_info(field)

        if (not field_info.get('read_only') and
            not isinstance(field, (serializers.RelatedField, serializers.ManyRelatedField)) and
                hasattr(field, 'choices')):
            field_info['choices'] = [
                {
                    'value': choice_value,
                    'display_name': force_str(choice_name, strings_only=True)
                }
                for choice_value, choice_name in field.choices.items()
            ]

        return field_info



## ... source file continues with no further force_str examples...

Example 11 from django-tables2

django-tables2 (projection documentation and PyPI page) is a code library for Django that simplifies creating and displaying tables in Django templates, especially with more advanced features such as pagination and sorting. The project and its code are available as open source.

django-tables2 / django_tables2 / tables.py

# tables.py
import copy
from collections import OrderedDict
from itertools import count

from django.conf import settings
from django.core.paginator import Paginator
from django.db import models
from django.template.loader import get_template
from django.utils.encoding import force_str

from . import columns
from .config import RequestConfig
from .data import TableData
from .rows import BoundRows
from .utils import Accessor, AttributeDict, OrderBy, OrderByTuple, Sequence


class DeclarativeColumnsMetaclass(type):

    def __new__(mcs, name, bases, attrs):
        attrs["_meta"] = opts = TableOptions(attrs.get("Meta", None), name)

        cols, remainder = [], {}
        for attr_name, attr in attrs.items():
            if isinstance(attr, columns.Column):
                attr._explicit = True
                cols.append((attr_name, attr))
            else:
                remainder[attr_name] = attr
        attrs = remainder

        cols.sort(key=lambda x: x[1].creation_counter)



## ... source file abbreviated to get to force_str examples ...


        return

    def as_html(self, request):
        self._counter = count()
        template = get_template(self.template_name)

        context = {"table": self, "request": request}

        self.before_render(request)
        return template.render(context)

    def as_values(self, exclude_columns=None):
        if exclude_columns is None:
            exclude_columns = ()

        columns = [
            column
            for column in self.columns.iterall()
            if not (column.column.exclude_from_export or column.name in exclude_columns)
        ]

        yield [force_str(column.header, strings_only=True) for column in columns]

        for row in self.rows:
            yield [
                force_str(row.get_cell_value(column.name), strings_only=True) for column in columns
            ]

    def has_footer(self):
        return self.show_footer and any(column.has_footer() for column in self.columns)

    @property
    def show_header(self):
        return self._show_header if self._show_header is not None else self._meta.show_header

    @show_header.setter
    def show_header(self, value):
        self._show_header = value

    @property
    def order_by(self):
        return self._order_by

    @order_by.setter
    def order_by(self, value):
        order_by = () if not value else value
        order_by = order_by.split(",") if isinstance(order_by, str) else order_by
        valid = []

        for alias in order_by:


## ... source file continues with no further force_str examples...

Example 12 from wagtail

wagtail (project website) is a fantastic Django-based CMS with code that is open source under the BSD 3-Clause "New" or "Revised" License.

wagtail / wagtail / core / fields.py

# fields.py
import json
from html import unescape

from django.core.serializers.json import DjangoJSONEncoder
from django.db import models
from django.utils.encoding import force_str
from django.utils.html import strip_tags

from wagtail.core.blocks import Block, BlockField, StreamBlock, StreamValue


class RichTextField(models.TextField):
    def __init__(self, *args, **kwargs):
        self.editor = kwargs.pop('editor', 'default')
        self.features = kwargs.pop('features', None)
        super().__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        from wagtail.admin.rich_text import get_rich_text_editor_widget
        defaults = {'widget': get_rich_text_editor_widget(self.editor, features=self.features)}
        defaults.update(kwargs)
        return super().formfield(**defaults)

    def get_searchable_content(self, value):
        source = force_str(value)
        return [unescape(strip_tags(source))]


class Creator:
    def __init__(self, field):
        self.field = field

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        field_name = self.field.name

        if field_name not in obj.__dict__:
            obj.refresh_from_db(fields=[field_name])
        return obj.__dict__[field_name]

    def __set__(self, obj, value):
        obj.__dict__[self.field.name] = self.field.to_python(value)


class StreamField(models.Field):
    def __init__(self, block_types, **kwargs):
        super().__init__(**kwargs)
        if isinstance(block_types, Block):


## ... source file continues with no further force_str examples...
1. Introduction 2. Development Environments 3. Data 4. Web Development 5. Deployment 6. DevOps Changelog What Full Stack Means About the Author Future Directions Page Statuses Django ExtensionsDjango Example Codedjango.apps.config AppConfigdjango.conf settingsdjango.conf.urls.urldjango.contrib.admindjango.contrib.admin.filters SimpleListFilterdjango.contrib.admin.sites registerdjango.contrib.admin helpersdjango.contrib.admin.helpers ActionFormdjango.contrib.admin.helpers AdminFormdjango.contrib.admin.options IS_POPUP_VARdjango.contrib.admin.options IncorrectLookupParametersdjango.contrib.admin.options ModelAdmindjango.contrib.admin.options csrf_protect_mdjango.contrib.admin.sites NotRegistereddjango.contrib.admin.sites sitedjango.contrib.staticfiles findersdjango.contrib.staticfiles storagedjango.contrib.staticfiles.finders BaseFinderdjango.contrib.staticfiles.finders BaseStorageFinderdjango.contrib.staticfiles.finders finddjango.contrib.staticfiles.finders get_findersdjango.contrib.staticfiles.handlers StaticFilesHandlerdjango.contrib.staticfiles.storage CachedStaticFilesStoragedjango.contrib.staticfiles.storage HashedFilesMixindjango.contrib.staticfiles.storage ManifestStaticFilesStoragedjango.contrib.staticfiles.storage StaticFilesStoragedjango.contrib.staticfiles.storage staticfiles_storagedjango.contrib.staticfiles.utils matches_patternsdjango.core cachedjango.core checksdjango.core exceptionsdjango.core maildjango.core managementdjango.core serializersdjango.core signalsdjango.core signingdjango.core validatorsdjango.core.exceptions DisallowedRedirectdjango.core.exceptions FieldDoesNotExistdjango.core.exceptions FieldErrordjango.core.exceptions MiddlewareNotUseddjango.core.exceptions NON_FIELD_ERRORSdjango.core.exceptions ObjectDoesNotExistdjango.core.exceptions PermissionDenieddjango.core.exceptions SuspiciousFileOperationdjango.core.exceptions SuspiciousMultipartFormdjango.core.exceptions ValidationErrordjango.db DEFAULT_DB_ALIASdjango.db DataErrordjango.db DatabaseErrordjango.db IntegrityErrordjango.db ProgrammingErrordjango.db connectiondjango.db connectionsdjango.db migrationsdjango.db modelsdjango.db routerdjango.db transactiondjango.db.backends utilsdjango.db.migrations RunPythondjango.db.migrations.autodetector MigrationAutodetectordjango.db.migrations.exceptions IrreversibleErrordjango.db.migrations.executor MigrationExecutordjango.db.migrations.loader MIGRATIONS_MODULE_NAMEdjango.db.migrations.loader MigrationLoaderdjango.db.migrations.operations.base Operationdjango.db.migrations.state ProjectStatedjango.db.models.query BaseIterabledjango.db.models.query EmptyQuerySetdjango.db.models.query ModelIterabledjango.db.models.query Prefetchdjango.db.models.query Qdjango.db.models.query QuerySetdjango.db.models.query prefetch_related_objectsdjango.db.models.query_utils DeferredAttributedjango.db.models.query_utils PathInfodjango.db.models.query_utils Qdjango.db.models.signals post_deletedjango.db.models.signals post_savedjango.db.models.signals pre_deletedjango.db.models.signals pre_savedjango.forms BaseFormdjango.forms CheckboxInputdjango.forms CheckboxSelectMultipledjango.forms DateInputdjango.forms Fielddjango.forms FileInputdjango.forms FilePathFielddjango.forms Formdjango.forms HiddenInputdjango.forms ImageFielddjango.forms Mediadjango.forms MediaDefiningClassdjango.forms ModelChoiceFielddjango.forms ModelFormdjango.forms ModelMultipleChoiceFielddjango.forms MultipleChoiceFielddjango.forms Selectdjango.forms SelectMultipledjango.forms ValidationErrordjango.shortcuts get_list_or_404django.shortcuts get_object_or_404django.shortcuts redirectdjango.shortcuts renderdjango.shortcuts resolve_urldjango.template Contextdjango.template.base Contextdjango.template loaderdjango.template.base FilterExpressiondjango.template.base Nodedjango.template.base NodeListdjango.template.base Parserdjango.template.base Templatedjango.template.base TemplateSyntaxErrordjango.template.base TextNodedjango.template.base Tokendjango.template.base TokenTypedjango.template.base VariableDoesNotExistdjango.template.base VariableNodedjango.template.base token_kwargsdjango.template.context Contextdjango.template.defaultfilters escapedjango.template.defaultfilters filesizeformatdjango.template.defaultfilters safedjango.template.defaultfilters slugifydjango.template.defaultfilters striptagsdjango.template.defaultfilters titledjango.template.defaultfilters truncatecharsdjango.template.loader get_templatedjango.template.loader render_to_stringdjango.template.loader select_templatedjango.template.loader_tags BlockNodedjango.template.loader_tags ExtendsNodedjango.template.loader_tags IncludeNodedjango.template.loaders.filesystem Loaderdjango.urls URLPatterndjango.urls URLResolverdjango.urls clear_url_cachesdjango.urls get_callabledjango.urls get_resolverdjango.urls get_script_prefixdjango.urls includedjango.urls re_pathdjango.urls register_converterdjango.urls resolvedjango.urls reversedjango.utils dateformatdjango.utils dateparsedjango.utils datetime_safedjango.utils formatsdjango.utils module_loadingdjango.utils termcolorsdjango.utils translationdjango.utils treedjango.utils.cache add_never_cache_headersdjango.utils.cache cc_delim_redjango.utils.cache patch_cache_controldjango.utils.cache patch_response_headersdjango.utils.cache patch_vary_headersdjango.utils.crypto constant_time_comparedjango.utils.crypto get_random_stringdjango.utils.datastructures MultiValueDictdjango.utils.dateparse parse_datetimedjango.utils.dateparse parse_durationdjango.utils.dates MONTHSdjango.utils.datetime_safe datetimedjango.utils.decorators method_decoratordjango.utils.deprecation MiddlewareMixindjango.utils.deprecation RenameMethodsBasedjango.utils.duration duration_stringdjango.utils.encoding DjangoUnicodeDecodeErrordjango.utils.encoding filepath_to_uridjango.utils.encoding force_bytesdjango.utils.encoding force_strdjango.utils.encoding force_textdjango.utils.encoding iri_to_uridjango.utils.encoding is_protected_typedjango.utils.encoding smart_bytesdjango.utils.encoding smart_strdjango.utils.encoding smart_textdjango.utils.encoding uri_to_iridjango.utils.formats get_formatdjango.utils.formats localize_inputdjango.utils.formats sanitize_separatorsdjango.utils.functional LazyObjectdjango.utils.functional Promisedjango.utils.functional SimpleLazyObjectdjango.utils.functional keep_lazydjango.utils.functional lazydjango.utils.functional total_orderingdjango.utils.functional wrapsdjango.utils.html conditional_escapedjango.utils.html escapedjango.utils.html escapejsdjango.utils.html format_html_joindjango.utils.html mark_safedjango.utils.html smart_urlquotedjango.utils.html strip_tagsdjango.utils.http base36_to_intdjango.utils.http http_datedjango.utils.http int_to_base36django.utils.http is_safe_urldjango.utils.http unquotedjango.utils.http url_has_allowed_host_and_schemedjango.utils.http urlencodedjango.utils.http urlquotedjango.utils.http urlunquotedjango.utils.ipv6 clean_ipv6_addressdjango.utils.itercompat is_iterabledjango.utils.module_loading autodiscover_modulesdjango.utils.module_loading import_stringdjango.utils.module_loading module_has_submoduledjango.utils.numberformat formatdjango.utils.safestring SafeDatadjango.utils.safestring SafeTextdjango.utils.safestring mark_safedjango.utils.termcolors colorizedjango.utils.text Truncatordjango.utils.text capfirstdjango.utils.text format_lazydjango.utils.text get_text_listdjango.utils.text get_valid_filenamedjango.utils.text slugifydjango.utils.timezone get_current_timezonedjango.utils.timezone make_awaredjango.utils.timezone nowdjango.utils.timezone timedeltadjango.utils.translation LANGUAGE_SESSION_KEYdjango.utils.translation activatedjango.utils.translation deactivate_alldjango.utils.translation get_languagedjango.utils.translation get_language_from_requestdjango.utils.translation gettextdjango.utils.translation gettext_lazydjango.utils.translation ngettextdjango.utils.translation overridedjango.utils.translation pgettextdjango.utils.translation pgettext_lazydjango.utils.translation ugettextdjango.utils.translation ugettext_lazydjango.utils.translation ungettextdjango.utils.translation ungettext_lazydjango.utils.version get_complete_versiondjango.views csrfdjango.views.debug get_default_exception_reporter_filterdjango.views.decorators.csrf csrf_exemptdjango.views.decorators.debug sensitive_post_parametersdjango.views.decorators.http require_GETdjango.views.decorators.http require_POSTdjango.views.generic CreateViewdjango.views.generic DeleteViewdjango.views.generic DetailViewdjango.views.generic FormViewdjango.views.generic ListViewdjango.views.generic RedirectViewdjango.views.generic TemplateViewdjango.views.generic UpdateViewdjango.views.generic Viewdjango.views.generic.base RedirectViewdjango.views.generic.base TemplateResponseMixindjango.views.generic.base TemplateViewdjango.views.generic.base Viewdjango.views.generic.detail SingleObjectMixindjango.views.generic.edit CreateViewdjango.views.generic.edit DeleteViewdjango.views.generic.edit DeletionMixindjango.views.generic.edit FormMixindjango.views.generic.edit FormViewdjango.views.generic.list ListViewdjango.views.generic.list MultipleObjectMixindjango.views.i18n JavaScriptCatalogdjango.views.static servedjango.views.static was_modified_sincedjango.contrib.auth.decorators login_requireddjango.contrib.auth get_user_modeldjango.contrib.auth.hashers make_passworddjango.core.exceptions ImproperlyConfigureddjango.core.mail.messages EmailMessagedjango.core.mail.send_maildjango.core.management.base BaseCommanddjango.db.models AutoFielddjango.db.models BooleanFielddjango.db.models CharFielddjango.db.models DateFielddjango.db.models DateTimeFielddjango.db.models FileFielddjango.db.models ForeignKeydjango.db.models GenericIPAddressFielddjango.db.models ImageFielddjango.db.models IntegerFielddjango.db.models Modeldjango.db.models PositiveIntegerFielddjango.db.models PositiveSmallIntegerFielddjango.db.models.signaldjango.db.models SlugFielddjango.db.models SmallIntegerFielddjango.db.models TextFielddjango.db OperationalErrordjango.dispatch Signaldjango.formsdjango.forms BooleanFielddjango.forms CharFielddjango.forms ChoiceFielddjango.forms DateFielddjango.forms DateTimeFielddjango.forms EmailFielddjango.forms IntegerFielddjango.forms TypedChoiceFielddjango.http Http404django.http HttpResponsedjango.http HttpResponseBadRequestdjango.http HttpResponseForbiddendjango.http HttpResponseNotModifieddjango.http HttpResponsePermanentRedirectdjango.http HttpResponseRedirectdjango.template.response SimpleTemplateResponsedjango.template.response TemplateResponsedjango.urls.pathdjango.urls reverse_lazydjango.urls.exceptions NoReverseMatchdjango.urls.exceptions Resolver404django.utils.html format_htmldjango.utils.timezone ...or view the full table of contents.

Full Stack Python

Full Stack Python is an open book that explains concepts in plain language and provides helpful resources for those topics.
Updates via Twitter & Facebook.

Matt Makai 2012-2022