Django:带有查询字符串指定的预填充和不可编辑字段的 CreateView

标签 django django-class-based-views django-generic-views django-forms

假设我们有一个名为 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我想要一个标准ModelFormOutfit模型,一切都是空白的,一切都是可编辑的。
  • 如果我访问 /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.POSTrequest.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 中以使格式更合适的处理?
  • 如果我想预先指定几件头饰,通过查询字符串传递感觉像 python 列表的正确格式是什么? IE。我应该做 /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/

    相关文章:

    python - Django 基于类的 View

    django-rest-framework - DRF - 如何在 CreateAPIView 中获取创建的对象

    python - UpdateView 不会保存表单,按保存后出现 404 错误

    django - 为django,vue.js,rabbitmq设置docker

    python - django中业务逻辑和数据访问的分离

    django - 在基于类的通用 View CreateView 中访问 request.user 以便在 Django 中设置 FK 字段

    django - 如何使用基于 django 类的 View 发送包含不同模型查询集的 json

    python - Django 通用 View 中 get_context_data 和 queryset 之间的区别?

    python - 如何修复pipenv中的锁定失败?

    python - Django 从分组列表中过滤