diff --git a/rest_framework/filters.py b/rest_framework/filters.py
index e68726499..418993405 100644
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -297,7 +297,7 @@ class OrderingFilter(BaseFilterBackend):
ascending_translation = _("ascending")
descending_translation = _("descending")
options.append((key, f'{label} - {ascending_translation}'))
- options.append(('-' + key, f'{label} - {descending_translation}'))
+ options.append((f'-{key}', f'{label} - {descending_translation}'))
context['options'] = options
return context
diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py
index e815d8d5c..13a91d753 100644
--- a/rest_framework/pagination.py
+++ b/rest_framework/pagination.py
@@ -118,7 +118,7 @@ def _reverse_ordering(ordering_tuple):
ordering and return a new tuple, eg. `('created', '-uuid')`.
"""
def invert(x):
- return x[1:] if x.startswith('-') else '-' + x
+ return x[1:] if x.startswith('-') else f'-{x}'
return tuple([invert(item) for item in ordering_tuple])
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index e8740d57b..068d109c4 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -344,7 +344,7 @@ class HTMLFormRenderer(BaseRenderer):
if 'template' in style:
template_name = style['template']
else:
- template_name = style['template_pack'].strip('/') + '/' + style['base_template']
+ template_name = style['template_pack'].strip('/') + f"/{style['base_template']}"
template = loader.get_template(template_name)
context = {'field': field, 'style': style}
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index e0ae24b95..2ee4b457f 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -254,7 +254,7 @@ class SimpleRouter(BaseRouter):
# so a slash in the beginning will (A) cause Django to give
# warnings and (B) generate URLS that will require using '//'.
if not prefix and regex[:2] == '^/':
- regex = '^' + regex[2:]
+ regex = f'^{regex[2:]}'
initkwargs = route.initkwargs.copy()
initkwargs.update({
@@ -283,7 +283,7 @@ class APIRootView(views.APIView):
namespace = request.resolver_match.namespace
for key, url_name in self.api_root_dict.items():
if namespace:
- url_name = namespace + ':' + url_name
+ url_name = f"{namespace}:{url_name}"
try:
ret[key] = reverse(
url_name,
diff --git a/rest_framework/schemas/coreapi.py b/rest_framework/schemas/coreapi.py
index 179f0fa3c..c892caae2 100644
--- a/rest_framework/schemas/coreapi.py
+++ b/rest_framework/schemas/coreapi.py
@@ -240,7 +240,7 @@ class SchemaGenerator(BaseSchemaGenerator):
# We can just break early in the case that there's at least
# one URL that doesn't have a path prefix.
return '/'
- prefixes.append('/' + prefix + '/')
+ prefixes.append(f'/{prefix}/')
return common_path(prefixes)
# View Inspectors #
diff --git a/rest_framework/schemas/inspectors.py b/rest_framework/schemas/inspectors.py
index 027472db1..94f34637d 100644
--- a/rest_framework/schemas/inspectors.py
+++ b/rest_framework/schemas/inspectors.py
@@ -97,7 +97,7 @@ class ViewInspector:
current_section, separator, lead = line.partition(':')
sections[current_section] = lead.strip()
else:
- sections[current_section] += '\n' + line
+ sections[current_section] += f'\n{line}'
# TODO: SCHEMA_COERCE_METHOD_NAMES appears here and in `SchemaGenerator.get_keys`
coerce_method_names = api_settings.SCHEMA_COERCE_METHOD_NAMES
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index ac4b92ca8..9d02151fe 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -477,7 +477,7 @@ class Serializer(BaseSerializer, metaclass=SerializerMetaclass):
fields = self._writable_fields
for field in fields:
- validate_method = getattr(self, 'validate_' + field.field_name, None)
+ validate_method = getattr(self, f'validate_{field.field_name}', None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py
index 8e35fec6e..c692eca65 100644
--- a/rest_framework/templatetags/rest_framework.py
+++ b/rest_framework/templatetags/rest_framework.py
@@ -187,12 +187,9 @@ def add_class(value, css_class):
html = str(value)
match = class_re.search(html)
if match:
- m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class,
- css_class, css_class),
- match.group(1))
+ m = re.search(fr'[^|\s]{css_class}[$|\s]', match.group(1))
if not m:
- return mark_safe(class_re.sub(match.group(1) + " " + css_class,
- html))
+ return mark_safe(class_re.sub(f"{match.group(1)} {css_class}", html))
else:
return mark_safe(html.replace('>', f' class="{css_class}">', 1))
return value
@@ -318,5 +315,5 @@ def break_long_headers(header):
when possible (are comma separated)
"""
if len(header) > 160 and ',' in header:
- header = mark_safe('
' + ',
'.join(header.split(',')))
+ header = mark_safe(f"
{header.replace(',', ',
')}")
return header
diff --git a/rest_framework/test.py b/rest_framework/test.py
index 0212348ee..d9f93b4c7 100644
--- a/rest_framework/test.py
+++ b/rest_framework/test.py
@@ -171,7 +171,7 @@ class APIRequestFactory(DjangoRequestFactory):
"Set TEST_REQUEST_RENDERER_CLASSES to enable "
"extra request formats.".format(
format,
- ', '.join(["'" + fmt + "'" for fmt in self.renderer_classes])
+ ', '.join([f"'{fmt}'" for fmt in self.renderer_classes])
)
)
diff --git a/rest_framework/urlpatterns.py b/rest_framework/urlpatterns.py
index df2afbe51..e4b4aedcb 100644
--- a/rest_framework/urlpatterns.py
+++ b/rest_framework/urlpatterns.py
@@ -11,7 +11,7 @@ def _get_format_path_converter(suffix_kwarg, allowed):
else:
allowed_cases = "|".join(allowed)
allowed_pattern = f'(?:{allowed_cases})'
- suffix_pattern = r"\.%s/?" % allowed_pattern
+ suffix_pattern = fr"\.{allowed_pattern}/?"
else:
suffix_pattern = r"\.[a-z0-9]+/?"
@@ -22,7 +22,7 @@ def _get_format_path_converter(suffix_kwarg, allowed):
return value.strip('./')
def to_url(self, value):
- return '.' + value + '/'
+ return f'.{value}/'
converter_name = 'drf_format_suffix'
if allowed:
@@ -102,9 +102,9 @@ def format_suffix_patterns(urlpatterns, suffix_required=False, allowed=None):
else:
allowed_cases = "|".join(allowed)
allowed_pattern = f'({allowed_cases})'
- suffix_pattern = r'\.(?P<%s>%s)/?$' % (suffix_kwarg, allowed_pattern)
+ suffix_pattern = fr'\.(?P<{suffix_kwarg}>{allowed_pattern})/?$'
else:
- suffix_pattern = r'\.(?P<%s>[a-z0-9]+)/?$' % suffix_kwarg
+ suffix_pattern = fr'\.(?P<{suffix_kwarg}>[a-z0-9]+)/?$'
converter_name, suffix_converter = _get_format_path_converter(suffix_kwarg, allowed)
register_converter(suffix_converter, converter_name)
diff --git a/rest_framework/utils/formatting.py b/rest_framework/utils/formatting.py
index c5917fd41..5d6604721 100644
--- a/rest_framework/utils/formatting.py
+++ b/rest_framework/utils/formatting.py
@@ -63,7 +63,7 @@ def markup_description(description):
description = apply_markdown(description)
else:
description = escape(description).replace('\n', '
')
- description = '
' + description + '
' + description = f'{description}
' return mark_safe(description) diff --git a/rest_framework/utils/html.py b/rest_framework/utils/html.py index c7ede7803..d10dbcf8e 100644 --- a/rest_framework/utils/html.py +++ b/rest_framework/utils/html.py @@ -83,7 +83,7 @@ def parse_html_dict(dictionary, prefix=''): } """ ret = MultiValueDict() - regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix)) + regex = re.compile(fr'^{re.escape(prefix)}\.(.+)$') for field in dictionary: match = regex.match(field) if not match: diff --git a/rest_framework/utils/representation.py b/rest_framework/utils/representation.py index f50b601f3..4ba6ae83c 100644 --- a/rest_framework/utils/representation.py +++ b/rest_framework/utils/representation.py @@ -77,7 +77,7 @@ def serializer_repr(serializer, indent, force_many=None): fields = serializer.fields for field_name, field in fields.items(): - ret += '\n' + indent_str + field_name + ' = ' + ret += f'\n{indent_str}{field_name} = ' if hasattr(field, 'fields'): ret += serializer_repr(field, indent + 1) elif hasattr(field, 'child'): diff --git a/rest_framework/versioning.py b/rest_framework/versioning.py index 78cfc9dc8..72c34f624 100644 --- a/rest_framework/versioning.py +++ b/rest_framework/versioning.py @@ -135,7 +135,7 @@ class NamespaceVersioning(BaseVersioning): ) def get_versioned_viewname(self, viewname, request): - return request.version + ':' + viewname + return f"{request.version}:{viewname}" class HostNameVersioning(BaseVersioning): diff --git a/rest_framework/views.py b/rest_framework/views.py index 0b00d2134..c76e4f20d 100644 --- a/rest_framework/views.py +++ b/rest_framework/views.py @@ -39,7 +39,7 @@ def get_view_name(view): # Suffix may be set by some Views, such as a ViewSet. suffix = getattr(view, 'suffix', None) if suffix: - name += ' ' + suffix + name += f' {suffix}' return name diff --git a/rest_framework/viewsets.py b/rest_framework/viewsets.py index d3988cbcc..926577f41 100644 --- a/rest_framework/viewsets.py +++ b/rest_framework/viewsets.py @@ -162,7 +162,7 @@ class ViewSetMixin: if self.request and self.request.resolver_match: namespace = self.request.resolver_match.namespace if namespace: - url_name = namespace + ':' + url_name + url_name = f"{namespace}:{url_name}" kwargs.setdefault('request', self.request) return reverse(url_name, *args, **kwargs)