some cleanup and optimization
This commit is contained in:
@ -18,11 +18,15 @@ def is_field_nullable(
|
|||||||
pydantic_only: Optional[bool],
|
pydantic_only: Optional[bool],
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if nullable is None:
|
if nullable is None:
|
||||||
return default is not None or server_default is not None or pydantic_only
|
return (
|
||||||
|
default is not None
|
||||||
|
or server_default is not None
|
||||||
|
or (pydantic_only is not None and pydantic_only)
|
||||||
|
)
|
||||||
return nullable
|
return nullable
|
||||||
|
|
||||||
|
|
||||||
def is_auto_primary_key(primary_key: bool, autoincrement: bool):
|
def is_auto_primary_key(primary_key: bool, autoincrement: bool) -> bool:
|
||||||
return primary_key and autoincrement
|
return primary_key and autoincrement
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import inspect
|
|
||||||
import logging
|
import logging
|
||||||
import warnings
|
import warnings
|
||||||
from typing import Any, Dict, List, Optional, Set, TYPE_CHECKING, Tuple, Type, Union
|
from typing import Any, Dict, List, Optional, TYPE_CHECKING, Tuple, Type, Union
|
||||||
|
|
||||||
import databases
|
import databases
|
||||||
import pydantic
|
import pydantic
|
||||||
@ -12,11 +11,12 @@ from pydantic.utils import lenient_issubclass
|
|||||||
from sqlalchemy.sql.schema import ColumnCollectionConstraint
|
from sqlalchemy.sql.schema import ColumnCollectionConstraint
|
||||||
|
|
||||||
import ormar # noqa I100
|
import ormar # noqa I100
|
||||||
from ormar import ForeignKey, ModelDefinitionError, Integer # noqa I100
|
from ormar import ForeignKey, Integer, ModelDefinitionError # noqa I100
|
||||||
from ormar.fields import BaseField
|
from ormar.fields import BaseField
|
||||||
from ormar.fields.foreign_key import ForeignKeyField
|
from ormar.fields.foreign_key import ForeignKeyField
|
||||||
from ormar.fields.many_to_many import ManyToMany, ManyToManyField
|
from ormar.fields.many_to_many import ManyToMany, ManyToManyField
|
||||||
from ormar.fields.model_fields import ModelFieldFactory
|
from ormar.fields.model_fields import ModelFieldFactory
|
||||||
|
from ormar.models.quick_access_views import quick_access_set
|
||||||
from ormar.queryset import QuerySet
|
from ormar.queryset import QuerySet
|
||||||
from ormar.relations.alias_manager import AliasManager
|
from ormar.relations.alias_manager import AliasManager
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ def create_pydantic_field(
|
|||||||
def get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField":
|
def get_pydantic_field(field_name: str, model: Type["Model"]) -> "ModelField":
|
||||||
return ModelField(
|
return ModelField(
|
||||||
name=field_name,
|
name=field_name,
|
||||||
type_=model.Meta.model_fields[field_name].__type__,
|
type_=model.Meta.model_fields[field_name].__type__, # type: ignore
|
||||||
model_config=model.__config__,
|
model_config=model.__config__,
|
||||||
required=not model.Meta.model_fields[field_name].nullable,
|
required=not model.Meta.model_fields[field_name].nullable,
|
||||||
class_validators={},
|
class_validators={},
|
||||||
@ -316,10 +316,12 @@ def populate_choices_validators(model: Type["Model"]) -> None: # noqa CCR001
|
|||||||
validators = getattr(model, "__pre_root_validators__", [])
|
validators = getattr(model, "__pre_root_validators__", [])
|
||||||
if choices_validator not in validators:
|
if choices_validator not in validators:
|
||||||
validators.append(choices_validator)
|
validators.append(choices_validator)
|
||||||
setattr(model, "__pre_root_validators__", validators)
|
model.__pre_root_validators__ = validators
|
||||||
|
|
||||||
|
|
||||||
def populate_default_options_values(new_model: Type["Model"], model_fields: Dict):
|
def populate_default_options_values(
|
||||||
|
new_model: Type["Model"], model_fields: Dict
|
||||||
|
) -> None:
|
||||||
if not hasattr(new_model.Meta, "constraints"):
|
if not hasattr(new_model.Meta, "constraints"):
|
||||||
new_model.Meta.constraints = []
|
new_model.Meta.constraints = []
|
||||||
if not hasattr(new_model.Meta, "model_fields"):
|
if not hasattr(new_model.Meta, "model_fields"):
|
||||||
@ -331,59 +333,28 @@ def populate_default_options_values(new_model: Type["Model"], model_fields: Dict
|
|||||||
new_model.Meta.include_props_in_fields = False
|
new_model.Meta.include_props_in_fields = False
|
||||||
|
|
||||||
|
|
||||||
def add_cached_properties(new_model):
|
def add_cached_properties(new_model: Type["Model"]) -> None:
|
||||||
new_model._props = {
|
new_model._props = {
|
||||||
prop
|
prop
|
||||||
for prop in vars(new_model)
|
for prop in vars(new_model)
|
||||||
if isinstance(getattr(new_model, prop), property)
|
if isinstance(getattr(new_model, prop), property)
|
||||||
and prop not in ("__values__", "__fields__", "fields", "pk_column", "saved")
|
and prop not in ("__values__", "__fields__", "fields", "pk_column", "saved")
|
||||||
}
|
}
|
||||||
new_model._quick_access_fields = {
|
new_model._quick_access_fields = quick_access_set
|
||||||
"_orm_id",
|
|
||||||
"_orm_saved",
|
|
||||||
"_orm",
|
|
||||||
"_convert_json",
|
|
||||||
"__fields__",
|
|
||||||
"_related_names",
|
|
||||||
"_props",
|
|
||||||
"__class__",
|
|
||||||
"__dict__",
|
|
||||||
"__config__",
|
|
||||||
"_iter",
|
|
||||||
"_get_value",
|
|
||||||
"_is_conversion_to_json_needed",
|
|
||||||
"__fields_set__",
|
|
||||||
"_skip_ellipsis",
|
|
||||||
"_calculate_keys",
|
|
||||||
"dict",
|
|
||||||
"_update_excluded_with_related_not_required",
|
|
||||||
"_extract_nested_models",
|
|
||||||
"_get_related_not_excluded_fields",
|
|
||||||
"get_properties",
|
|
||||||
"resolve_relation_name",
|
|
||||||
"resolve_relation_field",
|
|
||||||
"set_save_status",
|
|
||||||
"__pre_root_validators__",
|
|
||||||
"__post_root_validators__",
|
|
||||||
"_extract_nested_models_from_list",
|
|
||||||
"get_name",
|
|
||||||
"extract_related_names",
|
|
||||||
"Meta",
|
|
||||||
}
|
|
||||||
new_model._related_names = None
|
new_model._related_names = None
|
||||||
new_model._pydantic_fields = {name for name in new_model.__fields__}
|
new_model._pydantic_fields = {name for name in new_model.__fields__}
|
||||||
|
|
||||||
|
|
||||||
def add_property_fields(new_model):
|
def add_property_fields(new_model: Type["Model"]) -> None:
|
||||||
if new_model.Meta.include_props_in_fields:
|
if new_model.Meta.include_props_in_fields:
|
||||||
for prop in new_model._props:
|
for prop in new_model._props:
|
||||||
field_type = getattr(new_model, prop).fget.__annotations__.get("return")
|
field_type = getattr(new_model, prop).fget.__annotations__.get("return")
|
||||||
new_model.Meta.model_fields[prop] = ModelFieldFactory(
|
new_model.Meta.model_fields[prop] = ModelFieldFactory( # type: ignore
|
||||||
nullable=True, pydantic_only=True
|
nullable=True, pydantic_only=True
|
||||||
)
|
)
|
||||||
new_model.__fields__[prop] = ModelField(
|
new_model.__fields__[prop] = ModelField(
|
||||||
name=prop,
|
name=prop,
|
||||||
type_=Optional[field_type] if field_type else Any,
|
type_=Optional[field_type] if field_type is not None else Any, # type: ignore
|
||||||
model_config=new_model.__config__,
|
model_config=new_model.__config__,
|
||||||
required=False,
|
required=False,
|
||||||
class_validators={},
|
class_validators={},
|
||||||
|
|||||||
@ -20,10 +20,6 @@ from typing import (
|
|||||||
from ormar.exceptions import ModelPersistenceError, RelationshipInstanceError
|
from ormar.exceptions import ModelPersistenceError, RelationshipInstanceError
|
||||||
from ormar.queryset.utils import translate_list_to_dict, update
|
from ormar.queryset.utils import translate_list_to_dict, update
|
||||||
|
|
||||||
try:
|
|
||||||
import orjson as json
|
|
||||||
except ImportError: # pragma: nocover
|
|
||||||
import json # type: ignore
|
|
||||||
|
|
||||||
import ormar # noqa: I100
|
import ormar # noqa: I100
|
||||||
from ormar.fields import BaseField
|
from ormar.fields import BaseField
|
||||||
@ -45,7 +41,7 @@ Field = TypeVar("Field", bound=BaseField)
|
|||||||
class ModelTableProxy:
|
class ModelTableProxy:
|
||||||
if TYPE_CHECKING: # pragma no cover
|
if TYPE_CHECKING: # pragma no cover
|
||||||
Meta: ModelMeta
|
Meta: ModelMeta
|
||||||
_related_names: Set
|
_related_names: Optional[Set]
|
||||||
_related_names_hash: Union[str, bytes]
|
_related_names_hash: Union[str, bytes]
|
||||||
pk: Any
|
pk: Any
|
||||||
get_name: Callable
|
get_name: Callable
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import json
|
import json
|
||||||
import uuid
|
import uuid
|
||||||
from collections import Counter
|
|
||||||
from typing import (
|
from typing import (
|
||||||
AbstractSet,
|
AbstractSet,
|
||||||
Any,
|
Any,
|
||||||
@ -66,9 +65,11 @@ class NewBaseModel(
|
|||||||
_orm_relationship_manager: AliasManager
|
_orm_relationship_manager: AliasManager
|
||||||
_orm: RelationsManager
|
_orm: RelationsManager
|
||||||
_orm_saved: bool
|
_orm_saved: bool
|
||||||
_related_names: Set
|
_related_names: Optional[Set]
|
||||||
_related_names_hash: str
|
_related_names_hash: str
|
||||||
_props: Set
|
_props: Set
|
||||||
|
_pydantic_fields: Set
|
||||||
|
_quick_access_fields: Set
|
||||||
Meta: ModelMeta
|
Meta: ModelMeta
|
||||||
|
|
||||||
# noinspection PyMissingConstructor
|
# noinspection PyMissingConstructor
|
||||||
@ -170,7 +171,7 @@ class NewBaseModel(
|
|||||||
value = object.__getattribute__(self, "__dict__").get(item, None)
|
value = object.__getattribute__(self, "__dict__").get(item, None)
|
||||||
value = object.__getattribute__(self, "_convert_json")(item, value, "loads")
|
value = object.__getattribute__(self, "_convert_json")(item, value, "loads")
|
||||||
return value
|
return value
|
||||||
return object.__getattribute__(self, item)
|
return object.__getattribute__(self, item) # pragma: no cover
|
||||||
|
|
||||||
def _extract_related_model_instead_of_field(
|
def _extract_related_model_instead_of_field(
|
||||||
self, item: str
|
self, item: str
|
||||||
@ -223,13 +224,13 @@ class NewBaseModel(
|
|||||||
@classmethod
|
@classmethod
|
||||||
def get_properties(
|
def get_properties(
|
||||||
cls, include: Union[Set, Dict, None], exclude: Union[Set, Dict, None]
|
cls, include: Union[Set, Dict, None], exclude: Union[Set, Dict, None]
|
||||||
) -> List[str]:
|
) -> Set[str]:
|
||||||
|
|
||||||
props = cls._props
|
props = cls._props
|
||||||
if include:
|
if include:
|
||||||
props = [prop for prop in props if prop in include]
|
props = {prop for prop in props if prop in include}
|
||||||
if exclude:
|
if exclude:
|
||||||
props = [prop for prop in props if prop not in exclude]
|
props = {prop for prop in props if prop not in exclude}
|
||||||
return props
|
return props
|
||||||
|
|
||||||
def _get_related_not_excluded_fields(
|
def _get_related_not_excluded_fields(
|
||||||
|
|||||||
62
ormar/models/quick_access_views.py
Normal file
62
ormar/models/quick_access_views.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
quick_access_set = {
|
||||||
|
"Config",
|
||||||
|
"Meta",
|
||||||
|
"__class__",
|
||||||
|
"__config__",
|
||||||
|
"__custom_root_type__",
|
||||||
|
"__dict__",
|
||||||
|
"__fields__",
|
||||||
|
"__fields_set__",
|
||||||
|
"__json_encoder__",
|
||||||
|
"__post_root_validators__",
|
||||||
|
"__pre_root_validators__",
|
||||||
|
"__same__",
|
||||||
|
"_calculate_keys",
|
||||||
|
"_convert_json",
|
||||||
|
"_extract_db_related_names",
|
||||||
|
"_extract_model_db_fields",
|
||||||
|
"_extract_nested_models",
|
||||||
|
"_extract_nested_models_from_list",
|
||||||
|
"_extract_own_model_fields",
|
||||||
|
"_get_related_not_excluded_fields",
|
||||||
|
"_get_value",
|
||||||
|
"_is_conversion_to_json_needed",
|
||||||
|
"_iter",
|
||||||
|
"_orm",
|
||||||
|
"_orm_id",
|
||||||
|
"_orm_saved",
|
||||||
|
"_props",
|
||||||
|
"_related_names",
|
||||||
|
"_skip_ellipsis",
|
||||||
|
"_update_and_follow",
|
||||||
|
"_update_excluded_with_related_not_required",
|
||||||
|
"copy",
|
||||||
|
"delete",
|
||||||
|
"dict",
|
||||||
|
"extract_related_names",
|
||||||
|
"from_dict",
|
||||||
|
"get_column_alias",
|
||||||
|
"get_column_name_from_alias",
|
||||||
|
"get_filtered_names_to_extract",
|
||||||
|
"get_name",
|
||||||
|
"get_properties",
|
||||||
|
"get_related_field_name",
|
||||||
|
"get_relation_model_id",
|
||||||
|
"json",
|
||||||
|
"keys",
|
||||||
|
"load",
|
||||||
|
"pk_column",
|
||||||
|
"pk_type",
|
||||||
|
"populate_default_values",
|
||||||
|
"remove",
|
||||||
|
"resolve_relation_field",
|
||||||
|
"resolve_relation_name",
|
||||||
|
"save",
|
||||||
|
"save_related",
|
||||||
|
"saved",
|
||||||
|
"set_save_status",
|
||||||
|
"translate_aliases_to_columns",
|
||||||
|
"translate_columns_to_aliases",
|
||||||
|
"update",
|
||||||
|
"upsert",
|
||||||
|
}
|
||||||
@ -76,7 +76,7 @@ class RandomModel(ormar.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def full_name(self):
|
def full_name(self):
|
||||||
return ' '.join([self.first_name, self.last_name])
|
return " ".join([self.first_name, self.last_name])
|
||||||
|
|
||||||
|
|
||||||
class User(ormar.Model):
|
class User(ormar.Model):
|
||||||
@ -199,7 +199,7 @@ def test_all_endpoints():
|
|||||||
"first_name",
|
"first_name",
|
||||||
"last_name",
|
"last_name",
|
||||||
"created_date",
|
"created_date",
|
||||||
"full_name"
|
"full_name",
|
||||||
]
|
]
|
||||||
assert response.json().get("full_name") == "John Test"
|
assert response.json().get("full_name") == "John Test"
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ def test_all_endpoints():
|
|||||||
"first_name",
|
"first_name",
|
||||||
"last_name",
|
"last_name",
|
||||||
"created_date",
|
"created_date",
|
||||||
"full_name"
|
"full_name",
|
||||||
]
|
]
|
||||||
|
|
||||||
RandomModel.Meta.include_props_in_dict = True
|
RandomModel.Meta.include_props_in_dict = True
|
||||||
@ -224,5 +224,5 @@ def test_all_endpoints():
|
|||||||
"first_name",
|
"first_name",
|
||||||
"last_name",
|
"last_name",
|
||||||
"created_date",
|
"created_date",
|
||||||
"full_name"
|
"full_name",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -26,9 +26,9 @@ class Album(ormar.Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name10(self) -> str:
|
def name10(self) -> str:
|
||||||
return self.name + '_10'
|
return self.name + "_10"
|
||||||
|
|
||||||
@validator('name')
|
@validator("name")
|
||||||
def test(cls, v):
|
def test(cls, v):
|
||||||
return v
|
return v
|
||||||
|
|
||||||
@ -46,30 +46,30 @@ def create_test_database():
|
|||||||
async def test_pydantic_only_fields():
|
async def test_pydantic_only_fields():
|
||||||
async with database:
|
async with database:
|
||||||
async with database.transaction(force_rollback=True):
|
async with database.transaction(force_rollback=True):
|
||||||
album = await Album.objects.create(name='Hitchcock')
|
album = await Album.objects.create(name="Hitchcock")
|
||||||
assert album.pk is not None
|
assert album.pk is not None
|
||||||
assert album.saved
|
assert album.saved
|
||||||
assert album.timestamp is None
|
assert album.timestamp is None
|
||||||
|
|
||||||
album = await Album.objects.exclude_fields('timestamp').get()
|
album = await Album.objects.exclude_fields("timestamp").get()
|
||||||
assert album.timestamp is None
|
assert album.timestamp is None
|
||||||
|
|
||||||
album = await Album.objects.fields({'name', 'timestamp'}).get()
|
album = await Album.objects.fields({"name", "timestamp"}).get()
|
||||||
assert album.timestamp is None
|
assert album.timestamp is None
|
||||||
|
|
||||||
test_dict = album.dict()
|
test_dict = album.dict()
|
||||||
assert 'timestamp' in test_dict
|
assert "timestamp" in test_dict
|
||||||
assert test_dict['timestamp'] is None
|
assert test_dict["timestamp"] is None
|
||||||
|
|
||||||
album.timestamp = datetime.datetime.now()
|
album.timestamp = datetime.datetime.now()
|
||||||
test_dict = album.dict()
|
test_dict = album.dict()
|
||||||
assert 'timestamp' in test_dict
|
assert "timestamp" in test_dict
|
||||||
assert test_dict['timestamp'] is not None
|
assert test_dict["timestamp"] is not None
|
||||||
assert test_dict.get('name10') == 'Hitchcock_10'
|
assert test_dict.get("name10") == "Hitchcock_10"
|
||||||
|
|
||||||
Album.Meta.include_props_in_dict = False
|
Album.Meta.include_props_in_dict = False
|
||||||
test_dict = album.dict()
|
test_dict = album.dict()
|
||||||
assert 'timestamp' in test_dict
|
assert "timestamp" in test_dict
|
||||||
assert test_dict['timestamp'] is not None
|
assert test_dict["timestamp"] is not None
|
||||||
# key is still there as now it's a field
|
# key is still there as now it's a field
|
||||||
assert test_dict['name10'] is None
|
assert test_dict["name10"] is None
|
||||||
|
|||||||
Reference in New Issue
Block a user