On Fri, Mar 25, 2011 at 6:03 PM, Vivek Narayanan <m...@vivekn.co.cc> wrote: >> I think I see where you're going here. However, I'm not sure it >> captures the entire problem. >> >> Part of the problem with the existing serializers is that they don't >> account for the fact that there's actually two subproblems to >> serialization: >> >> 1) How do I output the value of a specific field >> 2) What is the gross structure of an object, which is a collection of >> fields plus, plus metadata about an object, plus >> >> So, for a single object the JSON serializer currently outputs: >> >> { >> "pk": 1, >> "model": "myapp.mymodel", >> "fields": { >> "foo": "foo value", >> "bar": "bar value" >> } >> >> } >> >> Implicit in this format is a bunch of assumptions: >> >> * That the primary key should be rendered in a different way to the >> rest of the fields >> * That I actually want to include model metadata like the model name >> * That the list of fields is an embedded structure rather than a list >> of top-level attributes. >> * That I want to include all the fields on the model >> * That I don't have any non-model or computed metadata that I want to >> include > > I believe that my model of using a recursive method and storing > temporary data in 'levels' would address most of these concerns. The > method for handling a model would consist of the following steps, > roughly: > > * Get the list of fields to be serialized.
For a suitably relaxed definition of "field". Remember, serialized data doesn't necessarily have to come from the model -- it could come from a related model, or be a constant, or be a computed field, or many other options. >> When you start dealing with foreign keys and m2m, you have an >> additional set of assumptions -- >> >> * How far should I traverse relations? > > The user can specify a limit to the levels of nesting through > variable ``max_nesting_depth``. A simple "nesting depth" approach won't work. You really need to handle this on a per-model basis; Mode It might be possible to automate some of this with a simple nesting depth definition, but there will always be a need to define the exact rollout of a tree of serialization options. This is also a case where being explicit makes your life easier. If you stop looking at "depth" as a single number specified at the top of the tree, it becomes a lot easier to handle recursive or >> * Do I traverse reverse relations? > > In my opinion, traversing reverse relations can get really ugly at > times, especially when there are M2M fields, foreign keys or circular > relations involved. But there are some scenarios where the data is in > a relatively simpler format and serializing them would be useful. To > support this, I thought of something like this: > > class Srz(Serializer): > ... > reverse_relations = [ (from_model_type, to_model_type), ... ] > > But this should be used with caution and avoided when possible. > >> * How do I represent traversed objects? As FK values? As embedded objects? > > As embedded objects, if the nesting depth limit is reached, then as FK > values. My point is that this is a serialization option. You're dictating a policy here, rather than allowing it to be a configuration option. >> * If they're embedded objects, how do I represent *their* traversed values? > > Their traversed values would be represented just as a normal model > would be, with field-value mappings. The user can choose which fields > to dump. Again -- you're dictating a policy, not allowing the user to define one. >> * What happens with circular relations? > > For all model type objects, like the base model in the query set and > all FK and M2M fields, some uniquely identifying data (like the > primary key, content type) will be stored in a list as each one of > them is processed. Before serializing a model, it would be checked if > the model is already on the list or not. If it is there, it is a > circular reference and that model would be ignored . > >> * If I have two foreign keys on the same model, are they both >> serialized the same way? > > Yes. Why should this be the case? Again, you are dictating policy, not allowing policy to be defined. >> When you start dealing with the XML serializer, you have all these >> problems and more (because you have the attribute/tag distinction for >> each of these decisions, too -- for example, I may want some fields to >> be rendered as attributes, and some as tags. >> > > For XML, I thought of using an intermediary container for a node that > would store all these details. > >> > --------------------------------------------------------- >> > New features in the serialize() function >> > --------------------------------------------------------- >> > Apart from the changes I’ve proposed for the ``fields`` argument of >> > serialize, I would like to add a couple of features: >> >> > • An exclude argument, which would be a list of fields to exclude from >> > the model, this would also contain the fields to exclude in related >> > models. >> >> > • An extras argument, which would allow properties and data returned >> > by some methods to be serialized. >> >> For me, the goal should be to deprecate these sorts of arguments. The >> decision to include (or exclude) a particular field is a feature of >> serialization that is intimately tied to the serialization format, not >> something that is an external argument. >> > Initially, I thought the goal was not to tie down a serializer to any > model, I can integrate these features into the serializer class then. My point is that it should be *possible* to define a "generic" serialization strategy -- after all, that's what Django does right now. If arguments like this do exist, they should essentially be arguments used to instantiate a specific serialization strategy, rather than something baked into the serialization API. >> > ----------------------------------------------------------------- >> > Representing the existing serialization model >> > ----------------------------------------------------------------- >> > Here is an implementation of the existing serialization format in >> > JSON, this would be the ‘fixture’ mode that I’ve mentioned above. >> >> I think these examples demonstrate what I said earlier -- your >> proposed framework allows me to customize the name given to a field in >> XML, but doesn't allow me to change the parent of that field within >> the broader XML structure. > > I'm not sure that I follow this, It would be great if you could give > an example. As I mentioned earlier, there will be an option to > 'flatten' the nested models , provide alternate names to the fields, > and wrap fields into a group. Initially I had thought of adding this > to the external ``fields`` argument in ``serialize()``, but I can add > them to the specification object too. The recurring theme in my comments is that you are dictating policy, not allowing users to define policy. We already have the former; we need the latter. Heres an example of the problem as I see it. Consider the serialization of a "book" model. Option 1: Django's current serializer: { "pk": 1 "model": "library.book" "fields": { "authors": [3, 4] "editor": 5 "title": "Django for Dummies" } } No real surprises here. Option 2: the format required for a particular book publishing API { "book details": { "book title": "Django for dummies" "authors": [ "John Smith", "Bob Jones" ], } "author_count": 2, "editor": { "firstname": "Alice" "lastname": Watson", "coworkers": [1, 5], "contact_phone": "98761234", "company": { "name": "Mega publishing corp", "founded": 2010 } }, } Notable features: * Authors and editor are both "Person" objects, but - We need to serialize editors in detail, including recursive calls - Authors are serialized using their combined first+last name * "book title" is a rename of the native model field * "author_count" isn't on the model at all. * "book details" doesn't reflect any aspect of model structure -- it's entirely decoration. Now - show me how both of these serializers are defined using your proposed API. Yours, Russ Magee %-) -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.