add tests for cross model forward references, add docs for processing forwardrefs, wip on refactoring queries into separate pages based on functionality
This commit is contained in:
126
docs/queries/select-columns.md
Normal file
126
docs/queries/select-columns.md
Normal file
@ -0,0 +1,126 @@
|
||||
# Selecting subset of columns
|
||||
|
||||
* `fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
* `exclude_fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
|
||||
## fields
|
||||
|
||||
`fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
|
||||
With `fields()` you can select subset of model columns to limit the data load.
|
||||
|
||||
!!!note Note that `fields()` and `exclude_fields()` works both for main models (on
|
||||
normal queries like `get`, `all` etc.)
|
||||
as well as `select_related` and `prefetch_related` models (with nested notation).
|
||||
|
||||
Given a sample data like following:
|
||||
|
||||
```python
|
||||
--8 < -- "../docs_src/queries/docs006.py"
|
||||
```
|
||||
|
||||
You can select specified fields by passing a `str, List[str], Set[str] or dict` with
|
||||
nested definition.
|
||||
|
||||
To include related models use
|
||||
notation `{related_name}__{column}[__{optional_next} etc.]`.
|
||||
|
||||
```python hl_lines="1"
|
||||
all_cars = await Car.objects.select_related('manufacturer').fields(['id', 'name', 'manufacturer__name']).all()
|
||||
for car in all_cars:
|
||||
# excluded columns will yield None
|
||||
assert all(getattr(car, x) is None for x in ['year', 'gearbox_type', 'gears', 'aircon_type'])
|
||||
# included column on related models will be available, pk column is always included
|
||||
# even if you do not include it in fields list
|
||||
assert car.manufacturer.name == 'Toyota'
|
||||
# also in the nested related models - you cannot exclude pk - it's always auto added
|
||||
assert car.manufacturer.founded is None
|
||||
```
|
||||
|
||||
`fields()` can be called several times, building up the columns to select.
|
||||
|
||||
If you include related models into `select_related()` call but you won't specify columns
|
||||
for those models in fields
|
||||
|
||||
- implies a list of all fields for those nested models.
|
||||
|
||||
```python hl_lines="1"
|
||||
all_cars = await Car.objects.select_related('manufacturer').fields('id').fields(
|
||||
['name']).all()
|
||||
# all fiels from company model are selected
|
||||
assert all_cars[0].manufacturer.name == 'Toyota'
|
||||
assert all_cars[0].manufacturer.founded == 1937
|
||||
```
|
||||
|
||||
!!!warning Mandatory fields cannot be excluded as it will raise `ValidationError`, to
|
||||
exclude a field it has to be nullable.
|
||||
|
||||
You cannot exclude mandatory model columns - `manufacturer__name` in this example.
|
||||
|
||||
```python
|
||||
await Car.objects.select_related('manufacturer').fields(
|
||||
['id', 'name', 'manufacturer__founded']).all()
|
||||
# will raise pydantic ValidationError as company.name is required
|
||||
```
|
||||
|
||||
!!!tip Pk column cannot be excluded - it's always auto added even if not explicitly
|
||||
included.
|
||||
|
||||
You can also pass fields to include as dictionary or set.
|
||||
|
||||
To mark a field as included in a dictionary use it's name as key and ellipsis as value.
|
||||
|
||||
To traverse nested models use nested dictionaries.
|
||||
|
||||
To include fields at last level instead of nested dictionary a set can be used.
|
||||
|
||||
To include whole nested model specify model related field name and ellipsis.
|
||||
|
||||
Below you can see examples that are equivalent:
|
||||
|
||||
```python
|
||||
--8 < -- "../docs_src/queries/docs009.py"
|
||||
```
|
||||
|
||||
!!!note All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
|
||||
So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained.
|
||||
|
||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||
|
||||
## exclude_fields
|
||||
|
||||
`exclude_fields(columns: Union[List, str, set, dict]) -> QuerySet`
|
||||
|
||||
With `exclude_fields()` you can select subset of model columns that will be excluded to
|
||||
limit the data load.
|
||||
|
||||
It's the opposite of `fields()` method so check documentation above to see what options
|
||||
are available.
|
||||
|
||||
Especially check above how you can pass also nested dictionaries and sets as a mask to
|
||||
exclude fields from whole hierarchy.
|
||||
|
||||
!!!note Note that `fields()` and `exclude_fields()` works both for main models (on
|
||||
normal queries like `get`, `all` etc.)
|
||||
as well as `select_related` and `prefetch_related` models (with nested notation).
|
||||
|
||||
Below you can find few simple examples:
|
||||
|
||||
```python hl_lines="47 48 60 61 67"
|
||||
--8<-- "../docs_src/queries/docs008.py"
|
||||
```
|
||||
|
||||
!!!warning Mandatory fields cannot be excluded as it will raise `ValidationError`, to
|
||||
exclude a field it has to be nullable.
|
||||
|
||||
!!!tip Pk column cannot be excluded - it's always auto added even if explicitly
|
||||
excluded.
|
||||
|
||||
!!!note All methods that do not return the rows explicitly returns a QueySet instance so
|
||||
you can chain them together
|
||||
|
||||
So operations like `filter()`, `select_related()`, `limit()` and `offset()` etc. can be chained.
|
||||
|
||||
Something like `Track.object.select_related("album").filter(album__name="Malibu").offset(1).limit(1).all()`
|
||||
Reference in New Issue
Block a user