Why do the IDs in many to many join tables change when there is no change.

42 views
Skip to first unread message

Shazwi Suwandi

unread,
Jan 19, 2015, 8:57:16 AM1/19/15
to django...@googlegroups.com
I'm using Swampdragon to provide real time updates to the system since I don't want users to keep refreshing their page to get them. I used the
ModelPublisherRouter which causes me to get any updates to a particular model. 

I currently have an Events model with the following attributes:
class Event(SelfPublishModel, models.Model):
    serializer_class = EventSerializer
    name = models.CharField(max_length=250)
    description = models.CharField(max_length=250)
    location = models.CharField(max_length=250)
    privacy = models.CharField(max_length=250)
    startDate = models.DateField()
    endDate = models.DateField()
    allDay = models.BooleanField(default=False)
    noOfAttendees = models.IntegerField(default=0)
    noOfNonAttendees = models.IntegerField(default=0)
    noOfInvitees = models.IntegerField(default=0)
    eventOwner = models.ForeignKey(User, related_name='eventsOwned')
    eventInvitees = models.ManyToManyField(User, related_name='eventInvitees')
    eventAttendees = models.ManyToManyField(User, related_name='eventAttendees')
    eventNonAttendees = models.ManyToManyField(User, related_name='eventNonAttendees')

As you can see, there are three many to many relationships with the User table. If I edit an event's name and description without doing any 
changes to eventInvitees, eventAttendees or eventNonAttendees, I was expecting just one "publish" from Swampdragon since there is a change
in the Events row. However, it "publishes" the update, 6 more times and I suspect it is because of the rows in the join tables as it does not publish
6 times when I comment out these relationships. 

I then checked the join tables and every time I do an update through the admin UI, even if I did not add or remove users, it changes the primary key 
of the rows, causing the publish from Swampdragon to be done. Is there any way I can avoid having the IDs change?

jonas hagstedt

unread,
Jan 19, 2015, 5:12:34 PM1/19/15
to django...@googlegroups.com
First off: this sounds like a bug, please log an issue on Github with as much info as possible (router, serializer and model etc. if you can)

I would recommend not using `SelfPublishModel` in this scenario, instead publish the event manually.
If you do it manually you lose out on having it publish when you save via admin (but you do get more control over when the publish occur, and you could of course add an action to admin to do this).

Two ways you can publish the model:

Using `publish_data` you could go about it this way


from swampdragon.pubsub_providers.data_publisher import publish_data

def publish_event(event):
serializer = EventSerializer(instance=event)
channel = 'public_events'
publish_data(channel, serializer.serialize())


The "drawback" of this is that you have to know the actual channel you are publishing to, and you wouldn't be able to use the `DataMapper` in JavaScript since it doesn't know if this set of data was a create, delete or an update action (publish_data was made with the intent to publish dictionaries rather than models).

If you use the `DataMapper` in JS, or have lots of subscribers on various channels all relating to the same model, or don't know the channel name, then use `publish_model` instead (this is probably the most recommended way).

`publish_model` will find the channels for you, but requires to know the action (was it an update, was it a delete or was it created?)

from swampdragon.pubsub_providers.model_publisher import publish_model

def publish_event(event):
action = 'created'  # you can use created, updated, deleted
publish_model(event, EventSerializer, action)


So if you have a view where you create/update events you can simply add this (assuming CBV) to your view:

class EventCreateView(CreateView):
model = Event

def form_valid(form):
event = form.save()
publish_event(event)
return HttpResponseRedirect(self.get_success_url())

You could easily modify `publish_event` to take the action as a parameter
Reply all
Reply to author
Forward
0 new messages