From 8cd0a80faaa551fb669370adfab6d5eda34827ae Mon Sep 17 00:00:00 2001 From: Steve Lacey Date: Mon, 15 Nov 2021 15:53:13 +0700 Subject: [PATCH] =?UTF-8?q?Marshmallow=20serialization=20=F0=9F=94=A5?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Pipfile.lock | 304 +++++++++++++++++++++++-------------------- setup.py | 1 + tests/models.py | 19 --- tests/serializers.py | 65 +++++---- worf/fields.py | 11 ++ worf/serializers.py | 47 +++++-- 6 files changed, 256 insertions(+), 191 deletions(-) create mode 100644 worf/fields.py diff --git a/Pipfile.lock b/Pipfile.lock index f1370b5..8385510 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -33,11 +33,11 @@ }, "django": { "hashes": [ - "sha256:42573831292029639b798fe4d3812996bfe4ff3275f04566da90764daec011a5", - "sha256:f6d2c4069c9b9bfac03bedff927ea1f9e0d29e34525cec8a68fd28eb2a8df7af" + "sha256:51284300f1522ffcdb07ccbdf676a307c6678659e1284f0618e5a774127a6a08", + "sha256:e22c9266da3eec7827737cde57694d7db801fedac938d252bf27377cec06ed1b" ], "markers": "python_version >= '3.6'", - "version": "==3.2.8" + "version": "==3.2.9" }, "django-url-filter": { "hashes": [ @@ -53,6 +53,14 @@ ], "version": "==0.0.3" }, + "marshmallow": { + "hashes": [ + "sha256:04438610bc6dadbdddb22a4a55bcc7f6f8099e69580b2e67f5a681933a1f4400", + "sha256:4c05c1684e0e97fe779c62b91878f173b937fe097b356cd82f793464f5bc6138" + ], + "markers": "python_version >= '3.6'", + "version": "==3.14.1" + }, "pytz": { "hashes": [ "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", @@ -226,42 +234,56 @@ "toml" ], "hashes": [ - "sha256:04560539c19ec26995ecfb3d9307ff154fbb9a172cb57e3b3cfc4ced673103d1", - "sha256:1549e1d08ce38259de2bc3e9a0d5f3642ff4a8f500ffc1b2df73fd621a6cdfc0", - "sha256:1db67c497688fd4ba85b373b37cc52c50d437fd7267520ecd77bddbd89ea22c9", - "sha256:30922626ce6f7a5a30bdba984ad21021529d3d05a68b4f71ea3b16bda35b8895", - "sha256:36e9040a43d2017f2787b28d365a4bb33fcd792c7ff46a047a04094dc0e2a30d", - "sha256:381d773d896cc7f8ba4ff3b92dee4ed740fb88dfe33b6e42efc5e8ab6dfa1cfe", - "sha256:3bbda1b550e70fa6ac40533d3f23acd4f4e9cb4e6e77251ce77fdf41b3309fb2", - "sha256:3be1206dc09fb6298de3fce70593e27436862331a85daee36270b6d0e1c251c4", - "sha256:424c44f65e8be58b54e2b0bd1515e434b940679624b1b72726147cfc6a9fc7ce", - "sha256:4b34ae4f51bbfa5f96b758b55a163d502be3dcb24f505d0227858c2b3f94f5b9", - "sha256:4e28d2a195c533b58fc94a12826f4431726d8eb029ac21d874345f943530c122", - "sha256:53a294dc53cfb39c74758edaa6305193fb4258a30b1f6af24b360a6c8bd0ffa7", - "sha256:60e51a3dd55540bec686d7fff61b05048ca31e804c1f32cbb44533e6372d9cc3", - "sha256:61b598cbdbaae22d9e34e3f675997194342f866bb1d781da5d0be54783dce1ff", - "sha256:6807947a09510dc31fa86f43595bf3a14017cd60bf633cc746d52141bfa6b149", - "sha256:6a6a9409223a27d5ef3cca57dd7cd4dfcb64aadf2fad5c3b787830ac9223e01a", - "sha256:7092eab374346121805fb637572483270324407bf150c30a3b161fc0c4ca5164", - "sha256:77b1da5767ed2f44611bc9bc019bc93c03fa495728ec389759b6e9e5039ac6b1", - "sha256:8251b37be1f2cd9c0e5ccd9ae0380909c24d2a5ed2162a41fcdbafaf59a85ebd", - "sha256:9f1627e162e3864a596486774876415a7410021f4b67fd2d9efdf93ade681afc", - "sha256:a1b73c7c4d2a42b9d37dd43199c5711d91424ff3c6c22681bc132db4a4afec6f", - "sha256:a82d79586a0a4f5fd1cf153e647464ced402938fbccb3ffc358c7babd4da1dd9", - "sha256:abbff240f77347d17306d3201e14431519bf64495648ca5a49571f988f88dee9", - "sha256:ad9b8c1206ae41d46ec7380b78ba735ebb77758a650643e841dd3894966c31d0", - "sha256:bbffde2a68398682623d9dd8c0ca3f46fda074709b26fcf08ae7a4c431a6ab2d", - "sha256:bcae10fccb27ca2a5f456bf64d84110a5a74144be3136a5e598f9d9fb48c0caa", - "sha256:c9cd3828bbe1a40070c11fe16a51df733fd2f0cb0d745fb83b7b5c1f05967df7", - "sha256:cd1cf1deb3d5544bd942356364a2fdc8959bad2b6cf6eb17f47d301ea34ae822", - "sha256:d036dc1ed8e1388e995833c62325df3f996675779541f682677efc6af71e96cc", - "sha256:db42baa892cba723326284490283a68d4de516bfb5aaba369b4e3b2787a778b7", - "sha256:e4fb7ced4d9dec77d6cf533acfbf8e1415fe799430366affb18d69ee8a3c6330", - "sha256:e7a0b42db2a47ecb488cde14e0f6c7679a2c5a9f44814393b162ff6397fcdfbb", - "sha256:f2f184bf38e74f152eed7f87e345b51f3ab0b703842f447c22efe35e59942c24" + "sha256:046647b96969fda1ae0605f61288635209dd69dcd27ba3ec0bf5148bc157f954", + "sha256:06d009e8a29483cbc0520665bc46035ffe9ae0e7484a49f9782c2a716e37d0a0", + "sha256:0cde7d9fe2fb55ff68ebe7fb319ef188e9b88e0a3d1c9c5db7dd829cd93d2193", + "sha256:1de9c6f5039ee2b1860b7bad2c7bc3651fbeb9368e4c4d93e98a76358cdcb052", + "sha256:24ed38ec86754c4d5a706fbd5b52b057c3df87901a8610d7e5642a08ec07087e", + "sha256:27a3df08a855522dfef8b8635f58bab81341b2fb5f447819bc252da3aa4cf44c", + "sha256:310c40bed6b626fd1f463e5a83dba19a61c4eb74e1ac0d07d454ebbdf9047e9d", + "sha256:3348865798c077c695cae00da0924136bb5cc501f236cfd6b6d9f7a3c94e0ec4", + "sha256:35b246ae3a2c042dc8f410c94bcb9754b18179cdb81ff9477a9089dbc9ecc186", + "sha256:3f546f48d5d80a90a266769aa613bc0719cb3e9c2ef3529d53f463996dd15a9d", + "sha256:586d38dfc7da4a87f5816b203ff06dd7c1bb5b16211ccaa0e9788a8da2b93696", + "sha256:5d3855d5d26292539861f5ced2ed042fc2aa33a12f80e487053aed3bcb6ced13", + "sha256:610c0ba11da8de3a753dc4b1f71894f9f9debfdde6559599f303286e70aeb0c2", + "sha256:62646d98cf0381ffda301a816d6ac6c35fc97aa81b09c4c52d66a15c4bef9d7c", + "sha256:66af99c7f7b64d050d37e795baadf515b4561124f25aae6e1baa482438ecc388", + "sha256:675adb3b3380967806b3cbb9c5b00ceb29b1c472692100a338730c1d3e59c8b9", + "sha256:6e5a8c947a2a89c56655ecbb789458a3a8e3b0cbf4c04250331df8f647b3de59", + "sha256:7a39590d1e6acf6a3c435c5d233f72f5d43b585f5be834cff1f21fec4afda225", + "sha256:80cb70264e9a1d04b519cdba3cd0dc42847bf8e982a4d55c769b9b0ee7cdce1e", + "sha256:82fdcb64bf08aa5db881db061d96db102c77397a570fbc112e21c48a4d9cb31b", + "sha256:8492d37acdc07a6eac6489f6c1954026f2260a85a4c2bb1e343fe3d35f5ee21a", + "sha256:94f558f8555e79c48c422045f252ef41eb43becdd945e9c775b45ebfc0cbd78f", + "sha256:958ac66272ff20e63d818627216e3d7412fdf68a2d25787b89a5c6f1eb7fdd93", + "sha256:95a58336aa111af54baa451c33266a8774780242cab3704b7698d5e514840758", + "sha256:96129e41405887a53a9cc564f960d7f853cc63d178f3a182fdd302e4cab2745b", + "sha256:97ef6e9119bd39d60ef7b9cd5deea2b34869c9f0b9777450a7e3759c1ab09b9b", + "sha256:98d44a8136eebbf544ad91fef5bd2b20ef0c9b459c65a833c923d9aa4546b204", + "sha256:9d2c2e3ce7b8cc932a2f918186964bd44de8c84e2f9ef72dc616f5bb8be22e71", + "sha256:a300b39c3d5905686c75a369d2a66e68fd01472ea42e16b38c948bd02b29e5bd", + "sha256:a34fccb45f7b2d890183a263578d60a392a1a218fdc12f5bce1477a6a68d4373", + "sha256:a4d48e42e17d3de212f9af44f81ab73b9378a4b2b8413fd708d0d9023f2bbde4", + "sha256:af45eea024c0e3a25462fade161afab4f0d9d9e0d5a5d53e86149f74f0a35ecc", + "sha256:ba6125d4e55c0b8e913dad27b22722eac7abdcb1f3eab1bd090eee9105660266", + "sha256:bc1ee1318f703bc6c971da700d74466e9b86e0c443eb85983fb2a1bd20447263", + "sha256:c18725f3cffe96732ef96f3de1939d81215fd6d7d64900dcc4acfe514ea4fcbf", + "sha256:c8e9c4bcaaaa932be581b3d8b88b677489975f845f7714efc8cce77568b6711c", + "sha256:cc799916b618ec9fd00135e576424165691fec4f70d7dc12cfaef09268a2478c", + "sha256:cd2d11a59afa5001ff28073ceca24ae4c506da4355aba30d1e7dd2bd0d2206dc", + "sha256:d0a595a781f8e186580ff8e3352dd4953b1944289bec7705377c80c7e36c4d6c", + "sha256:d3c5f49ce6af61154060640ad3b3281dbc46e2e0ef2fe78414d7f8a324f0b649", + "sha256:d9a635114b88c0ab462e0355472d00a180a5fbfd8511e7f18e4ac32652e7d972", + "sha256:e5432d9c329b11c27be45ee5f62cf20a33065d482c8dec1941d6670622a6fb8f", + "sha256:eab14fdd410500dae50fd14ccc332e65543e7b39f6fc076fe90603a0e5d2f929", + "sha256:ebcc03e1acef4ff44f37f3c61df478d6e469a573aa688e5a162f85d7e4c3860d", + "sha256:fae3fe111670e51f1ebbc475823899524e3459ea2db2cb88279bbfb2a0b8a3de", + "sha256:fd92ece726055e80d4e3f01fff3b91f54b18c9c357c48fcf6119e87e2461a091", + "sha256:ffa545230ca2ad921ad066bf8fd627e7be43716b6e0fcf8e32af1b8188ccb0ab" ], "index": "pypi", - "version": "==6.0.2" + "version": "==6.1.2" }, "cryptography": { "hashes": [ @@ -297,11 +319,11 @@ }, "docutils": { "hashes": [ - "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125", - "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" + "sha256:a31688b2ea858517fa54293e5d5df06fbb875fb1f7e4c64529271b77781ca8fc", + "sha256:c1d5dab2b11d16397406a282e53953fe495a46d69ae329f55aa98a5c4e3c5fbb" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.17.1" + "version": "==0.18" }, "execnet": { "hashes": [ @@ -313,19 +335,19 @@ }, "factory-boy": { "hashes": [ - "sha256:1d3db4b44b8c8c54cdd8b83ae4bdb9aeb121e464400035f1f03ae0e1eade56a4", - "sha256:401cc00ff339a022f84d64a4339503d1689e8263a4478d876e58a3295b155c5b" + "sha256:a98d277b0c047c75eb6e4ab8508a7f81fb03d2cb21986f627913546ef7a2a55e", + "sha256:eb02a7dd1b577ef606b75a253b9818e6f9eaf996d94449c9d5ebb124f90dc795" ], "index": "pypi", - "version": "==3.2.0" + "version": "==3.2.1" }, "faker": { "hashes": [ - "sha256:072b61422be9da464b0bb40cdb44267dd584582056b77a2982d7c66c767f044c", - "sha256:8ffd1ca479364a2ea78fe23a5710d5f940c50576f45c3f62edf9f7f9242cec0b" + "sha256:b9ea5970f43c1fa05443d1885fbed822aba816facefa053d3d20168bfef4ae84", + "sha256:cfe4eed0309cd5325c40817519f8fbb18281a3f43a9a23fe03e3e7f091a9775b" ], "markers": "python_version >= '3.6'", - "version": "==9.6.0" + "version": "==9.8.1" }, "flake8": { "hashes": [ @@ -352,11 +374,11 @@ }, "importlib-metadata": { "hashes": [ - "sha256:b618b6d2d5ffa2f16add5697cf57a46c76a56229b0ed1c438322e4e95645bd15", - "sha256:f284b3e11256ad1e5d03ab86bb2ccd6f5339688ff17a4d797a0fe7df326f23b1" + "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100", + "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb" ], "markers": "python_version >= '3.6'", - "version": "==4.8.1" + "version": "==4.8.2" }, "inflection": { "hashes": [ @@ -405,11 +427,11 @@ }, "packaging": { "hashes": [ - "sha256:7dc96269f53a4ccec5c0670940a4281106dd0bb343f47b7471f779df49c2fbe7", - "sha256:c86254f9220d55e31cc94d69bade760f0847da8000def4dfe1c6b872fd14ff14" + "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966", + "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0" ], "markers": "python_version >= '3.6'", - "version": "==21.0" + "version": "==21.2" }, "pathspec": { "hashes": [ @@ -475,11 +497,11 @@ }, "py": { "hashes": [ - "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3", - "sha256:3b80836aa6d1feeaa108e046da6423ab8f6ceda6468545ae8d02d9d58d18818a" + "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", + "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.10.0" + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==1.11.0" }, "pycodestyle": { "hashes": [ @@ -491,11 +513,11 @@ }, "pycparser": { "hashes": [ - "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0", - "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705" + "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9", + "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206" ], "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==2.20" + "version": "==2.21" }, "pyflakes": { "hashes": [ @@ -515,11 +537,11 @@ }, "pyparsing": { "hashes": [ - "sha256:84196357aa3566d64ad123d7a3c67b0e597a115c4934b097580e5ce220b91531", - "sha256:fd93fc45c47893c300bd98f5dd1b41c0e783eaeb727e7cea210dcc09d64ce7c3" + "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1", + "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b" ], - "markers": "python_version >= '3.6'", - "version": "==3.0.1" + "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.4.7" }, "pytest": { "hashes": [ @@ -596,44 +618,57 @@ }, "regex": { "hashes": [ - "sha256:0c186691a7995ef1db61205e00545bf161fb7b59cdb8c1201c89b333141c438a", - "sha256:0dcc0e71118be8c69252c207630faf13ca5e1b8583d57012aae191e7d6d28b84", - "sha256:0f7552429dd39f70057ac5d0e897e5bfe211629652399a21671e53f2a9693a4e", - "sha256:129472cd06062fb13e7b4670a102951a3e655e9b91634432cfbdb7810af9d710", - "sha256:13ec99df95003f56edcd307db44f06fbeb708c4ccdcf940478067dd62353181e", - "sha256:1f2b59c28afc53973d22e7bc18428721ee8ca6079becf1b36571c42627321c65", - "sha256:2b20f544cbbeffe171911f6ce90388ad36fe3fad26b7c7a35d4762817e9ea69c", - "sha256:2fb698037c35109d3c2e30f2beb499e5ebae6e4bb8ff2e60c50b9a805a716f79", - "sha256:34d870f9f27f2161709054d73646fc9aca49480617a65533fc2b4611c518e455", - "sha256:391703a2abf8013d95bae39145d26b4e21531ab82e22f26cd3a181ee2644c234", - "sha256:450dc27483548214314640c89a0f275dbc557968ed088da40bde7ef8fb52829e", - "sha256:45b65d6a275a478ac2cbd7fdbf7cc93c1982d613de4574b56fd6972ceadb8395", - "sha256:5095a411c8479e715784a0c9236568ae72509450ee2226b649083730f3fadfc6", - "sha256:530fc2bbb3dc1ebb17f70f7b234f90a1dd43b1b489ea38cea7be95fb21cdb5c7", - "sha256:56f0c81c44638dfd0e2367df1a331b4ddf2e771366c4b9c5d9a473de75e3e1c7", - "sha256:5e9c9e0ce92f27cef79e28e877c6b6988c48b16942258f3bc55d39b5f911df4f", - "sha256:6d7722136c6ed75caf84e1788df36397efdc5dbadab95e59c2bba82d4d808a4c", - "sha256:74d071dbe4b53c602edd87a7476ab23015a991374ddb228d941929ad7c8c922e", - "sha256:7b568809dca44cb75c8ebb260844ea98252c8c88396f9d203f5094e50a70355f", - "sha256:80bb5d2e92b2258188e7dcae5b188c7bf868eafdf800ea6edd0fbfc029984a88", - "sha256:8d1cdcda6bd16268316d5db1038965acf948f2a6f43acc2e0b1641ceab443623", - "sha256:9f665677e46c5a4d288ece12fdedf4f4204a422bb28ff05f0e6b08b7447796d1", - "sha256:a30513828180264294953cecd942202dfda64e85195ae36c265daf4052af0464", - "sha256:a7a986c45d1099a5de766a15de7bee3840b1e0e1a344430926af08e5297cf666", - "sha256:a940ca7e7189d23da2bfbb38973832813eab6bd83f3bf89a977668c2f813deae", - "sha256:ab7c5684ff3538b67df3f93d66bd3369b749087871ae3786e70ef39e601345b0", - "sha256:be04739a27be55631069b348dda0c81d8ea9822b5da10b8019b789e42d1fe452", - "sha256:c0938ddd60cc04e8f1faf7a14a166ac939aac703745bfcd8e8f20322a7373019", - "sha256:cb46b542133999580ffb691baf67410306833ee1e4f58ed06b6a7aaf4e046952", - "sha256:d134757a37d8640f3c0abb41f5e68b7cf66c644f54ef1cb0573b7ea1c63e1509", - "sha256:de557502c3bec8e634246588a94e82f1ee1b9dfcfdc453267c4fb652ff531570", - "sha256:ded0c4a3eee56b57fcb2315e40812b173cafe79d2f992d50015f4387445737fa", - "sha256:e1dae12321b31059a1a72aaa0e6ba30156fe7e633355e445451e4021b8e122b6", - "sha256:eb672217f7bd640411cfc69756ce721d00ae600814708d35c930930f18e8029f", - "sha256:ee684f139c91e69fe09b8e83d18b4d63bf87d9440c1eb2eeb52ee851883b1b29", - "sha256:f3f9a91d3cc5e5b0ddf1043c0ae5fa4852f18a1c0050318baf5fc7930ecc1f9c" - ], - "version": "==2021.10.23" + "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f", + "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc", + "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4", + "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4", + "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8", + "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f", + "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a", + "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef", + "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f", + "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc", + "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50", + "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d", + "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d", + "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733", + "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36", + "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345", + "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0", + "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12", + "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646", + "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667", + "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244", + "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29", + "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec", + "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf", + "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4", + "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449", + "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a", + "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d", + "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb", + "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e", + "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83", + "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e", + "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a", + "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94", + "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc", + "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e", + "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965", + "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0", + "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36", + "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec", + "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23", + "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7", + "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe", + "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6", + "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b", + "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb", + "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b", + "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30", + "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e" + ], + "version": "==2021.11.10" }, "requests": { "hashes": [ @@ -706,54 +741,43 @@ }, "twine": { "hashes": [ - "sha256:087328e9bb405e7ce18527a2dca4042a84c7918658f951110b38bc135acab218", - "sha256:4caec0f1ed78dc4c9b83ad537e453d03ce485725f2aea57f1bb3fdde78dae936" + "sha256:4caad5ef4722e127b3749052fcbffaaf71719b19d4fd4973b29c469957adeba2", + "sha256:916070f8ecbd1985ebed5dbb02b9bda9a092882a96d7069d542d4fc0bb5c673c" ], "index": "pypi", - "version": "==3.4.2" + "version": "==3.6.0" }, "typed-ast": { "hashes": [ - "sha256:01ae5f73431d21eead5015997ab41afa53aa1fbe252f9da060be5dad2c730ace", - "sha256:067a74454df670dcaa4e59349a2e5c81e567d8d65458d480a5b3dfecec08c5ff", - "sha256:0fb71b8c643187d7492c1f8352f2c15b4c4af3f6338f21681d3681b3dc31a266", - "sha256:1b3ead4a96c9101bef08f9f7d1217c096f31667617b58de957f690c92378b528", - "sha256:2068531575a125b87a41802130fa7e29f26c09a2833fea68d9a40cf33902eba6", - "sha256:209596a4ec71d990d71d5e0d312ac935d86930e6eecff6ccc7007fe54d703808", - "sha256:2c726c276d09fc5c414693a2de063f521052d9ea7c240ce553316f70656c84d4", - "sha256:398e44cd480f4d2b7ee8d98385ca104e35c81525dd98c519acff1b79bdaac363", - "sha256:52b1eb8c83f178ab787f3a4283f68258525f8d70f778a2f6dd54d3b5e5fb4341", - "sha256:5feca99c17af94057417d744607b82dd0a664fd5e4ca98061480fd8b14b18d04", - "sha256:7538e495704e2ccda9b234b82423a4038f324f3a10c43bc088a1636180f11a41", - "sha256:760ad187b1041a154f0e4d0f6aae3e40fdb51d6de16e5c99aedadd9246450e9e", - "sha256:777a26c84bea6cd934422ac2e3b78863a37017618b6e5c08f92ef69853e765d3", - "sha256:95431a26309a21874005845c21118c83991c63ea800dd44843e42a916aec5899", - "sha256:9ad2c92ec681e02baf81fdfa056fe0d818645efa9af1f1cd5fd6f1bd2bdfd805", - "sha256:9c6d1a54552b5330bc657b7ef0eae25d00ba7ffe85d9ea8ae6540d2197a3788c", - "sha256:aee0c1256be6c07bd3e1263ff920c325b59849dc95392a05f258bb9b259cf39c", - "sha256:af3d4a73793725138d6b334d9d247ce7e5f084d96284ed23f22ee626a7b88e39", - "sha256:b36b4f3920103a25e1d5d024d155c504080959582b928e91cb608a65c3a49e1a", - "sha256:b9574c6f03f685070d859e75c7f9eeca02d6933273b5e69572e5ff9d5e3931c3", - "sha256:bff6ad71c81b3bba8fa35f0f1921fb24ff4476235a6e94a26ada2e54370e6da7", - "sha256:c190f0899e9f9f8b6b7863debfb739abcb21a5c054f911ca3596d12b8a4c4c7f", - "sha256:c907f561b1e83e93fad565bac5ba9c22d96a54e7ea0267c708bffe863cbe4075", - "sha256:cae53c389825d3b46fb37538441f75d6aecc4174f615d048321b716df2757fb0", - "sha256:dd4a21253f42b8d2b48410cb31fe501d32f8b9fbeb1f55063ad102fe9c425e40", - "sha256:dde816ca9dac1d9c01dd504ea5967821606f02e510438120091b84e852367428", - "sha256:f2362f3cb0f3172c42938946dbc5b7843c2a28aec307c49100c8b38764eb6927", - "sha256:f328adcfebed9f11301eaedfa48e15bdece9b519fb27e6a8c01aa52a17ec31b3", - "sha256:f8afcf15cc511ada719a88e013cec87c11aff7b91f019295eb4530f96fe5ef2f", - "sha256:fb1bbeac803adea29cedd70781399c99138358c26d05fcbd23c13016b7f5ec65" - ], - "version": "==1.4.3" + "sha256:14fed8820114a389a2b7e91624db5f85f3f6682fda09fe0268a59aabd28fe5f5", + "sha256:155b74b078be842d2eb630dd30a280025eca0a5383c7d45853c27afee65f278f", + "sha256:224afecb8b39739f5c9562794a7c98325cb9d972712e1a98b6989a4720219541", + "sha256:361b9e5d27bd8e3ccb6ea6ad6c4f3c0be322a1a0f8177db6d56264fa0ae40410", + "sha256:37ba2ab65a0028b1a4f2b61a8fe77f12d242731977d274a03d68ebb751271508", + "sha256:49af5b8f6f03ed1eb89ee06c1d7c2e7c8e743d720c3746a5857609a1abc94c94", + "sha256:51040bf45aacefa44fa67fb9ebcd1f2bec73182b99a532c2394eea7dabd18e24", + "sha256:52ca2b2b524d770bed7a393371a38e91943f9160a190141e0df911586066ecda", + "sha256:618912cbc7e17b4aeba86ffe071698c6e2d292acbd6d1d5ec1ee724b8c4ae450", + "sha256:65c81abbabda7d760df7304d843cc9dbe7ef5d485504ca59a46ae2d1731d2428", + "sha256:7b310a207ee9fde3f46ba327989e6cba4195bc0c8c70a158456e7b10233e6bed", + "sha256:7e6731044f748340ef68dcadb5172a4b1f40847a2983fe3983b2a66445fbc8e6", + "sha256:806e0c7346b9b4af8c62d9a29053f484599921a4448c37fbbcbbf15c25138570", + "sha256:a67fd5914603e2165e075f1b12f5a8356bfb9557e8bfb74511108cfbab0f51ed", + "sha256:e4374a76e61399a173137e7984a1d7e356038cf844f24fd8aea46c8029a2f712", + "sha256:e8a9b9c87801cecaad3b4c2b8876387115d1a14caa602c1618cedbb0cb2a14e6", + "sha256:ea517c2bb11c5e4ba7a83a91482a2837041181d57d3ed0749a6c382a2b6b7086", + "sha256:ec184dfb5d3d11e82841dbb973e7092b75f306b625fad7b2e665b64c5d60ab3f", + "sha256:ff4ad88271aa7a55f19b6a161ed44e088c393846d954729549e3cde8257747bb" + ], + "markers": "python_version >= '3.6'", + "version": "==1.5.0" }, "typing-extensions": { "hashes": [ - "sha256:49f75d16ff11f1cd258e1b988ccff82a3ca5570217d7ad8c5f48205dd99a677e", - "sha256:d8226d10bc02a29bcc81df19a26e56a9647f8b0a6d4a83924139f4a8b01f17b7", - "sha256:f1d25edafde516b146ecd0613dabcc61409817af4766fbbcfb8d1ad4ec441a34" + "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9" ], - "version": "==3.10.0.2" + "markers": "python_version >= '3.6'", + "version": "==4.0.0" }, "urllib3": { "hashes": [ diff --git a/setup.py b/setup.py index 3c25f9f..c7a84e5 100644 --- a/setup.py +++ b/setup.py @@ -45,6 +45,7 @@ def get_version(rel_path): install_requires=[ "Django>=3.0.0,<3.3", "django-url-filter>=0.3.15", + "marshmallow>=3.14.0", ], include_package_data=True, keywords="django, rest, framework, api", diff --git a/tests/models.py b/tests/models.py index 61e0f5f..b2f6fd0 100644 --- a/tests/models.py +++ b/tests/models.py @@ -25,12 +25,6 @@ class Role(models.Model): class Skill(models.Model): name = models.CharField(max_length=200) - def api(self): - return dict( - id=self.pk, - name=self.name, - ) - class RatedSkill(models.Model): class Meta: @@ -52,23 +46,10 @@ class Meta: def __str__(self): return f"{self.skill.name}: {self.get_rating_display()}" - def api(self): - return dict( - id=self.skill.pk, - name=self.skill.name, - rating=self.rating, - ) - class Tag(models.Model): name = models.CharField(max_length=200) - def api(self): - return dict( - id=self.pk, - name=self.name, - ) - class Team(models.Model): name = models.CharField(max_length=64) diff --git a/tests/serializers.py b/tests/serializers.py index 90cd713..25d5a9b 100644 --- a/tests/serializers.py +++ b/tests/serializers.py @@ -1,37 +1,56 @@ -from worf.serializers import Serializer +from worf.serializers import fields, Serializer class UserSerializer(Serializer): - def read(self, model): - return dict( - username=model.username, - lastLogin=model.last_login, - dateJoined=model.date_joined, - email=model.email, - ) - - def write(self): - return [ + last_login = fields.DateTime(dump_only=True) + date_joined = fields.DateTime(dump_only=True) + + class Meta: + fields = [ "username", + "last_login", + "date_joined", "email", ] class ProfileSerializer(Serializer): - def read(self, model): - return dict( - username=model.user.username, - email=model.user.email, - role=dict(name=model.role.name) if model.role else None, - skills=[t.api() for t in model.ratedskill_set.all()], - team=dict(name=model.team.name) if model.team else None, - tags=[t.api() for t in model.tags.all()], - ) - - def write(self): - return [ + username = fields.Function(lambda obj: obj.user.username) + email = fields.Function(lambda obj: obj.user.email) + role = fields.Nested("RoleSerializer") + skills = fields.Nested("RatedSkillSerializer", attribute="ratedskill_set", many=True) + team = fields.Nested("TeamSerializer") + tags = fields.Nested("TagSerializer", many=True) + + class Meta: + fields = [ + "username", + "email", "role", "skills", "team", "tags", ] + + +class RatedSkillSerializer(Serializer): + id = fields.Function(lambda obj: obj.skill.id) + name = fields.Function(lambda obj: obj.skill.name) + + class Meta: + fields = ["id", "name", "rating"] + + +class RoleSerializer(Serializer): + class Meta: + fields = ["id", "name"] + + +class TagSerializer(Serializer): + class Meta: + fields = ["id", "name"] + + +class TeamSerializer(Serializer): + class Meta: + fields = ["id", "name"] diff --git a/worf/fields.py b/worf/fields.py new file mode 100644 index 0000000..9bb8fed --- /dev/null +++ b/worf/fields.py @@ -0,0 +1,11 @@ +from django.db.models import Manager + +import marshmallow.fields +from marshmallow.fields import * # noqa: F401, F403 + + +class Nested(marshmallow.fields.Nested): + def _serialize(self, nested_obj, attr, obj, **kwargs): + if isinstance(nested_obj, Manager): + nested_obj = nested_obj.all() + return super()._serialize(nested_obj, attr, obj, **kwargs) diff --git a/worf/serializers.py b/worf/serializers.py index 0eb6b4f..dd2a1d6 100644 --- a/worf/serializers.py +++ b/worf/serializers.py @@ -1,24 +1,53 @@ import json +import marshmallow from django.core.exceptions import ImproperlyConfigured +from worf import fields # noqa: F401 +from worf.casing import snake_to_camel + def deserialize(response): return json.loads(response.content.decode("UTF-8")) -class Serializer: - def create(self): - return [] +class Serializer(marshmallow.Schema): + """ + Serializer base class with sensible defaults for typically read-only fields. + + Worf serializers are basically marshmallow schemas with better support for + Django models, and some extra opinions around field naming and ordering. + + The read/write methods are relics of our interim serialization strategy + they're analogous with marshmallow dump/load, but a bit less flexible. + + Marshmallow is primarily used for field filtering right now, worf coerces + values itself, but we might delegated more to marshmallow later. + """ + + id = fields.Function(lambda obj: obj.pk, dump_only=True) + created_at = fields.DateTime(dump_only=True) + deleted_at = fields.DateTime(dump_only=True) + updated_at = fields.DateTime(dump_only=True) + + @property + def dict_class(self): + return dict def list(self, items): return [self.read(item) for item in items] - def read(self, model): - return {} + def on_bind_field(self, field_name, field_obj): + field_obj.data_key = snake_to_camel(field_obj.data_key or field_name) + + def read(self, obj): + return self.dump(obj) def write(self): - return [] + return list(self.load_fields.keys()) + + class Meta: + ordered = True class LegacySerializer(Serializer): @@ -26,10 +55,10 @@ def __init__(self, model_class, api_method): self.api_method = api_method self.model_class = model_class - def read(self, model): - payload = getattr(model, self.api_method)() + def read(self, obj): + payload = getattr(obj, self.api_method)() if not isinstance(payload, dict): - msg = f"{model.__name__}.{self.api_method}() did not return a dictionary" + msg = f"{obj.__name__}.{self.api_method}() did not return a dictionary" raise ImproperlyConfigured(msg) return payload