URL manipulation made simple.
65
The Query class handles URL query string manipulation with support for multiple values per key, custom encoding options, and ordered parameter dictionaries. It provides comprehensive query parameter management while maintaining proper URL encoding.
Create and load query objects from various input formats with automatic parsing and encoding.
class Query:
def __init__(self, query='', strict=False):
"""
Initialize a Query object.
Args:
query (str): Query string to parse
strict (bool): Enable strict parsing mode
"""
def load(self, query):
"""
Load query string or parameters into the Query object.
Args:
query (str|dict|list): Query string, dictionary, or list of tuples
Returns:
Query: Self for method chaining
"""Usage:
from furl import Query
# Create from query string
q = Query('key1=value1&key2=value2&key1=another')
print(q.params.allitems()) # [('key1', 'value1'), ('key2', 'value2'), ('key1', 'another')]
# Create from dictionary
q = Query()
q.load({'name': 'John', 'age': '30'})
print(str(q)) # 'name=John&age=30'
# Create from list of tuples
q.load([('category', 'electronics'), ('category', 'computers')])
print(q.params.getlist('category')) # ['electronics', 'computers']Add, set, and remove query parameters with support for multiple values per key.
class Query:
@property
def params(self) -> 'omdict1D':
"""
Ordered multivalue dictionary containing query parameters.
Supports multiple values per key and maintains insertion order.
"""
@params.setter
def params(self, params):
"""Set parameters from various input types"""
def add(self, args):
"""
Add query parameters without replacing existing ones.
Args:
args (dict|list|str): Parameters to add
Returns:
Query: Self for method chaining
"""
def set(self, mapping):
"""
Set query parameters, replacing existing ones.
Args:
mapping (dict|list|str): Parameters to set
Returns:
Query: Self for method chaining
"""
def remove(self, query):
"""
Remove query parameters.
Args:
query (list|str|bool): Parameter keys to remove, or True for all
Returns:
Query: Self for method chaining
"""Usage:
q = Query('existing=value')
# Add parameters (preserves existing)
q.add({'new': 'parameter', 'existing': 'another'})
print(q.params.allitems()) # [('existing', 'value'), ('new', 'parameter'), ('existing', 'another')]
# Set parameters (replaces existing)
q.set({'fresh': 'start', 'count': '5'})
print(str(q)) # 'fresh=start&count=5'
# Add multiple values for same key
q.add([('tags', 'python'), ('tags', 'url'), ('tags', 'parsing')])
print(q.params.getlist('tags')) # ['python', 'url', 'parsing']
# Remove specific parameters
q.remove(['count'])
print('count' in q.params) # False
# Remove all parameters
q.remove(True)
print(str(q)) # ''Access individual parameters and handle multiple values per key.
class omdict1D:
def __getitem__(self, key):
"""Get first value for key"""
def __setitem__(self, key, value):
"""Set value for key (replaces all existing values)"""
def __delitem__(self, key):
"""Remove all values for key"""
def __contains__(self, key):
"""Check if key exists"""
def get(self, key, default=None):
"""Get first value for key with default"""
def getlist(self, key):
"""Get all values for key as list"""
def setlist(self, key, values):
"""Set multiple values for key"""
def addlist(self, key, values):
"""Add multiple values for key"""
def items(self):
"""Iterator over (key, first_value) pairs"""
def allitems(self):
"""List of all (key, value) pairs including duplicates"""
def keys(self):
"""Iterator over unique keys"""
def values(self):
"""Iterator over first values"""Usage:
q = Query('name=John&skills=python&skills=django&skills=rest')
# Access first value
print(q.params['name']) # 'John'
print(q.params['skills']) # 'python' (first value)
# Access all values
print(q.params.getlist('skills')) # ['python', 'django', 'rest']
# Set single value
q.params['name'] = 'Jane'
print(q.params['name']) # 'Jane'
# Set multiple values
q.params.setlist('languages', ['python', 'javascript', 'go'])
print(q.params.getlist('languages')) # ['python', 'javascript', 'go']
# Add to existing values
q.params.addlist('skills', ['postgresql'])
print(q.params.getlist('skills')) # ['python', 'django', 'rest', 'postgresql']
# Check existence
print('name' in q.params) # True
print('age' in q.params) # False
# Iterate over parameters
for key, value in q.params.items():
print(f"{key}: {value}") # Prints first value for each key
# Iterate over all values
for key, value in q.params.allitems():
print(f"{key}: {value}") # Prints all key-value pairsConvert query objects to strings with customizable encoding options.
class Query:
def encode(self, delimiter='&', quote_plus=True, dont_quote='',
delimeter=None):
"""
Encode query parameters to string.
Args:
delimiter (str): Separator between parameters
quote_plus (bool): Use '+' for spaces instead of '%20'
dont_quote (str): Characters not to percent-encode
delimeter (str): Deprecated alias for delimiter
Returns:
str: Encoded query string
"""
def __str__(self):
"""Default string encoding of query parameters"""Usage:
q = Query()
q.add({'name': 'John Doe', 'message': 'Hello World!', 'chars': 'special&chars'})
# Default encoding
print(str(q)) # 'name=John+Doe&message=Hello+World%21&chars=special%26chars'
# Custom delimiter
print(q.encode(delimiter=';')) # 'name=John+Doe;message=Hello+World%21;chars=special%26chars'
# Disable plus encoding for spaces
print(q.encode(quote_plus=False)) # 'name=John%20Doe&message=Hello%20World%21&chars=special%26chars'
# Don't quote certain characters
print(q.encode(dont_quote='!&')) # 'name=John+Doe&message=Hello+World!&chars=special&chars'Perform operations on query objects and convert to different formats.
class Query:
def asdict(self):
"""
Convert query to dictionary representation.
Returns:
dict: Dictionary with query metadata and parameters
"""
def __eq__(self, other):
"""Check query equality"""
def __bool__(self):
"""Boolean evaluation (True if query has parameters)"""Usage:
q1 = Query('name=John&age=30')
q2 = Query('age=30&name=John')
# Query comparison (order matters)
print(q1 == q2) # False (different order)
# Boolean evaluation
empty_query = Query()
print(bool(empty_query)) # False
non_empty = Query('key=value')
print(bool(non_empty)) # True
# Dictionary representation
query_dict = q1.asdict()
print(query_dict) # Contains query metadata and parametersHandle parameters with multiple values using the ordered multivalue dictionary:
q = Query()
# Multiple values for same parameter
q.params.addlist('colors', ['red', 'green', 'blue'])
q.params.add('colors', 'yellow')
print(q.params.getlist('colors')) # ['red', 'green', 'blue', 'yellow']
print(str(q)) # 'colors=red&colors=green&colors=blue&colors=yellow'
# Replace all values for a key
q.params.setlist('colors', ['black', 'white'])
print(q.params.getlist('colors')) # ['black', 'white']The omdict1D maintains insertion order:
q = Query()
q.add({'z': '1', 'a': '2', 'm': '3'})
print(str(q)) # 'z=1&a=2&m=3' (maintains insertion order)
# Adding more parameters maintains order
q.add({'b': '4'})
print(str(q)) # 'z=1&a=2&m=3&b=4'Handle complex parameter values with proper encoding:
q = Query()
# Unicode values
q.add({'greeting': 'Hello 世界', 'emoji': '🚀'})
# Special characters
q.add({'query': 'SELECT * FROM users WHERE name = "John"'})
# List-like values (automatically flattened)
q.params.addlist('items', ['item1', 'item2', 'item3'])
print(str(q)) # Properly encoded query stringQuery objects handle various edge cases:
strict=True# Handling edge cases
q = Query(strict=False) # Lenient parsing
# Empty values
q.add({'empty': '', 'none_value': None})
# Invalid percent encoding (handled gracefully)
q.load('malformed=%ZZ&valid=ok')
# Unicode handling
q.add({'unicode': '测试'})Install with Tessl CLI
npx tessl i tessl/pypi-furlevals
scenario-1
scenario-2
scenario-3
scenario-4
scenario-5
scenario-6
scenario-7
scenario-8
scenario-9
scenario-10