开发者

How Can I Populate Default Form Data with a ManyToMany Field?

Ok, I've been crawling google and Django documentation for over 2 hours now (as well as the IRC channel on freenode), and haven't been able to figure this one out.

Basically, I have a model called Room, which is displayed below:

class Room(models.Model):
    """
    A `Partyline` room. Rooms on the `Partyline`s are like mini-chatrooms. Each
    room has a variable amount of `Caller`s, and usually a moderator of some
    sort. Each `Partyline` has many rooms, and it is common for `Caller`s to
    join multiple rooms over the duration of their call.
    """
    LIVE = 0
    PRIVATE = 1
    ONE_ON_ONE = 2
    UNCENSORED = 3
    BULLETIN_BOARD = 4
    CHILL = 5
    PHONE_BOOTH = 6
    TYPE_CHOICES = (
        ('LR', 'Live Room'),
        ('PR', 'Private Room'),
        ('UR', 'Uncensored Room'),
    )

    type = models.CharField('Room Type', max_length=2, choices=TYPE_CHOICES)
    number = models.IntegerField('Room Number')
    partyline = models.Foreig开发者_如何学编程nKey(Partyline)
    owner = models.ForeignKey(User, blank=True, null=True)
    bans = models.ManyToManyField(Caller, blank=True, null=True)

    def __unicode__(self):
        return "%s - %s %d" % (self.partyline.name, self.type, self.number)

I've also got a forms.py which has the following ModelForm to represent my Room model:

from django.forms import ModelForm

from partyline_portal.rooms.models import Room


class RoomForm(ModelForm):
    class Meta:
        model = Room

I'm creating a view which allows administrators to edit a given Room object. Here's my view (so far):

def edit_room(request, id=None):
    """
    Edit various attributes of a specific `Room`. Room owners do not have
    access to this page. They cannot edit the attributes of the `Room`(s) that
    they control.
    """
    room = get_object_or_404(Room, id=id)
    if not room.is_owner(request.user):
        return HttpResponseForbidden('Forbidden.')

    if is_user_type(request.user, ['admin']):
        form_type = RoomForm
    elif is_user_type(request.user, ['lm']):
        form_type = LineManagerEditRoomForm
    elif is_user_type(request.user, ['lo']):
        form_type = LineOwnerEditRoomForm

    if request.method == 'POST':
        form = form_type(request.POST, instance=room)
        if form.is_valid():
            if 'owner' in form.cleaned_data:
                room.owner = form.cleaned_data['owner']

        room.save()
    else:
        defaults = {'type': room.type, 'number': room.number, 'partyline': room.partyline.id}
        if room.owner:
            defaults['owner'] = room.owner.id
        if room.bans:
            defaults['bans'] = room.bans.all() ### this does not work properly!

        form = form_type(defaults, instance=room)

    variables = RequestContext(request, {'form': form, 'room': room})
    return render_to_response('portal/rooms/edit.html', variables)

Now, this view works fine when I view the page. It shows all of the form attributes, and all of the default values are filled in (when users do a GET)... EXCEPT for the default values for the ManyToMany field 'bans'.

Basically, if an admins clicks on a Room object to edit, the page they go to will show all of the Rooms default values except for the 'bans'. No matter what I do, I can't find a way to get Django to display the currently 'banned users' for the Room object. Here is the line of code that needs to be changed (from the view):

defaults = {'type': room.type, 'number': room.number, 'partyline': room.partyline.id}
if room.owner:
        defaults['owner'] = room.owner.id
if room.bans:
        defaults['bans'] = room.bans.all() ### this does not work properly!

There must be some other syntax I have to use to specify the default value for the 'bans' field. I've really been pulling my hair out on this one, and would definitely appreciate some help.

Thanks!

UPDATE

lazerscience actually helped me find the solution in one of his comments. Basically, the way it works is if you pass a list of primary keys. To make it work I had to change:

if room.bans:
        defaults['bans'] = room.bans.all() ### this does not work properly!

to

if room.bans:
        defaults['bans'] = [b.pk for b in room.bans.all()]

And bam, it instantly started working (when I view the page, it will show a selectable list of Callers, with the already banned callers already highlighted (selected).


You probably need to use "initial": Django set default form values

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜