Как я могу заполнить данные формы по умолчанию с помощью поля ManyToMany?


Хорошо, я уже более 2 часов просматриваю документацию google и Django (а также IRC-канал на freenode), и не смог разобраться в этом.

В принципе, у меня есть модель под названием Room, которая отображается ниже:

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.ForeignKey(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)

У меня также есть forms.py который имеет следующие ModelForm представлять мои Room модель

from django.forms import ModelForm

from partyline_portal.rooms.models import Room


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

Я создаю представление, которое позволяет администраторам редактировать данный объект Room. Вот мой взгляд (так что далеко):

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)

Теперь это представление прекрасно работает, когда я просматриваю страницу. Он показывает все атрибуты формы, и все значения по умолчанию заполняются (когда пользователи делают GET)... За исключением значений по умолчанию для поля ManyToMany 'bans'.

В принципе, если администратор нажимает на объект Room Для редактирования, на странице, на которую он переходит, будут показаны все значения по умолчанию Room, за исключением "запретов". Независимо от того, что я делаю, я не могу найти способ заставить Django отображать в настоящее время "запрещенных пользователей" для Объект Room. Вот строка кода, которую необходимо изменить (из представления):

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!

Должен быть какой-то другой синтаксис, который я должен использовать, чтобы указать значение по умолчанию для поля 'bans'. Я действительно рвал на себе волосы на этом, и определенно был бы признателен за помощь.

Спасибо!

Обновить

Lazerscience на самом деле помог мне найти решение в одном из своих комментариев. В принципе, это работает, если вы передаете список основных ключи. Чтобы заставить его работать, мне пришлось изменить:

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()]

И бац, он мгновенно начал работать (когда я просмотрю страницу, он покажет выбираемый список Caller s, с уже запрещенными абонентами, уже выделенными (выбранными).

1 5

1 ответ:

Вам, вероятно, нужно использовать "initial": Django set default form values