hagsteel / swampdragon

swampdragon
Other
557 stars 73 forks source link

SelfPublishModel - Delay created with ManyToManyFields #136

Closed ZuSe closed 9 years ago

ZuSe commented 9 years ago

This is more a question than an issue. If have the following model:

class MyModel(SelfPublishModel, models.Model):
      serializer_class = MyModelSDSerializer
      participants = models.ManyToManyField(Account)  # Receivers

The router looks like:

class MyModelRouter(TokenAuthMixin, ModelPubRouter):
    @login_required
    def subscribe(self, **kwargs):
        print("User subscribed", self.connection.get_user())
        super().subscribe(**kwargs)

    def get_subscription_contexts(self, **kwargs):
        return {'participants__id__exact': self.connection.user.pk}

What happens. Somewhere in the application I create the model from a REST request (could also be done via sd in the future). Now my application adds various participants select by some smart algo to the model. Since it's a ManyToMany Relationship I have the initialize the model first and save it in the database before I can add the participants. This results in 2 write transactions to the database. You can guess the problem, with the first transaction SD sets the action created. Since at this time there is no participant assigned no subscriber is informed. As soon as I add the participants, all subscribers get informed but the action/state is set to updated since the instance was already created in the prior step.

This leads to my datamapper on client side ignoring the object (the first message i receive has state updated, it can't find a respective entry in the array). So my question what is the smartest way to delay the publishment of the create message? Or ask it another way.. is there an option to send a message with a custom action set?

Hope you can help me, otherwise I need to map the data manually on the client side. Thanks in advance!

Best, Patrick

gnzlo789 commented 9 years ago

Hi, I don't know if this will work or if It's the best way but I think you can try to edit the dataMapper.mapUpdated function so, if it didn't change anything call dataMapper.mapCreated, that way (if I am not missing something) it should save your data in the datasource.

Also I think you should use ModelRouter instead of ModelPubRouter, when you are using a SelfPublishModel.

Another way, where you don't have to change the swampdragon sources is to override the method save (and init) of SelfPublishModel, in a new class MySelfPublishModel. And there you can use your own actions without affecting the behavior of other SelfPublishModels. You will have to add new receivers if you are using them.

class MyModel(MySelfPublishModel, models.Model):
    ...

Please forgive my English, and hope it helps.

ZuSe commented 9 years ago

Hi gnzlo,

thanks for your help. I finally decided to do it the other way round and implemented a custom DataMapper based on ES6 Maps (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map). I am using ModelRouter for sure, ModelPub was just for testing. I agree with you, the best fix might be to implement an own router with a modified save method.

Thanks again!