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 相关文章推荐
Python可跨平台实现获取按键的方法
Mar 05 Python
使用Python中的线程进行网络编程的入门教程
Apr 15 Python
python 二分查找和快速排序实例详解
Oct 13 Python
tensorflow构建BP神经网络的方法
Mar 12 Python
Django如何自定义分页
Sep 25 Python
Python弹出输入框并获取输入值的实例
Jun 18 Python
python数据挖掘需要学的内容
Jun 23 Python
Keras使用ImageNet上预训练的模型方式
May 23 Python
Python Pandas list列表数据列拆分成多行的方法实现
Dec 14 Python
python读取excel数据并且画图的实现示例
Feb 08 Python
Python爬虫实战之爬取携程评论
Jun 02 Python
pytorch 运行一段时间后出现GPU OOM的问题
Jun 02 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中mysql模块部分功能的简单封装
2011/09/30 PHP
php连接mssql的一些相关经验及注意事项
2013/02/05 PHP
php实现统计目录文件大小的函数
2015/12/25 PHP
php魔法函数与魔法常量使用介绍
2017/07/23 PHP
php递归函数怎么用才有效
2018/02/24 PHP
Laravel 集成 Geetest验证码的方法
2018/05/14 PHP
php实现将数据做成json的格式给前端使用
2018/08/21 PHP
用js+xml自动生成表格的东西
2006/12/21 Javascript
jQuery Ajax中的事件详细介绍
2015/04/16 Javascript
jquery操作angularjs对象
2015/06/26 Javascript
javascript类型系统——日期Date对象全面了解
2016/07/13 Javascript
Angular的事件和表单详解
2016/12/26 Javascript
Mac下使用charles遇到的问题以及解决办法
2017/01/10 Javascript
深入理解Webpack 中路径的配置
2017/06/17 Javascript
VueJS事件处理器v-on的使用方法
2017/09/27 Javascript
JavaScript递归函数解“汉诺塔”算法代码解析
2018/07/05 Javascript
layui将table转化表单显示的方法(即table.render转为表单展示)
2019/09/24 Javascript
vue+axios 拦截器实现统一token的案例
2020/09/11 Javascript
[43:24]2018DOTA2亚洲邀请赛3月29日 小组赛A组 LGD VS Liquid
2018/03/30 DOTA
Python去掉字符串中空格的方法
2014/03/11 Python
基于Python的身份证号码自动生成程序
2014/08/15 Python
python numpy和list查询其中某个数的个数及定位方法
2018/06/27 Python
用Python徒手撸一个股票回测框架搭建【推荐】
2019/08/05 Python
Python使用GitPython操作Git版本库的方法
2020/02/29 Python
jupyter notebook运行命令显示[*](解决办法)
2020/05/18 Python
python右对齐的实例方法
2020/07/05 Python
Python实现对word文档添加密码去除密码的示例代码
2020/12/29 Python
CSS3教程(3):border-color网页边框色彩
2009/04/02 HTML / CSS
CSS3盒子模型详解
2013/04/24 HTML / CSS
CSS3 transforms应用于背景图像的解决方法
2019/04/16 HTML / CSS
Viking比利时:购买办公用品
2019/10/30 全球购物
光电信息专业应届生求职信
2013/10/07 职场文书
工程部经理岗位职责
2015/02/02 职场文书
会议主持词开场白
2015/05/28 职场文书
《艾尔登法环》1.03.3补丁上线 碎星伤害调整
2022/04/06 其他游戏
使用Ajax实现进度条的绘制
2022/04/07 Javascript