python - 来自实例的 Django ModelChoiceField 动态查询集
问题描述
我有一个数据集,用户可能需要在其中编辑旧记录,但也需要将选择限制为一组“活动”值。This means the legacy choices need to be added to the queryset of the ModelChoiceField when an instance containing a non-active value is selected.
在我看来,理想的方法是对 ModelChoiceField 进行子类化,但是我似乎无法在 ModelChoiceField 中找到实例数据的插入点。我可以通过在 forms.py 中设置查询集来使其工作,但我有大量字段需要这些字段,并且真的希望有一个更 Pythonic/DRY 的解决方案。
例如:
模型.py
class ActiveChoiceModel(models.Model):
name = models.CharField(max_length=10)
active = models.NullBooleanField(default=False)
class MyModel(models.Model):
fk_activechoicemodel = models.ForeignKey(to='mydb.ActiveChoiceModel')
ModelChoiceField 的查询集应该是:
ActiveChoiceModel.objects.filter(active=True) | ActiveChoiceModel.objects.filter(pk=instance.fk_activechoicemodel.id)
这可以在 forms.py 中实现,如下所示:
Class MyForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
if self.instance.fk_activechoicemodel:
self.fields['fk_activechoicemodel'].queryset = ActiveChoiceModel.objects.filter(active=True) | ActiveChoiceModel.objects.filter(pk=instance.fk_activechoicemodel.id)
关于如何为 10 或 100 的“ActiveChoiceModels”做到这一点的清洁和干燥有什么想法吗?
解决方案
选项1
我认为最好的解决方案是自定义 models.Manager来获取特殊的查询集。但是,真正的工作是使用Q 对象完成的,因此如果您不必在其他任何地方拉取此查询集,则可能只使用 Q 对象。没有你的代码我没有测试过,但它是从我正在运行的自定义管理器修改的,加上这个答案。
# models.py
from django.db import models
from django.db.models import Q
class AvailableChoiceManager(models.Manager):
"""Active choices + existing choice even if it's now inactive.
"""
def get_queryset(self, pk=None):
qs = super().get_queryset() # get every possible choice
current_choice = ChoiceModel.objects.get(pk=pk):
return qs.filter((Q(pk=pk) | Q(active=True))
在您的模型定义中,您需要添加此管理器的一个实例:
# models.ActiveChoiceModel
AvailableChoices=AvailableChoiceManager()
调用:
qs = AvailableChoiceModel.AvailableChoices(pk=pk)
选项 2。
获取活动选项列表:
choice_list = list(Choices.objects.filter(active=True).values_list('id', 'slug'))
if fk.pk not in choice_list:
choice_list.insert(0, (fk.pk, fk.slug))
将小部件的选择属性设置为choice_list
:
self.fields['fk'].widget = forms.Select(
choices=choice_list,
attrs={'pk': 'lug', 'size': 7, 'style': "width:100%"})
推荐阅读
- amazon-web-services - 将文件从 s3 移动到 s3 冰川的方法
- python - 在 HTML 中创建带有页码的动态目录
- vue.js - vuex 安装使我的项目变为空白
- python-3.x - 使用 Python 在 Seaborn 中设置散点图中点的大小
- c++ - 如何无阻塞加入到标准线程
- javascript - 在 HTML 表单中添加 Spotify 链接
- c# - 在我尝试将记录插入我的 SQL Server 时,列名“T001”无效
- ios - Amazon s3 传输实用程序无法在后台运行
- css - 使用 HTML 为按钮创建边框的问题
- docker - 在 Jupyter docker 容器上运行的 Py2neo 函数无法连接到 neo4j docker 容器