Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Programmatically replace one django CMS plugin with another

I have a website with many Filer Video plugins that point to YouTube. I've decided that the filer isn't very good for responsive sites (it demands fixed widths) so rather than fix it, I've written my own simple little plugin that does YouTube embeds very easily for variable-width layouts.

So now I have a ton of cmsplugin_filer_video.models.FilerVideo instances that I want to replace with my cmsyoutube.models.YtVideo instances. Looping them is fine but how do I programmatically take out one plugin and replace it (in place) with another?

Thinking out aloud, they're both [eventually] based on CMSPlugin. Can I transpose the parent items into my new class?


This is as far as I've gotten so far. Iterate over the old videos and try to create a new YtVideo (same thing) that points at the same cmsplugin_ptr before deleting the old FilerVideo v...

for v in FilerVideo.objects.all():
    plugin = v.cmsplugin_ptr
    v.cmsplugin_ptr_id = None
    new = YtVideo()
    new.cmsplugin_ptr = plugin
    plugin.plugin_type = 'YoutubePlugin'
    new.youtube_id = re.search(r'v=([^&]+)', v.movie_url).groups(0)[0]
    new.thumbnail = v.image
    new.save()
    plugin.save()
    v.delete()

But TreeBeard gets very upset with this:

NodeAlreadySaved: Attempted to add a tree node that is already in the database

Looks like there's some cascade save logic in there. Any idea how to hotwire this so I can replace the plugin instances without destroying the underlying CMSPlugin tree?

like image 621
Oli Avatar asked Jul 04 '26 12:07

Oli


1 Answers

Had more luck with cms.api.add_plugin. Funny thing is I couldn't get the position to stick. I think it expects wafty "last-child"-style English rather than a numerical input. So I just nail it in a second time after add_plugin.

from cms import api
for v in FilerVideo.objects.all():
    youtube_id = re.search(r'v=([^&]+)', v.movie_url).groups(0)[0]
    position = v.position
    v.delete()
    new = api.add_plugin(v.placeholder, 'YoutubePlugin', v.language, position, v.parent, youtube_id=youtube_id, thumbnail=v.image)
    new.position = position
    new.save()
like image 194
Oli Avatar answered Jul 07 '26 03:07

Oli



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!