Coverage for utilities/querydict.py: 21%
27 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 18:35 +0000
1from urllib.parse import urlencode
3from django.http import QueryDict
4from django.utils.datastructures import MultiValueDict
6from netbox.models.features import CloningMixin
8__all__ = (
9 'dict_to_querydict',
10 'normalize_querydict',
11 'prepare_cloned_fields',
12)
15def dict_to_querydict(d, mutable=True):
16 """
17 Create a QueryDict instance from a regular Python dictionary.
18 """
19 qd = QueryDict(mutable=True)
20 for k, v in d.items():
21 item = MultiValueDict({k: v}) if isinstance(v, (list, tuple, set)) else {k: v}
22 qd.update(item)
23 if not mutable:
24 qd._mutable = False
25 return qd
28def normalize_querydict(querydict):
29 """
30 Convert a QueryDict to a normal, mutable dictionary, preserving list values. For example,
32 QueryDict('foo=1&bar=2&bar=3&baz=')
34 becomes:
36 {'foo': '1', 'bar': ['2', '3'], 'baz': ''}
38 This function is necessary because QueryDict does not provide any built-in mechanism which preserves multiple
39 values.
40 """
41 return {
42 k: v if len(v) > 1 else v[0] for k, v in querydict.lists()
43 }
46def prepare_cloned_fields(instance):
47 """
48 Generate a QueryDict comprising attributes from an object's clone() method.
49 """
50 # Generate the clone attributes from the instance
51 if not issubclass(type(instance), CloningMixin):
52 return QueryDict(mutable=True)
53 attrs = instance.clone()
55 # Prepare QueryDict parameters
56 params = []
57 for key, value in attrs.items():
58 if type(value) in (list, tuple):
59 params.extend([(key, v) for v in value])
60 elif value is not False and value is not None:
61 params.append((key, value))
62 else:
63 params.append((key, ''))
65 # Return a QueryDict with the parameters
66 return QueryDict(urlencode(params), mutable=True)