如何使用多对多字段填充默认表单数据?
Posted
技术标签:
【中文标题】如何使用多对多字段填充默认表单数据?【英文标题】:How Can I Populate Default Form Data with a ManyToMany Field? 【发布时间】:2011-02-28 07:37:21 【问题描述】:好的,我已经爬了 2 个多小时的 google 和 Django 文档(以及 freenode 上的 IRC 频道),但一直无法弄清楚这一点。
基本上,我有一个模型叫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
s 默认值。无论我做什么,我都找不到让 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 实际上帮助我在他的一个 cmets 中找到了解决方案。基本上,它的工作方式是传递主键列表。为了让它发挥作用,我必须做出改变:
if room.bans:
defaults['bans'] = room.bans.all() ### this does not work properly!
到
if room.bans:
defaults['bans'] = [b.pk for b in room.bans.all()]
然后 bam,它立即开始工作(当我查看页面时,它将显示Caller
s 的可选列表,已经被禁止的呼叫者已经突出显示(选择)。
【问题讨论】:
如果房间的编辑只能编辑一个字段,只给他们一个字段来编辑并将房间的其余数据显示为显示文本。这也将解决您初始化 M2M 的默认字段的问题 “它不能正常工作”是什么意思?它是在产生一种感觉还是什么也没有? 【参考方案1】:您可能需要使用“初始”:Django set default form values
【讨论】:
'initial' 和 'default' 是一样的,它们都有效。正如我上面所说,代码当前正确设置了所有默认值,除了“bans”字段(这是一个多对多)。这个问题是关于为 ManyToMany 字段设置默认表单值所需的代码。 好吧,我现在无法真正验证这一点,但我想我做过一次,我必须将对象主键传递给它,而不是查询集...... 谢谢,成功了。传入主键列表正是我需要做的。啊!我将用解决方案更新问题。以上是关于如何使用多对多字段填充默认表单数据?的主要内容,如果未能解决你的问题,请参考以下文章
Django admin - 如何在自定义管理表单中为多对多字段添加绿色加号