Django 表单模型选择框如何使用分组


Posted in Python onMay 16, 2019

起步

Django 表单中有两种字段类型可以使用选择框: ChoiceFieldModelChoiceField

对于 ChoiceField 的基本使用是:

class ExpenseForm(forms.Form):
  CHOICES = (
    (11, 'Credit Card'),
    (12, 'Student Loans'),
    (13, 'Taxes'),
    (21, 'Books'),
    (22, 'Games'),
    (31, 'Groceries'),
    (32, 'Restaurants'),
  )
  date = forms.DateField()
  category = forms.ChoiceField(choices=CHOICES)

它能渲染出:

Django 表单模型选择框如何使用分组

使用分组下拉框

还可以使用如下方式生成 <optgourp> 标签:

class ExpenseForm(forms.Form):
  CHOICES = (
    ('Debt', (
      (11, 'Credit Card'),
      (12, 'Student Loans'),
      (13, 'Taxes'),
    )),
    ('Entertainment', (
      (21, 'Books'),
      (22, 'Games'),
    )),
    ('Everyday', (
      (31, 'Groceries'),
      (32, 'Restaurants'),
    )),
  )
  date = forms.DateField()
  category = forms.ChoiceField(choices=CHOICES)

能够渲染为:

Django 表单模型选择框如何使用分组

分组模型下拉框

如果使用的是 ModelChoiceField ,那抱歉,Django本身没有提供解决方案。

在 https://code.djangoproject.com/ticket/27331 中提供了一个很好的解决方案。

首先为需要分类的类型创建模型,在另一个模型中用外键关联它:

from django.db import models

class Category(models.Model):
  name = models.CharField(max_length=30)
  parent = models.ForeignKey('Category', on_delete=models.CASCADE, null=True)

  def __str__(self):
    return self.name

class Expense(models.Model):
  amount = models.DecimalField(max_digits=10, decimal_places=2)
  date = models.DateField()
  category = models.ForeignKey(Category, on_delete=models.CASCADE)

  def __str__(self):
    return self.amount

其次,创建一个新的表单 Field 类型:

from functools import partial
from itertools import groupby
from operator import attrgetter

from django.forms.models import ModelChoiceIterator, ModelChoiceField

class GroupedModelChoiceIterator(ModelChoiceIterator):
  def __init__(self, field, groupby):
    self.groupby = groupby
    super().__init__(field)

  def __iter__(self):
    if self.field.empty_label is not None:
      yield ("", self.field.empty_label)
    queryset = self.queryset
    # Can't use iterator() when queryset uses prefetch_related()
    if not queryset._prefetch_related_lookups:
      queryset = queryset.iterator()
    for group, objs in groupby(queryset, self.groupby):
      yield (group, [self.choice(obj) for obj in objs])

class GroupedModelChoiceField(ModelChoiceField):
  def __init__(self, *args, choices_groupby, **kwargs):
    if isinstance(choices_groupby, str):
      choices_groupby = attrgetter(choices_groupby)
    elif not callable(choices_groupby):
      raise TypeError('choices_groupby must either be a str or a callable accepting a single argument')
    self.iterator = partial(GroupedModelChoiceIterator, groupby=choices_groupby)
    super().__init__(*args, **kwargs)

最后,在表单中可以如下进行使用:

from django import forms
from .fields import GroupedModelChoiceField
from .models import Category, Expense

class ExpenseForm(forms.ModelForm):
  category = GroupedModelChoiceField(
    queryset=Category.objects.exclude(parent=None), 
    choices_groupby='parent'
  )

  class Meta:
    model = Expense
    fields = ('amount', 'date', 'category')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
使用C语言扩展Python程序的简单入门指引
Apr 14 Python
Python面向对象之继承和组合用法实例分析
Aug 27 Python
python抓取京东小米8手机配置信息
Nov 13 Python
Python3字符串encode与decode的讲解
Apr 02 Python
Python通用函数实现数组计算的方法
Jun 13 Python
教你如何编写、保存与运行Python程序的方法
Jul 12 Python
Python +Selenium解决图片验证码登录或注册问题(推荐)
Feb 09 Python
Python 开发工具PyCharm安装教程图文详解(新手必看)
Feb 28 Python
python如何进入交互模式
Jul 06 Python
python线程里哪种模块比较适合
Aug 02 Python
对Pytorch 中的contiguous理解说明
Mar 03 Python
Python多个MP4合成视频的实现方法
Jul 16 Python
详解pandas如何去掉、过滤数据集中的某些值或者某些行?
May 15 #Python
详解Python列表赋值复制深拷贝及5种浅拷贝
May 15 #Python
Python 20行简单实现有道在线翻译的详解
May 15 #Python
Python中的字符串切片(截取字符串)的详解
May 15 #Python
python3 property装饰器实现原理与用法示例
May 15 #Python
详解Python下载图片并保存本地的两种方式
May 15 #Python
Python常用模块之requests模块用法分析
May 15 #Python
You might like
聊天室php&amp;mysql(三)
2006/10/09 PHP
Yii2框架使用计划任务的方法
2016/05/25 PHP
JS 建立对象的方法
2007/04/21 Javascript
javascript SocialHistory 检查访问者是否访问过某站点
2008/08/02 Javascript
用javascript作一个通用向导说明
2011/08/30 Javascript
基于jquery实现的文字向上跑动类似跑马灯的效果
2014/06/17 Javascript
JavaScript不使用prototype和new实现继承机制
2014/12/29 Javascript
js实现头像图片切割缩放及无刷新上传图片的方法
2015/07/17 Javascript
详解Vue.js动态绑定class
2016/12/20 Javascript
详解angularjs 关于ui-router分层使用
2017/06/12 Javascript
Vue如何实现响应式系统
2018/07/11 Javascript
使用Vue 自定义文件选择器组件的实例代码
2020/03/04 Javascript
js获取图片的base64编码并压缩
2020/12/05 Javascript
elementui实现预览图片组件二次封装
2020/12/29 Javascript
[49:05]Newbee vs TNC 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Python中规范定义命名空间的一些建议
2016/06/04 Python
Python函数和模块的使用总结
2019/05/20 Python
如何运行.ipynb文件的图文讲解
2019/06/27 Python
将python运行结果保存至本地文件中的示例讲解
2019/07/11 Python
pytorch中tensor张量数据类型的转化方式
2019/12/31 Python
python opencv把一张图片嵌入(叠加)到另一张图片上的实现代码
2020/06/11 Python
Django解决frame拒绝问题的方法
2020/12/18 Python
欧洲第一的摇滚和金属乐队服装网站:EMP
2017/10/26 全球购物
Rag & Bone官网:瑞格布恩高级成衣
2018/04/19 全球购物
俄罗斯童装网上商店:BebaKids
2020/06/06 全球购物
机电一体化专业推荐信
2013/12/03 职场文书
初婚初育证明
2014/01/14 职场文书
《四季》教学反思
2014/04/08 职场文书
《厄运打不垮的信念》教学反思
2014/04/13 职场文书
超市开店计划书
2014/09/15 职场文书
重阳节标语大全
2014/10/07 职场文书
学校党的群众路线教育实践活动整改措施
2014/10/25 职场文书
升职自我推荐信范文
2015/03/25 职场文书
民事撤诉申请书范本
2015/05/18 职场文书
团结友爱主题班会
2015/08/13 职场文书
解决Pytorch修改预训练模型时遇到key不匹配的情况
2021/06/05 Python