开发者

Editing both sides of M2M in Admin Page

First I'll lay out what I'm trying to achieve in case there's a different way to go about it!

I want to be able to edit both sides of an M2M relationship (preferably on the admin page although if needs be it could be on a normal page) using any of the multi select interfaces.

The problem obviously comes with the reverse side, as the main side (where the relationship is defined) works just fine automagically.

开发者_如何学Go

I have tried some of the advice here to get an inline to appear and that works but its not a very nice interface.

The advice I got on the django mailing list was to use a custom ModelForm. I've got as far as getting a multiselect box to appear but it doesnt seem to be "connected" to anything as it does not start with anything selected and does not save any changes that are made.

Here's the appropriate snippets of code:

#models.py
class Tag(models.Model):
    name = models.CharField(max_length=200)

class Project(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField()
    tags = models.ManyToManyField(Tag, related_name='projects')

#admin.py
class TagForm(ModelForm):
    fields = ('name', 'projects')
    projects = ModelMultipleChoiceField(Project.objects.all(), widget=SelectMultiple())
    class Meta:
        model = Tag

class TagAdmin(admin.ModelAdmin):
    fields = ('name', 'projects')
    form = TagForm

Any help would be much appreciated, either getting the code above to work or by providing a better way to do it!

DavidM


The reason why nothing happens automatically is that the "projects" field is not a part of the Tag model. Which means you have to do all the work yourself. Something like (in TagForm):

def __init__(self, *args, **kwargs):
    super(TagForm, self).__init__(*args, **kwargs)
    if 'instance' in kwargs:
        self.fields['projects'].initial = self.instance.project_set.all()

def save(self, *args, **kwargs):
    super(TagForm, self).save(*args, **kwargs)
    self.instance.project_set.clear()
    for project in self.cleaned_data['projects']:
        self.instance.project_set.add(project)

Note that the code is untested so you might need to tweek it some to get it to work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜