如何根据先前的用户选择在 Django 中预填充(多个)ChoiceField

Posted

技术标签:

【中文标题】如何根据先前的用户选择在 Django 中预填充(多个)ChoiceField【英文标题】:How to pre-populate (Multiple)ChoiceField in Django based on previous user selection 【发布时间】:2021-11-17 13:55:37 【问题描述】:

我设法将用户选择的类别存储并更新到数据库中。现在,一旦用户再次查询表单,我想使用此选择预填充 MultipleChoiceSelect。

所以我当前的表单将始终返回所有可用的类别。如何将用户的个人选择应用于此,以便在 DOM 中预先选择他的最后一个选择?

# Models

class UserCategoryFilter(models.Model):
    """
    Saves the selected category filter by a user
    """
    user = models.ForeignKey(Account, on_delete=models.CASCADE)
    categories_selected = models.CharField(max_length=2000)


class Category(models.Model):
    """
    Model to store all available categories
    """
    poller_category = models.CharField(max_length=30)
# Form

class SelectCategoryForm(forms.Form):
    choices = forms.ModelMultipleChoiceField(queryset=Category.objects.all(),
                                             widget=forms.CheckboxSelectMultiple)
# View

@require_POST
def save_category_filter(request):

    [..]

        # Get the form instance
        filter_form = SelectCategoryForm(request.POST)

        # Form validation
        if filter_form.is_valid():


            # Get the cleaned data
            selection = filter_form.clean()

            # Check if user already has a filter instance
            instance_exists = UserCategoryFilter.objects.filter(user=request.user)

            # If not create, else update
            if not instance_exists:
                filter_instance = UserCategoryFilter(user=request.user,
                                                     categories_selected=selection)
                filter_instance.save()
            else:
                # Update existing instance
                UserCategoryFilter.objects.filter(user=request.user).update(categories_selected=selection)
                pass
        [..]

这是categories_selected中当前保存用户选择的方式:

'choices': <QuerySet [<Category: Sports>, <Category: Lifestyle>]>

【问题讨论】:

你能分享GET的观点吗? 【参考方案1】:

这是用户的选择当前保存在categories_selected中的方式:

'choices': <QuerySet [<Category: Sports>, <Category: Lifestyle>]>

这不是一个友好的数据结构。相反,让我们做["Sports", "Lifestyle"]

# Get the cleaned data
selection = filter_form.clean()
selection = json.dumps([c.poller_category for c in selection['choices']])  # Add this

现在,我们可以json.loads 选择和.filter(poller_category__in=selection)

然后,我们在SelectCategoryForm(initial='choices': choices) 中传递初始选择。

@require_GET
def select_category(request):
    choices = ()
    user_category_filter_queryset = UserCategoryFilter.objects.filter(user=request.user)
    selection = user_category_filter_queryset.values_list('categories_selected', flat=True).first()
    if selection:
        try:
            selection = json.loads(selection)
        except JSONDecodeError:
            pass
        if selection:
            choices = Category.objects.filter(poller_category__in=selection)
    form = SelectCategoryForm(initial=
        'choices': choices,
    )
    return render(request, 'select-category.html', 'form': form)

【讨论】:

【参考方案2】:

您可以在创建表单时设置选择字段的初始值:

filter_form = SelectCategoryForm(
    request.POST, 
    initial='choices': Category.objects.filter(<get_user's_category_here>)
)

您没有共享模型,因此构建查询有点棘手,但只需更改过滤器即可获取用户的当前类别。

【讨论】:

以上是关于如何根据先前的用户选择在 Django 中预填充(多个)ChoiceField的主要内容,如果未能解决你的问题,请参考以下文章

在 Django Admin FilteredSelectmultiple 小部件中预填充选定值

预填充 Django(非模型)表单

如何使用链接从数据库中预填充表单字段?

根据先前的选择填充下拉列表

如何根据同一仪器中先前的复选框结果自动填充 REDCap 复选框

如何在 React Native 应用程序中预填充 TextInput?