black, add additional tests with combined fields and exclude_fields, add aliases for column names to tests with fields and exclude_fields

This commit is contained in:
collerek
2020-11-11 10:10:30 +01:00
parent b1a30eaffc
commit 9350b929aa
15 changed files with 148 additions and 46 deletions

View File

@ -18,6 +18,7 @@ class BaseField(FieldInfo):
column_type: sqlalchemy.Column
constraints: List = []
name: str
alias: str
primary_key: bool
autoincrement: bool
@ -33,10 +34,14 @@ class BaseField(FieldInfo):
default: Any
server_default: Any
@classmethod
def get_alias(cls) -> str:
return cls.alias if cls.alias else cls.name
@classmethod
def is_valid_field_info_field(cls, field_name: str) -> bool:
return (
field_name not in ["default", "default_factory"]
field_name not in ["default", "default_factory", "alias"]
and not field_name.startswith("__")
and hasattr(cls, field_name)
)
@ -93,7 +98,7 @@ class BaseField(FieldInfo):
@classmethod
def get_column(cls, name: str) -> sqlalchemy.Column:
return sqlalchemy.Column(
cls.name or name,
cls.alias or name,
cls.column_type,
*cls.constraints,
primary_key=cls.primary_key,

View File

@ -50,6 +50,7 @@ def ForeignKey( # noqa CFQ002
virtual: bool = False,
onupdate: str = None,
ondelete: str = None,
**kwargs: Any,
) -> Any:
fk_string = to.Meta.tablename + "." + to.get_column_alias(to.Meta.pkname)
to_field = to.Meta.model_fields[to.Meta.pkname]
@ -62,7 +63,8 @@ def ForeignKey( # noqa CFQ002
namespace = dict(
__type__=__type__,
to=to,
name=name,
alias=name,
name=kwargs.pop("real_name", None),
nullable=nullable,
constraints=[
sqlalchemy.schema.ForeignKey(

View File

@ -31,6 +31,7 @@ def ManyToMany(
__type__=__type__,
to=to,
through=through,
alias=name,
name=name,
nullable=True,
unique=unique,

View File

@ -32,7 +32,8 @@ class ModelFieldFactory:
namespace = dict(
__type__=cls._type,
name=kwargs.pop("name", None),
alias=kwargs.pop("name", None),
name=None,
primary_key=kwargs.pop("primary_key", False),
default=default,
server_default=server_default,

View File

@ -88,7 +88,7 @@ def register_reverse_model_fields(
adjust_through_many_to_many_model(model, child, model_field)
else:
model.Meta.model_fields[child_model_name] = ForeignKey(
child, name=child_model_name, virtual=True
child, real_name=child_model_name, virtual=True
)
@ -96,10 +96,10 @@ def adjust_through_many_to_many_model(
model: Type["Model"], child: Type["Model"], model_field: Type[ManyToManyField]
) -> None:
model_field.through.Meta.model_fields[model.get_name()] = ForeignKey(
model, name=model.get_name(), ondelete="CASCADE"
model, real_name=model.get_name(), ondelete="CASCADE"
)
model_field.through.Meta.model_fields[child.get_name()] = ForeignKey(
child, name=child.get_name(), ondelete="CASCADE"
child, real_name=child.get_name(), ondelete="CASCADE"
)
create_and_append_m2m_fk(model, model_field)
@ -166,7 +166,7 @@ def sqlalchemy_columns_from_model_fields(
and not field.virtual
and not issubclass(field, ManyToManyField)
):
columns.append(field.get_column(field_name))
columns.append(field.get_column(field.get_alias()))
register_relation_in_alias_manager(table_name, field)
return pkname, columns
@ -211,8 +211,7 @@ def populate_pydantic_default_values(attrs: Dict) -> Tuple[Dict, Dict]:
{k: v for k, v in attrs.items() if lenient_issubclass(v, BaseField)}
)
for field_name, field in potential_fields.items():
if field.name is None:
field.name = field_name
field.name = field_name
attrs = populate_default_pydantic_field_value(field, field_name, attrs)
model_fields[field_name] = field
attrs["__annotations__"][field_name] = field.__type__

View File

@ -164,8 +164,11 @@ class Model(NewBaseModel):
if not self.pk and self.Meta.model_fields[self.Meta.pkname].autoincrement:
self_fields.pop(self.Meta.pkname, None)
self_fields = self.populate_default_values(self_fields)
self_fields = self.translate_columns_to_aliases(self_fields)
expr = self.Meta.table.insert()
expr = expr.values(**self_fields)
item_id = await self.Meta.database.execute(expr)
if item_id: # postgress does not return id if it's already there
setattr(self, self.Meta.pkname, item_id)

View File

@ -65,14 +65,14 @@ class ModelTableProxy:
@classmethod
def get_column_alias(cls, field_name: str) -> str:
field = cls.Meta.model_fields.get(field_name)
if field and field.name is not None and field.name != field_name:
return field.name
if field and field.alias is not None:
return field.alias
return field_name
@classmethod
def get_column_name_from_alias(cls, alias: str) -> str:
for field_name, field in cls.Meta.model_fields.items():
if field and field.name == alias:
if field and field.alias == alias:
return field_name
return alias # if not found it's not an alias but actual name
@ -164,19 +164,15 @@ class ModelTableProxy:
@classmethod
def translate_columns_to_aliases(cls, new_kwargs: Dict) -> Dict:
for field_name, field in cls.Meta.model_fields.items():
if (
field_name in new_kwargs
and field.name is not None
and field.name != field_name
):
new_kwargs[field.name] = new_kwargs.pop(field_name)
if field_name in new_kwargs:
new_kwargs[field.get_alias()] = new_kwargs.pop(field_name)
return new_kwargs
@classmethod
def translate_aliases_to_columns(cls, new_kwargs: Dict) -> Dict:
for field_name, field in cls.Meta.model_fields.items():
if field.name in new_kwargs and field.name != field_name:
new_kwargs[field_name] = new_kwargs.pop(field.name)
if field.alias and field.alias in new_kwargs:
new_kwargs[field_name] = new_kwargs.pop(field.alias)
return new_kwargs
@classmethod

View File

@ -138,9 +138,9 @@ class NewBaseModel(pydantic.BaseModel, ModelTableProxy, metaclass=ModelMetaclass
def _extract_related_model_instead_of_field(
self, item: str
) -> Optional[Union["T", Sequence["T"]]]:
alias = self.get_column_alias(item)
if alias in self._orm:
return self._orm.get(alias)
# alias = self.get_column_alias(item)
if item in self._orm:
return self._orm.get(item)
return None # pragma no cover
def __eq__(self, other: object) -> bool:

View File

@ -120,7 +120,13 @@ class SqlJoin:
pkname_alias = model_cls.get_column_alias(model_cls.Meta.pkname)
if not is_multi:
self.get_order_bys(alias, to_table, pkname_alias, part)
self.get_order_bys(
alias=alias,
to_table=to_table,
pkname_alias=pkname_alias,
part=part,
model_cls=model_cls,
)
self_related_fields = model_cls.own_table_columns(
model_cls, self.fields, self.exclude_fields, nested=True,
@ -150,8 +156,21 @@ class SqlJoin:
condition[-2] == part or condition[-2][1:] == part
)
def set_aliased_order_by(
self, condition: List[str], alias: str, to_table: str, model_cls: Type["Model"],
) -> None:
direction = f"{'desc' if condition[0][0] == '-' else ''}"
column_alias = model_cls.get_column_alias(condition[-1])
order = text(f"{alias}_{to_table}.{column_alias} {direction}")
self.sorted_orders["__".join(condition)] = order
def get_order_bys( # noqa: CCR001
self, alias: str, to_table: str, pkname_alias: str, part: str
self,
alias: str,
to_table: str,
pkname_alias: str,
part: str,
model_cls: Type["Model"],
) -> None:
if self.order_columns:
split_order_columns = [
@ -159,9 +178,12 @@ class SqlJoin:
]
for condition in split_order_columns:
if self._check_if_condition_apply(condition, part):
direction = f"{'desc' if condition[0][0] == '-' else ''}"
order = text(f"{alias}_{to_table}.{condition[-1]} {direction}")
self.sorted_orders["__".join(condition)] = order
self.set_aliased_order_by(
condition=condition,
alias=alias,
to_table=to_table,
model_cls=model_cls,
)
else:
order = text(f"{alias}_{to_table}.{pkname_alias}")
self.sorted_orders[f"{to_table}.{pkname_alias}"] = order

View File

@ -54,14 +54,17 @@ class Query:
pkname_alias = self.model_cls.get_column_alias(self.model_cls.Meta.pkname)
return f"{self.table.name}.{pkname_alias}"
def alias(self, name: str) -> str:
return self.model_cls.get_column_alias(name)
def apply_order_bys_for_primary_model(self) -> None: # noqa: CCR001
if self.order_columns:
for clause in self.order_columns:
if "__" not in clause:
clause = (
text(f"{clause[1:]} desc")
text(f"{self.alias(clause[1:])} desc")
if clause.startswith("-")
else text(clause)
else text(self.alias(clause))
)
self.sorted_orders[clause] = clause
else:

View File

@ -337,15 +337,15 @@ class QuerySet:
expr = self.table.insert()
expr = expr.values(**new_kwargs)
instance = self.model(**kwargs)
pk = await self.database.execute(expr)
pk_name = self.model.get_column_alias(self.model_meta.pkname)
if pk_name not in kwargs and pk_name in new_kwargs:
instance.pk = new_kwargs[self.model_meta.pkname]
kwargs["pk"] = new_kwargs[self.model_meta.pkname]
if pk and isinstance(pk, self.model.pk_type()):
setattr(instance, self.model_meta.pkname, pk)
kwargs[self.model_meta.pkname] = pk
instance = self.model(**kwargs)
# refresh server side defaults
instance = await instance.load()