Django ModelChoiceField dynamic queryset来自实例

2024-06-26 02:03:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据集,用户可能需要编辑旧记录,但也需要将选择限制为一组“活动”值。这意味着在选择包含非活动值的实例时,需要将遗留选项添加到ModelChoiceField的queryset中。在

在我看来,实现这一点的理想方法是将ModelChoiceField子类化,但是我似乎找不到实例数据插入ModelChoiceField的位置。 我可以通过设置queryset来实现它表单.py但我有大量的领域需要这一点,我真的希望有一个更Python/干的解决方案。在

例如:

在模型.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的查询集应为:

^{pr2}$

这可以在表单.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年的'积极选择模型'?在


Tags: 数据实例py模型self表单modelmodels
1条回答
网友
1楼 · 发布于 2024-06-26 02:03:53

选项1

我认为最好的解决方案是使用custom models.Manager来获取特殊的查询集,但是真正的工作是用一个Q表达式完成的,所以如果您不必在其他地方提取这个queryset,那么可能只使用Q表达式。没有你的代码我还没有测试过,但是它是从我正在运行的自定义管理器中修改的,加上this answer.

# models.py
from django.db import models
from django.db.models import Q

class AvailableChoiceManager(models.Manager):
    """Active choices + existing choice even if its 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))

在模型定义中,需要添加此管理器的实例:

^{pr2}$

调用方式:

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))

将小部件的“选项”属性设置为“选项”列表:

self.fields['fk'].widget = forms.Select(
            choices=choice_list,
            attrs={'pk': 'lug', 'size': 7, 'style': "width:100%"})

我不确定是否有一种方法可以用少于三到四行的代码来实现这一点,但我不认为这是很多。在

相关问题 更多 >