0

Use @dataclass in my project. Now I want to implement @dataclass for PATCH method(partial_update) and initialize only provided arguments.

For example:

@dataclass
class Person:
    id: int
    first_name: Optional[str]
    last_name: Optional[str]
    birthday: Optional[datetime.date]

and use it like:

person = Person(id=1, first_name ='Andrew')

so now person have only two arguments id and first_name(person.id, person.first_name )

Does someone have understanding how to implement such stuff? maybe is some wrapper for @dataclass?

P.S. Can't use

@dataclass
class Person:
    id: int
    first_name: Optional[str] = None
    last_name: Optional[str] = None
    birthday: Optional[datetime.date] = None

because it will provide None to not provided arguments and it will update fields in database with None.

I don't want these fields be updated in database, so I don't need them being initialized in dataclass.

  • Is a `Person` allowed to have `None` for any of these values, or does an instance of `Person` only represent a modification of a person, not the person itself? – chepner Mar 14 '23 at 16:52
  • I suspect you are looking for `functools.partial`, but I am not sure if you should have separate `Person` (all fields required) and `PersonUpdate` (any field is optional) classes. – chepner Mar 14 '23 at 16:53
  • Or, if what you really want is a `dict` that just *lacks* certain keys to construct the `PATCH` request. (Compare `{'first_name': 'bob'}` with a `Person` object that will have all four attributes no matter what value you assign to them.) – chepner Mar 14 '23 at 17:09
  • it represents modification – autoescape_on Mar 14 '23 at 20:40

1 Answers1

0

I would suggest to check out dataclass-wizard, to see if it can work for your use case. It supports skip_defaults argument when serializing a dataclass instance to JSON using to_dict, which behaves very similar to the builtin dataclasses.asdict.

You can use to_dict() method when saving modified fields (only values passed in to the __init__() constructor method) to database, as shown below.

Disclaimer: I am the creator and maintener of this library.

# Can be removed in Python 3.10+, as `X | Y` annotation syntax is supported OOTB
from __future__ import annotations

from dataclasses import dataclass
from datetime import date

from dataclass_wizard import JSONWizard


@dataclass
class Person(JSONWizard):

    # Custom config for (de)serializing a dataclass instance
    class _(JSONWizard.Meta):
        skip_defaults = True
        # optional: if you need (serialized) field names to be `snake_cased`
        # key_transform_with_dump = 'SNAKE'

    # REQUIRED
    id: int
    # (NOT) REQUIRED
    first_name: str | None = None
    last_name: str | None = None
    birthday: date | None = None


person = Person(id=1, first_name='Andrew')

# Print the `__repr__()` of class instance
print(repr(person))
print()

# Print the update data (for database)
print(person.to_dict())

Prints:

Person(id=1, first_name='Andrew', last_name=None, birthday=None)

{'id': 1, 'firstName': 'Andrew'}
rv.kvetch
  • 9,940
  • 3
  • 24
  • 53