Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add InertiaMeta for automatic serialization #66

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,30 @@ def inertia_share(get_response):
return get_response(request)
return middleware
```
### Prop Serialization

Unlike Rails and Laravel, Django does not handle converting objects to JSON by default so Inertia Django offers two different ways to handle prop serialization.

#### InertiaJsonEncoder

The default behavior is via the InertiaJsonEncoder. The InertiaJsonEncoder is a barebones implementation
that extends the DjangoJSONEncoder with the ability to handle QuerySets and models. Models are JSON encoded
via Django's `model_to_dict` method excluding the field `password`. This method has limitations though, as
`model_to_dict` does not include fields where editable=False (such as automatic timestamps).

#### InertiaMeta

Starting in Inertia Django v1.2, Inertia Django supports an InertiaMeta nested class. Similar to Django Rest Framework's serializers, any class (not just models) can contain an InertiaMeta class which can specify how that class should be serialized to JSON. At this time, in only supports `fields`, but this may be extended in future versions.

```python
class User(models.Model):
name = models.CharField(max_length=255)
password = models.CharField(max_length=255)
created_at = models.DateField(auto_now_add=True)

class InertiaMeta:
fields = ('name', 'created_at')
```

### External Redirects

Expand Down
21 changes: 20 additions & 1 deletion inertia/tests/test_encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from django.test import TestCase

from inertia.tests.testapp.models import User
from inertia.tests.testapp.models import Sport, User
from inertia.utils import InertiaJsonEncoder


Expand Down Expand Up @@ -31,6 +31,25 @@ def test_it_handles_models_with_dates_and_removes_passwords(self):
self.encode(user),
)

def test_it_handles_inertia_meta_fields(self):
sport = Sport(
id=3,
name="Hockey",
season="Winter",
created_at=datetime(2022, 10, 31, 10, 13, 1),
)

self.assertEqual(
dumps(
{
"id": 3,
"name": "Hockey",
"created_at": "2022-10-31T10:13:01",
}
),
self.encode(sport),
)

def test_it_handles_querysets(self):
User(
name="Brandon",
Expand Down
10 changes: 10 additions & 0 deletions inertia/tests/testapp/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,13 @@ class User(models.Model):
password = models.CharField(max_length=255)
birthdate = models.DateField()
registered_at = models.DateTimeField()
created_at = models.DateField(auto_now_add=True)


class Sport(models.Model):
name = models.CharField(max_length=255)
season = models.CharField(max_length=255)
created_at = models.DateField(auto_now_add=True)

class InertiaMeta:
fields = ("id", "name", "created_at")
6 changes: 6 additions & 0 deletions inertia/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ def model_to_dict(model):

class InertiaJsonEncoder(DjangoJSONEncoder):
def default(self, value):
if hasattr(value.__class__, "InertiaMeta"):
return {
field: getattr(value, field)
for field in value.__class__.InertiaMeta.fields
}

if isinstance(value, models.Model):
return model_to_dict(value)

Expand Down
Loading