Source code for quazy.db_field
from __future__ import annotations
import typing
from dataclasses import dataclass, field as data_field
if typing.TYPE_CHECKING:
from typing import *
from .db_table import DBTable
__all__ = ['DBField', 'UX', 'Unassigned']
class Unassigned:
pass
[docs]
@dataclass
class DBField:
"""Table field description class"""
_type: 'type[DBTable] | type' = data_field(default=None, init=False)
@property
def type(self):
"""field type class"""
return self._type
@type.setter
def type(self, value):
self._type = value
if self.ux:
self.ux.type = value
name: str = data_field(default='', init=False) #: field name in Python
column: str = '' #: field/column name in database
pk: bool = False #: is it a primary key?
cid: bool = False #: is it storage of table name for :ref:`derived tables <extendable>` ?
ref: bool = data_field(default=False, init=False) #: is it a foreign key (reference)?
body: bool = False #: is it a body field for :ref:`properties <properties>`?
property: bool = False #: is it a :ref:`properties <properties>` field?
required: bool = data_field(default=True, init=False) #: is a field not *null* ?
indexed: bool = False #: is it indexed for fast search ?
unique: bool = False #: is it unique ?
default: Union[Any, Callable[[DBTable], Any]] = Unassigned #: default value at Python level
default_sql: str = None #: default value at SQL level
reverse_name: str = None #: reverse name for reference fields
# many_field: bool = data_field(default=False, init=False)
ux: Optional[UX] = None #: UX/UI specific attributes
def __post_init__(self):
if self.default is not object or self.default_sql is not None:
self.required = False
def prepare(self, name: str):
self.name = name
if not self.column:
self.column = self.name
if not self.ux:
self.ux = UX(self.name, blank=not self.required, hidden=self.body or self.cid)
else:
if not self.ux.title:
self.ux.title = self.name
self.ux.field = self
def _dump_schema(self) -> dict[str, Any]:
from .db_types import db_type_name
res = {
'name': self.name,
'column': self.column,
'type': db_type_name(self.type) if not self.ref else self.type.__qualname__,
}
for col in 'pk cid ref body property required indexed unique'.split():
if val := getattr(self, col):
res[col] = val
if val := self.default_sql:
res['default_sql'] = val
return res
@classmethod
def _load_schema(cls, state: dict[str, Any]) -> DBField:
from .db_types import db_type_by_name
name = state.pop('name')
f_type = state.pop('type')
ref = state.pop('ref', False)
required = state.pop('required', False)
field = DBField(**state)
field.prepare(name)
field.ref = ref
field.required = required
field._type = db_type_by_name(f_type)
return field
[docs]
@dataclass
class UX:
"""Base class for visual representation of field, UI specific
This class contains the most common visual representation properties. It isn't used in Quazy directly, but it
helps to integrate with any GUI framework.
"""
_field: DBField = data_field(init=False)
name: str = '' #:
type: 'type' = None #:
title: str = '' #: user level title of a field
width: int = None #: integer size in GUI specific units (usually, letters amount)
choices: Mapping[str, Any] = None #: select value by user level title from dropdown list
blank: bool = False #: allow field unfilled
readonly: bool = False #: disable modifications of a field
multiline: bool = False #: enable multiline editor for a text field
hidden: bool = False #: hide field from UI
sortable: bool = True #: allows sorting by field values in tables
resizable: bool = True #: allows resizing column of field in tables
meta: dict[str, Any] = data_field(default_factory=dict) #: additional data for UI specific
def __post_init__(self):
if self.name and not self.title:
self.title = self.name
@property
def field(self) -> DBField:
"""reference to original field"""
return self._field
@field.setter
def field(self, field: DBField):
self._field = field
self.name = field.name
self.type = field.type
@dataclass
class DBManyField:
foreign_table: type[DBTable]
foreign_field: str | None = None
@dataclass
class DBManyToManyField(DBManyField):
middle_table: type[DBTable] | None = None