dominno / django-moderation

django-moderation is reusable application for Django framework, that allows to moderate any model objects.
BSD 3-Clause "New" or "Revised" License
269 stars 90 forks source link

Add "pending_column" for performance when checking if pending moderation #45

Open swiharta opened 13 years ago

swiharta commented 13 years ago

I'm working out how to add a "pending_column" to improve performance when you want to check which of a large number of moderated model instances are pending moderation. I added a 'pending' Boolean field to my model and referenced it as my 'pending_column' when I subclassed moderator.GenericModerator.

As a first step, in register.py pre_save_handler I added:

if moderator.pending_column:
    setattr(instance, moderator.pending_column, True)

After saving a change to a model instance, on viewing this instance in the admin, I can see the 'pending' attribute appropriately set as True, but when I do mymodel_instance.pending, it strangely returns False. I'm not sure what's going on here, likely something to do with the manager, any idea?

treyhunner commented 13 years ago

The pending attribute is probably being set on the unapproved version of the object stored in the changed_object field of ModeratedObject and not in the original instance.

swiharta commented 13 years ago

Actually, I just replaced instance with moderated_obj.changed_object, and while it seems kind of hacky, it produces exactly the behavior I want. I guess changed_object in this case represents a copy of the original model instance, and this is what the objects manager retrieves if a ModeratedObject exists, rather than the instance itself? The variable name is a little confusing, because this "changed object" is actually supposed to be a copy of the unchanged model instance, if I'm getting this right.

In register.py pre_save_handler, I added:

if moderator.pending_column: # is 'pending_column' in your subclassed GenericModerator
    setattr(moderated_obj.changed_object, moderator.pending_column, True) # set 'pending_column' True in the visible instance
moderated_obj.save()

'pending' becomes False after I approve a change, automatically it seems, because the True was only applied to a copy of the original instance, not the instance itself, at least that's how it seems to be occurring.

Now I can do model_instance.pending in my templates / view to see if there is a pending change under moderation, without generating extra db queries. Seems to be working as intended so far, I'll report back with any problems.

EDIT: Still work to do, this isn't working consistently.

dominno commented 12 years ago

@swiharta so how you would named changed_object to be more descriptive ? I named it changed because it holds changed version of original object that is available on live.

Why you need this pending column ? what are you trying to do ?

swiharta commented 12 years ago

I "want to check which of a large number of moderated model instances are pending moderation".

I have a calendar app populated with events. I want to have all the events under moderation, and basically I just want to add a CSS class "moderating" to each event on the calendar if there is a pending change (if the corresponding ModeratedObject status is "pending"). In a private message here on GitHub you and I discussed how to do this without a "pending column", but it generated an extra query for each event, so this column would improve performance, that's the point.

As far as the "changed_object" nomenclature, I think its fine if it is what you say it is, it's just that in my limited testing, as above, it seemed like the "changed_object" was actually an "unchanged_object". I need to dig in deeper to understand what's going on, there is a lot of passing around versions of objects and I'm a noob.