An idea for a serialization framework

7 views
Skip to first unread message

Andy Kelley

unread,
Jun 23, 2010, 6:43:00 AM6/23/10
to Django developers
I posted this in django-users but someone said I should post it in
django developers, so here we are.

I am coming up with a framework that helps serialization of models. My
idea is for each field to have a view permissions level: PUBLIC,
OWNER, or ADMIN. I want to have a model to dict function that takes 2
arguments, permission_level and serialize_chain. Firstly, let me
explain how it would change models.py:


from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.ForeignKey(User, permission=PUBLIC)
bio = models.TextField(permission=PUBLIC)
activated = models.BooleanField(default=False, permission=OWNER)
activate_code = models.CharField(max_length=256, permission=ADMIN)
pages_bookmarked = models.ManyToManyField('Page',
related_name='profile_pages_bookmarked', permission=OWNER)


So, in this example, let's think about when we serialize Profile into
a dictionary (for later turning into JSON for ajax). user is the only
special case, so skip that mentally for now. Anyone is able to view a
profile's bio. A person can view their own profile's activation status
and what pages they have bookmarked. But only the system can read the
activate_code. Of course the default value for permission would be
ADMIN, so you'd have to explicitly allow fields to be sent to the
browser.

OK, and how would the serialization work? Let's look at a view
function.


from django.shortcuts import get_object_or_404
from django.http import HttpResponse
import simplejson as json

def ajax_profile_info(request, id):
id = int(id)
profile = get_object_or_404(Profile, id=id)
# ok now we want to serialize profile for sending to json.
# let's say this is the ajax view for getting data about OTHER
people.
return json_response(profile.serialize(PUBLIC))

def json_response(data):
return HttpResponse(json.dumps(data), mimetype="text/plain")


So in this view, only fields with the PUBLIC will get rendered into
the dict. Let's say it was a view function for looking at a person's
own account settings. Then we would pass OWNER to the serialize
function and we would get all PUBLIC fields + OWNER fields.

OK that's dandy, but I have one other idea to make serialization
awesome. When you have models that foreignkey all over the place, it's
a pain to create a nice json object that follows the chain to the
exact depth that you want. So let me complicate the model a little
bit.


from django.db import models
from django.contrib.auth.models import User

class Profile(models.Model):
user = models.ForeignKey(User, permission=PUBLIC)
bio = models.TextField(permission=PUBLIC)
activated = models.BooleanField(default=False, permission=OWNER)
activate_code = models.CharField(max_length=256, permission=ADMIN)
books_read = models.ManyToManyField('Book',
related_name='profile_pages_bookmarked', permission=PUBLIC)

class Book(models.Model):
title = models.CharField(max_length=100, permission=PUBLIC)
protagonist = models.ForeignKey('Character', permission=PUBLIC)
language_used = models.ForeignKey('Language', permission=PUBLIC)
cover_art_plan = models.ForeignKey('CoverArtPlan',
permission=PUBLIC)
internal_admin_thing = models.IntegerField(permission=ADMIN)

class Character(models.Model):
name = models.CharField(max_length=100, permission=PUBLIC)

class Language(models.Model):
name = models.CharField(max_length=100, permission=PUBLIC)

class CoverArtPlan(models.Model):
name = models.CharField(max_length=100, permission=PUBLIC)

OK so let's say I'm making a page where we see all the books a person
has read (and the info about those books). Here's a view function:


def ajax_books_read(request, profile_id):
id = int(id)
profile = get_object_or_404(Profile, id=id)
return json_response(profile.serialize(PUBLIC),
['books_read.protagonist', 'books_read.language_used'])


So this second argument, the serialize_chain, says that we want to
serialize profile into a dict, and the books_read field, instead of
containing a list of ids, should contain a list of serialized Books.
And since we have a dot there, when Profile passes it's serialization
request on to Book, it cuts off the "books_read." and passes the rest
to Book, so that book sees ['protagonist', 'language_used']. so when
Book serializes, its 'protagonist' field is the serialization of the
Character instead of just an id. Same for 'language_used'. However,
since cover_art_plan was not included, it is simply the id of the
CoverArtPlan instead of following the link. Also of note, since we
serialized with PUBLIC, internal_admin_thing is completely left out of
Book's serialized data.

A note about access levels: let's say Profile was serialized with
OWNER access, when it serializes its books_read, it doesn't pass
OWNER, it de-escalates the access level to PUBLIC. However if you
serialize Profile with ADMIN access, it does pass admin when it
serializes its links. Think about it; it makes sense.


Anyways, I would like to know if

1) Does a solution like this already exist? and if not
2) Is this cool enough to go into django core? or contrib or whatever.


I got some feedback from mattmcc in #django:
<mattmcc> superjoe: At first glance, I'd be more inclined to look at a
role-based access control mechanism that doesn't obligate hardcoding
permission levels on to model fields..

However I still think the idea has merit - even alongside a role-based
security system.

Feedback?

Sergej dergatsjev eecho

unread,
Jun 23, 2010, 9:04:04 AM6/23/10
to django-d...@googlegroups.com
2010/6/23 Andy Kelley <super...@gmail.com>:

http://docs.djangoproject.com/en/dev/topics/serialization/

Custom types serialization

http://code.djangoproject.com/wiki/DynamicModels

> 2) Is this cool enough to go into django core? or contrib or whatever.
>
>
> I got some feedback from mattmcc in #django:
> <mattmcc> superjoe: At first glance, I'd be more inclined to look at a
> role-based access control mechanism that doesn't obligate hardcoding
> permission levels on to model fields..
>
> However I still think the idea has merit - even alongside a role-based
> security system.
>
> Feedback?
>

> --
> You received this message because you are subscribed to the Google Groups "Django developers" group.
> To post to this group, send email to django-d...@googlegroups.com.
> To unsubscribe from this group, send email to django-develop...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.
>
>

--
Sergej Dergatsjev
E-mail: sergej.d...@gmail.com
Skype: SergejDergatsjev
Site: http://www.eecho.info

Russell Keith-Magee

unread,
Jun 23, 2010, 10:20:34 AM6/23/10
to django-d...@googlegroups.com

Of a fashion.

http://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-fields

You need to manually define the list of fields, but you can control
the subset that is serialized.

> 2) Is this cool enough to go into django core? or contrib or whatever.
>
>
> I got some feedback from mattmcc in #django:
> <mattmcc> superjoe: At first glance, I'd be more inclined to look at a
> role-based access control mechanism that doesn't obligate hardcoding
> permission levels on to model fields..

Matt is right on the money. Putting permission stuff into the model
definition like that makes my teeth itch.

There is a lot of room for improvement in Django's serialization code,
and selective serialization of fields is one of those areas of
improvement. However, serialization strategies are orthogonal to model
definitions; I can't say I'm a huge fan of a proposal that tries to
convolve the two.

Yours,
Russ Magee %-)

Andy Kelley

unread,
Jun 23, 2010, 5:52:31 PM6/23/10
to Django developers
Thanks for the tips guys.

I implemented this in my app, and it's interesting, at least. After
quite a bit of refactoring, I was left with my solution. I see what
you're saying about coupling serialization strategies with model
definitions. This is an interesting post-refactoring feeling. Usually
after a major refactoring, the only feeling is, "Ah what a bunch of
great clean code." However with this one, it's more like, "Well, the
code is cleaner and shorter. But there does exist something fishy
about this."

Anyways, I'll shut up about this, because it's clear that it's ok way
to do things on an individual project but isn't something to
evangelize.

On Jun 23, 7:20 am, Russell Keith-Magee <russ...@keith-magee.com>
wrote:
> http://docs.djangoproject.com/en/dev/topics/serialization/#subset-of-...
Reply all
Reply to author
Forward
0 new messages