fusionbox / django-widgy

A CMS framework for Django built on a heterogenous tree editor.
http://wid.gy
Other
332 stars 52 forks source link

Using ManyToManyFields on a widget is difficult #300

Closed rockymeza closed 9 years ago

rockymeza commented 9 years ago

It's technically possible, but there are things that you have to do.

I don't know if we want to make it automatic or if we just want to document it somewhere, so here's the steps I took to do it on my project:

First add the ManyToManyField on your widget

class MyWidget(Content):
    colors = models.ManyToManyField('Colors')

Unlike some other field types, you don't have to set null=True on this one.

Now you have to override the clone method:

class MyWidget(Content):
    # ...
    def clone(self):
        new = super(MyWidget, self).clone()
        new.colors = self.colors.all()
        return new

We have a nice comment hidden in the long models/base.py file explaining this (but I remembered it, so that was good for me).

Then I thought I was good, but it didn't, because of the implementation of Content.equal, the versioning was working incorrectly.

So then I figured out how to fix the equal method, which is by overriding get_attributes.

class MyWidget(Content):
    # ...
    def get_attributes(self):
        attrs = super(MyWidget, self).get_attributes()
        attrs['colors'] = self.colors.values_list('pk', flat=True)
        return attrs

I wasn't sure what to put in there, but it seemed to work out ok like that. This doesn't seem like it would work out great if the ordering of the colors is unspecified, so I suppose a set would go well there--then again, maybe we should have used the actual model instances?

Now it seems to be working, but I'm not sure how well.

gavinwahl commented 9 years ago

333