假设我们有一个名为 Closet 的应用程序,它有一些模型:
# closet.models.py
class Outfit(models.Model):
shirt = models.ForeignKey(Shirt)
pants = models.ForeignKey(Trouser)
class Shirt(models.Model):
desc = models.TextField()
class Trouser(models.Model):
desc = models.TextField()
class Footwear(models.Model):
desc = models.TextField
使用通用详细信息 View ,可以很容易地制作 URL conf 以获取有关每个详细信息的详细信息:
#urls.py
urlpatterns = patterns('',
url(r'^closet/outfit/(?P<pk>\d+)$', DetailView(model=Outfit), name='outfit_detail'),
url(r'^closet/shirt/(?P<pk>\d+)$', DetailView(model=Shirt), name='shirt_detail'),
url(r'^closet/trouser/(?P<pk>\d+)$', DetailView(model=Trouser), name='trouser_detail'),
url(r'^closet/footwear/(?P<pk>\d+)$', DetailView(model=Footwear), name='footwear_detail'),
)
我接下来要做的是定义将创建每种类型的新对象的 View 。我想用
CreateView
的扩展版本来做到这一点。这将能够处理预填充字段上的数据。具体来说,我想要以下行为:
/closet/outfit/new
我想要一个标准ModelForm
为 Outfit
模型,一切都是空白的,一切都是可编辑的。 /closet/outfit/new/?shirt=1
我想查看我在案例 1) 中看到的所有字段,但我希望衬衫字段预先填充 pk=1 的衬衫。此外,我希望衬衫字段显示为不可编辑。如果表单被提交并被视为无效,当表单重新显示时,我希望衬衫字段继续不可编辑。 /closet/outfit/new/?shirt=1&trouser=2
我想查看我在案例 1) 中看到的所有字段,但现在衬衫和裤子字段都应该预先填充并且不可编辑。 (即只有 footwear
字段应该是可编辑的。)一般来说,这可能吗? IE。查询字符串可以通过这种方式修改显示表单的结构吗?我想以最干燥的方式实现这一点。我的直觉告诉我这对于基于类的 View 应该是可行的,也许会涉及
model_form_factory
但我无法在脑海中理清逻辑。特别是,我不确定是否可以让基于类的 View 访问 request.REQUEST
(即 request.POST
或 request.GET
参数)在 ModelForm
正在 build 中。也许只有当我对锁定的字段使用不同的查询字符串关键字时才有可能。 IE。也许 URL 需要是:
/closet/outfit/new/?lock_shirt=1
和 /closet/outfit/new?lock_shirt=1&lock_trouser=2
.也许如果它这样做了 POST
处理程序将同时收到锁定字段列表(用于在浏览器中显示表单)以及所有模型字段的常规列表,以便实际创建对象。为什么我想要这个:在
footwear_detail
的模板中我希望能够制作一个标签<a href="{% url outfit_new %}?footwear={{object.pk}}>Click to create a new outfit with this footwear!</a>
一般来说,能够链接到其“结构”(不仅仅是值)根据传递的查询字符串而变化的表单将非常有用。
回应 Berislav Lopac 的伟大建议:
所以我继续做了:
class CreateViewWithPredefined(CreateView):
def get_initial(self):
return self.request.GET
这让我得到了我需要的 90%。但让我更详细地说明一下情况。假设我向 Outfit 模型添加了两个字段:
headgear = models.ManyToManyField('headgear')
和 awesomeness_rating = models.FloatField()
.两个问题:
/closet/outfit/new/?awesomeness_rating=10
然后我的表格预填了 [u'10']
而不是仅仅填充 10
.是否有我应该在模板中使用的过滤器或一些可以添加到我的 View 中以使格式更合适的处理? /closet/outfit/new/?headgear=1,2,3
?如果是这样,Django 会正确地确定我想用这些 ID 预先选择 3 件头饰吗? 继续在这方面工作......
class CreateViewWithPredefined(CreateView):
def get_initial(self):
initial = super(CreateView, self).get_initial()
for k, v in self.request.GET.iterlists():
if len(v) > 1:
initial.update({ k : v })
else:
initial.update({ k : v[0] })
return initial
这似乎一石激起千层浪:数字数据从 unicode 强制转换为数字,并在可能的情况下(按预期)将列表展平。需要检查这是否适用于多值字段。
最佳答案
它是 self.request
, CBV 中的任何位置。 :-)
好的,让我让这个答案更全面。基本上,你想要的是get_initial
方法,由 FormMixin 贡献.覆盖它以填充字段的初始值。
关于Django:带有查询字符串指定的预填充和不可编辑字段的 CreateView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17191778/