Added documentation about custom fields

This commit is contained in:
Itai Shirav 2017-10-31 11:36:17 +02:00
parent b976899f75
commit 0f9487f589
2 changed files with 39 additions and 29 deletions

View File

@ -178,37 +178,43 @@ class BooleanField(Field):
Here's another example - a field for storing UUIDs in the database as 16-byte strings. We'll use Python's built-in `UUID` class to handle the conversion from strings, ints and tuples into UUID instances. So in our Python code we'll have the convenience of working with UUID objects, but they will be stored in the database as efficiently as possible: Here's another example - a field for storing UUIDs in the database as 16-byte strings. We'll use Python's built-in `UUID` class to handle the conversion from strings, ints and tuples into UUID instances. So in our Python code we'll have the convenience of working with UUID objects, but they will be stored in the database as efficiently as possible:
```python ```python
from infi.clickhouse_orm.fields import Field from infi.clickhouse_orm.fields import Field
from infi.clickhouse_orm.utils import escape from infi.clickhouse_orm.utils import escape
from six import string_types from uuid import UUID
from uuid import UUID import six
class UUIDField(Field): class UUIDField(Field):
# The ClickHouse column type to use # The ClickHouse column type to use
db_type = 'FixedString(16)' db_type = 'FixedString(16)'
# The default value if empty # The default value if empty
class_default = UUID(int=0) class_default = UUID(int=0)
def to_python(self, value, timezone_in_use): def to_python(self, value, timezone_in_use):
# Convert valid values to UUID instance # Convert valid values to UUID instance
if isinstance(value, UUID): if isinstance(value, UUID):
return value return value
elif isinstance(value, string_types): elif isinstance(value, six.string_types):
return UUID(bytes=value) if len(value) == 16 else UUID(value) return UUID(bytes=value.encode('latin1')) if len(value) == 16 else UUID(value)
elif isinstance(value, (int, long)): elif isinstance(value, six.integer_types):
return UUID(int=value) return UUID(int=value)
elif isinstance(value, tuple): elif isinstance(value, tuple):
return UUID(fields=value) return UUID(fields=value)
else: else:
raise ValueError('Invalid value for UUIDField: %r' % value) raise ValueError('Invalid value for UUIDField: %r' % value)
def to_db_string(self, value, quote=True):
# The value was already converted by to_python, so it's a UUID instance
val = value.bytes
if six.PY3:
val = str(val, 'latin1')
return escape(val, quote)
def to_db_string(self, value, quote=True):
# The value was already converted by to_python, so it's a UUID instance
return escape(value.bytes, quote)
``` ```
Note that the latin-1 encoding is used as an identity encoding for converting between raw bytes and strings. This is required in Python 3, where `str` and `bytes` are different types.
--- ---
[<< Querysets](querysets.md) | [Table of Contents](toc.md) | [Table Engines >>](table_engines.md) [<< Querysets](querysets.md) | [Table of Contents](toc.md) | [Table Engines >>](table_engines.md)

View File

@ -1,6 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import unittest import unittest
from six import string_types import six
from uuid import UUID from uuid import UUID
from infi.clickhouse_orm.database import Database from infi.clickhouse_orm.database import Database
from infi.clickhouse_orm.fields import Field, Int16Field from infi.clickhouse_orm.fields import Field, Int16Field
@ -101,9 +101,9 @@ class UUIDField(Field):
# Convert valid values to UUID instance # Convert valid values to UUID instance
if isinstance(value, UUID): if isinstance(value, UUID):
return value return value
elif isinstance(value, string_types): elif isinstance(value, six.string_types):
return UUID(bytes=value) if len(value) == 16 else UUID(value) return UUID(bytes=value.encode('latin1')) if len(value) == 16 else UUID(value)
elif isinstance(value, (int, long)): elif isinstance(value, six.integer_types):
return UUID(int=value) return UUID(int=value)
elif isinstance(value, tuple): elif isinstance(value, tuple):
return UUID(fields=value) return UUID(fields=value)
@ -112,4 +112,8 @@ class UUIDField(Field):
def to_db_string(self, value, quote=True): def to_db_string(self, value, quote=True):
# The value was already converted by to_python, so it's a UUID instance # The value was already converted by to_python, so it's a UUID instance
return escape(value.bytes, quote) val = value.bytes
if six.PY3:
val = str(val, 'latin1')
return escape(val, quote)