Update django queries tutorial

This commit is contained in:
Griatch 2025-02-19 20:09:07 +01:00
parent d36c5d8fd5
commit c1794bb17e

View file

@ -174,14 +174,16 @@ will_transform = (
Character.objects Character.objects
.filter( .filter(
db_location__db_tags__db_key__iexact="moonlit", db_location__db_tags__db_key__iexact="moonlit",
db_attributes__db_key="lycanthropy", db_attributes__db_key__iexact="lycanthropy",
db_attributes__db_value__eq=2 db_attributes__db_value=2
) )
) )
``` ```
```{sidebar} Attributes vs database fields ```{sidebar} Attributes vs database fields
Don't confuse database fields with [Attributes](../../../Components/Attributes.md) you set via `obj.db.attr = 'foo'` or `obj.attributes.add()`. Attributes are custom database entities *linked* to an object. They are not separate fields *on* that object like `db_key` or `db_location` are. Don't confuse database fields with [Attributes](../../../Components/Attributes.md) you set via `obj.db.attr = 'foo'` or `obj.attributes.add()`. Attributes are custom database entities *linked* to an object. They are not separate fields *on* that object like `db_key` or `db_location` are.
While an Attribute's `db_key` is just a normal string, their `db_value` is in fact a serialized piece of data. This means that cannot query this with additional operators. So if you use e.g. `db_attributes__db_value__iexact=2`, you'll get an error. While Attributes are very flexible, this is their drawback - their stored value is not possible to directly query with advanced query methods beyond finding the exact match.
``` ```
- **Line 4** We want to find `Character`s, so we access `.objects` on the `Character` typeclass. - **Line 4** We want to find `Character`s, so we access `.objects` on the `Character` typeclass.
- We start to filter ... - We start to filter ...
@ -190,7 +192,7 @@ Don't confuse database fields with [Attributes](../../../Components/Attributes.m
that we can treat like an object for this purpose; it references all Tags on the location) that we can treat like an object for this purpose; it references all Tags on the location)
- ... and from those `Tags`, we looking for `Tags` whose `db_key` is "monlit" (non-case sensitive). - ... and from those `Tags`, we looking for `Tags` whose `db_key` is "monlit" (non-case sensitive).
- **Line 7**: ... We also want only Characters with `Attributes` whose `db_key` is exactly `"lycanthropy"` - **Line 7**: ... We also want only Characters with `Attributes` whose `db_key` is exactly `"lycanthropy"`
- **Line 8** :... at the same time as the `Attribute`'s `db_value` is exactly 2. - **Line 8** :... at the same time as the `Attribute`'s `db_value` is 2.
Running this query makes our newly lycanthropic Character appear in `will_transform` so we know to transform it. Success! Running this query makes our newly lycanthropic Character appear in `will_transform` so we know to transform it. Success!
@ -243,7 +245,7 @@ will_transform = (
Q(db_location__db_tags__db_key__iexact="moonlit") Q(db_location__db_tags__db_key__iexact="moonlit")
& ( & (
Q(db_attributes__db_key="lycanthropy", Q(db_attributes__db_key="lycanthropy",
db_attributes__db_value__eq=2) db_attributes__db_value=2)
| Q(db_tags__db_key__iexact="recently_bitten") | Q(db_tags__db_key__iexact="recently_bitten")
)) ))
.distinct() .distinct()
@ -256,7 +258,7 @@ That's quite compact. It may be easier to see what's going on if written this wa
from django.db.models import Q from django.db.models import Q
q_moonlit = Q(db_location__db_tags__db_key__iexact="moonlit") q_moonlit = Q(db_location__db_tags__db_key__iexact="moonlit")
q_lycanthropic = Q(db_attributes__db_key="lycanthropy", db_attributes__db_value__eq=2) q_lycanthropic = Q(db_attributes__db_key="lycanthropy", db_attributes__db_value=2)
q_recently_bitten = Q(db_tags__db_key__iexact="recently_bitten") q_recently_bitten = Q(db_tags__db_key__iexact="recently_bitten")
will_transform = ( will_transform = (