change limit/offset with select related to be applied on a subquery and limit only main model query
This commit is contained in:
@ -9,7 +9,7 @@ Out of various types of ORM models inheritance `ormar` currently supports two of
|
||||
|
||||
The short summary of different types of inheritance is:
|
||||
|
||||
* **Mixins [SUPPORTED]** - don't even subclass `ormar.Model`, just define fields that are later used on several different models (like `created_date` and `updated_date` on each model), only actual models create tables but those fields from mixins are added
|
||||
* **Mixins [SUPPORTED]** - don't subclass `ormar.Model`, just define fields that are later used on different models (like `created_date` and `updated_date` on each model), only actual models create tables, but those fields from mixins are added
|
||||
* **Concrete table inheritance [SUPPORTED]** - means that parent is marked as abstract and each child has it's own table with columns from parent and own child columns, kind of similar to Mixins but parent also is a Model
|
||||
* **Single table inheritance [NOT SUPPORTED]** - means that only one table is created with fields that are combination/sum of the parent and all children models but child models use only subset of column in db (all parent and own ones, skipping the other children ones)
|
||||
* **Multi/ Joined table inheritance [NOT SUPPORTED]** - means that part of the columns is saved on parent model and part is saved on child model that are connected to each other by kind of one to one relation and under the hood you operate on two models at once
|
||||
@ -83,7 +83,7 @@ class AuditModel(ormar.Model):
|
||||
created_by: str = ormar.String(max_length=100)
|
||||
updated_by: str = ormar.String(max_length=100, default="Sam")
|
||||
|
||||
# but if you provide it it will be inherited
|
||||
# but if you provide it it will be inherited - DRY (Don't Repeat Yourself) in action
|
||||
class DateFieldsModel(ormar.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
@ -117,3 +117,69 @@ Of course apart from that all fields from base classes are combined and created
|
||||
So in example above `Category` cannot declare it's own `created_date` as this filed will be inherited from `DateFieldsMixins`.
|
||||
|
||||
If you try to the `ModelDefinitionError` will be raised.
|
||||
|
||||
## Redefining fields in subclasses
|
||||
|
||||
Note that you can redefine previously created fields like in normal python class inheritance.
|
||||
|
||||
Whenever you define a field with same name and new definition it will completely replace the previously defined one.
|
||||
|
||||
```python
|
||||
# base class
|
||||
class DateFieldsModel(ormar.Model):
|
||||
class Meta:
|
||||
abstract = True
|
||||
metadata = metadata
|
||||
database = db
|
||||
# note that UniqueColumns need sqlalchemy db columns names not the ormar one
|
||||
constraints = [ormar.UniqueColumns("creation_date", "modification_date")]
|
||||
|
||||
created_date: datetime.datetime = ormar.DateTime(
|
||||
default=datetime.datetime.now, name="creation_date"
|
||||
)
|
||||
updated_date: datetime.datetime = ormar.DateTime(
|
||||
default=datetime.datetime.now, name="modification_date"
|
||||
)
|
||||
|
||||
class RedefinedField(DateFieldsModel):
|
||||
class Meta(ormar.ModelMeta):
|
||||
tablename = "redefines"
|
||||
metadata = metadata
|
||||
database = db
|
||||
|
||||
id: int = ormar.Integer(primary_key=True)
|
||||
# here the created_date is replaced by the String field
|
||||
created_date: str = ormar.String(max_length=200, name="creation_date")
|
||||
|
||||
|
||||
# you can verify that the final field is correctly declared and created
|
||||
changed_field = RedefinedField.Meta.model_fields["created_date"]
|
||||
assert changed_field.default is None
|
||||
assert changed_field.alias == "creation_date"
|
||||
assert any(x.name == "creation_date" for x in RedefinedField.Meta.table.columns)
|
||||
assert isinstance(
|
||||
RedefinedField.Meta.table.columns["creation_date"].type,
|
||||
sqlalchemy.sql.sqltypes.String,
|
||||
)
|
||||
```
|
||||
|
||||
!!!warning
|
||||
If you declare `UniqueColumns` constraint with column names, the final model **has to have**
|
||||
a column with the same name declared. Otherwise, the `ModelDefinitionError` will be raised.
|
||||
|
||||
So in example above if you do not provide `name` for `created_date` in `RedefinedField` model
|
||||
ormar will complain.
|
||||
|
||||
`created_date: str = ormar.String(max_length=200) # exception`
|
||||
|
||||
`created_date: str = ormar.String(max_length=200, name="creation_date2") # exception`
|
||||
|
||||
|
||||
## Relations in inheritance
|
||||
|
||||
You can declare relations in every step of inheritance, so both in parent and child classes.
|
||||
|
||||
But you always need to be aware of related_name parameter, that has to be unique across a model,
|
||||
when you define multiple child classes that inherit the same relation.
|
||||
|
||||
|
||||
|
||||
@ -1,3 +1,19 @@
|
||||
# 0.8.0
|
||||
|
||||
* **Breaking:** removing parent from child side in reverse ForeignKey relation now requires passing a relation `name`,
|
||||
as the same model can be registered multiple times and ormar needs to know from which relation on the parent you want to remove the child.
|
||||
* **Breaking:** applying limit and offset with select related is by default applied only on the main table before the join -> meaning that not the total
|
||||
number of rows is limited but just main models (first one in the query, the one to used to construct it)
|
||||
* **Breaking:** issuing `first()` now fetches the first row ordered by the primary key asc (so first one inserted (can be different for non number primary keys - i.e. alphabetical order of string)) and also can be used with `prefetch_related`
|
||||
* **Breaking:** issuing `get()` **without any filters** now fetches the first row ordered by the primary key desc (so should be last one inserted (can be different for non number primary keys - i.e. alphabetical order of string))
|
||||
* Introduce inheritance, for now two types of inheritance are possible:
|
||||
* **Mixins** - don't subclass `ormar.Model`, just define fields that are later used on different models (like `created_date` and `updated_date` on each model), only actual models create tables, but those fields from mixins are added
|
||||
* **Concrete table inheritance** - means that parent is marked as abstract and each child has its own table with columns from the parent and own child columns, kind of similar to Mixins but parent also is a Model
|
||||
* To read more check the docs on models -> inheritance section.
|
||||
* Fix bug in order_by for primary model order bys
|
||||
* Fix in `prefetch_query` for multiple related_names for the same model.
|
||||
* Split and cleanup in docs.
|
||||
|
||||
# 0.7.5
|
||||
|
||||
* Fix for wrong relation column name in many_to_many relation joins (fix [#73][#73])
|
||||
|
||||
Reference in New Issue
Block a user