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 相关文章推荐
Django数据库操作的实例(增删改查)
Sep 04 Python
python简单实例训练(21~30)
Nov 15 Python
Python将多个excel文件合并为一个文件
Jan 03 Python
Python爬虫框架scrapy实现的文件下载功能示例
Aug 04 Python
在python中pandas的series合并方法
Nov 12 Python
python对视频画框标记后保存的方法
Dec 07 Python
Python3字符串encode与decode的讲解
Apr 02 Python
python 批量修改 labelImg 生成的xml文件的方法
Sep 09 Python
对tensorflow中tf.nn.conv1d和layers.conv1d的区别详解
Feb 11 Python
pycharm设置python文件模板信息过程图解
Mar 10 Python
详解python程序中的多任务
Sep 16 Python
python读写数据读写csv文件(pandas用法)
Dec 14 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+DBM的同学录程序(1)
2006/10/09 PHP
适合PHP初学者阅读的4本经典书籍
2016/09/23 PHP
新页面打开实际尺寸的图片
2006/08/25 Javascript
Javascript 判断函数类型完美解决方案
2009/09/02 Javascript
IE与Firefox在JavaScript上的7个不同写法小结
2009/09/14 Javascript
jQuery :nth-child前有无空格的区别分析
2011/07/11 Javascript
提高jQuery性能优化的技巧
2015/08/03 Javascript
js实现简洁的滑动门菜单(选项卡)效果代码
2015/09/04 Javascript
Jquery轮播效果实现过程解析
2016/03/30 Javascript
JavaScript中获取时间的函数集
2016/08/16 Javascript
想学习javascript JS和jQuery哪个重要 先学哪个
2016/12/11 Javascript
微信小程序获取循环元素id以及wx.login登录操作
2017/08/17 Javascript
通过一个简单的例子学会vuex与模块化
2017/11/22 Javascript
element-ui表格数据转换的示例代码
2018/08/24 Javascript
Nginx设置为Node.js的前端服务器方法总结
2019/03/27 Javascript
原生js通过一行代码实现简易轮播图
2019/06/05 Javascript
JS算法教程之字符串去重与字符串反转
2020/12/15 Javascript
打印出python 当前全局变量和入口参数的所有属性
2009/07/01 Python
Scrapy的简单使用教程
2017/10/24 Python
Python list列表中删除多个重复元素操作示例
2019/02/27 Python
Python安装及Pycharm安装使用教程图解
2019/09/20 Python
python3.6、opencv安装环境搭建过程(图文教程)
2019/11/05 Python
Python综合应用名片管理系统案例详解
2020/01/03 Python
详解pytorch tensor和ndarray转换相关总结
2020/09/03 Python
python自动化办公操作PPT的实现
2021/02/05 Python
css3 iphone玻璃透明气泡完美实现
2013/03/20 HTML / CSS
html5中audio支持音频格式的解决方法
2018/08/24 HTML / CSS
洲际酒店集团美国官网:IHG美国
2017/11/16 全球购物
Cotton On南非:澳洲时尚平价品牌
2018/06/28 全球购物
网上开店必备创业计划书
2014/01/26 职场文书
CAD制图设计师自荐信
2014/01/29 职场文书
设计专业毕业生求职信
2014/06/25 职场文书
辩论赛开场白大全(主持人+辩手)
2015/05/29 职场文书
教师素质教育心得体会
2016/01/19 职场文书
社区志愿者服务心得体会
2016/01/22 职场文书
Python使用DFA算法过滤内容敏感词
2022/04/22 Python