windows form 下拉选项_Django限制表单中ForeignKey对应下拉菜单选项数量的两种经典方法...

e8d5b613062f2dbb0b255a419bd96ee2.png

假如我们有文章Article和类别Category两个模型,其中类别和文章是一对多的关系。我们希望某个用户在使用表单创建或编辑某篇新文章时,表单上类别对应的下拉菜单选项不显示所有类别,而只显示用户自己创建的类别,我们该如何实现?小编我今天就提供两种经典方法供参考。

如果不出意外,Django模型models.py应该是如下所示:

from django.db import models
from django.contrib.auth.models import User

class Article(models.Model):
    """文章模型"""
title = models.CharField('标题', max_length=200, db_index=True)
    author = models.ForeignKey(User, verbose_name='作者', on_delete=models.CASCADE, related_name='articles')
    category = models.ForeignKey('Category', verbose_name='分类', on_delete=models.CASCADE, blank=False, null=False)

    def __str__(self):
        return self.title


class Category(models.Model):
    """类别模型"""
    name = models.CharField('name', max_length=30, unique=True)
    author = models.ForeignKey(User, verbose_name='作者', on_delete=models.CASCADE, blank=True, null=True,)
   
    def __str__(self):
        return self.name

表单文件forms.py应该如下所示。从ArticleForm定义我们可得知,ArticleForm类没有指定显示何种类别,所以默认将显示所有类别。或许你想尝试修改ArticleForm的定义来将类别选项限定于作者自己创建的类别,但却找不到真正的突破口。

from django import forms
from .models import Article, Category


class ArticleForm(forms.ModelForm):
    class Meta:
        model = Article
        exclude = ['author',]

那么答案在哪里?答案在视图里。我们可以在视图里对表单ForeignKey对应下拉菜单选项的内容和数量做出限制。接下来我们将分别介绍如何在基于类的视图和传统函数视图里实现。

基于类的视图(Class-based Views)

原先的视图views.py可能如下所示。 你直接使用ArticleForm,没有对form的各个字段做出任何修改或调整。

@method_decorator(login_required, name='dispatch')
class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'blog/article_form.html'

     # Associate form.instance.user with self.request.user
     def form_valid(self, form):
         form.instance.author = self.request.user
         return super().form_valid(form)

现在我们就要来见证下奇迹的时刻了。通过重写基于类的视图自带的get_context_data方法,你可以对form的任何字段做出修改和限制。比如本例中限定了category对应的queryset仅限于用户自己创建的类别。models.py, forms.py和模板文件什么都不需要修改。

@method_decorator(login_required, name='dispatch')
class ArticleCreateView(CreateView):
    model = Article
    form_class = ArticleForm
    template_name = 'blog/article_form.html'

     def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'].fields['category'].queryset = Category.objects.filter(author=self.request.user)
        return context

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

传统函数视图(Functional Based Views)

如果你喜欢传统的函数视图,你会从下面的代码中获取启发。其中最重要的一行代码莫过于

form.fields['category'].queryset = Category.objects.filter(author=request.user).


@login_required
def article_create(request):
    if request.method == 'POST':
        form = ArticleForm(request.POST)
        if form.is_valid():
            article = form.save(commit=False)
            article.author = request.user  # Set the user object here
            article.save()  # Now you can send it to DB
            return HttpResponseRedirect("/blog/")
       else:
        form = ArticleForm()
        form.fields['category'].queryset = Category.objects.filter(author=request.user)
    return render(request, 'blog/article_create_form.html', {'form': form, })

注意:

本例ArticleForm使用的是ModelForm,由模型创建,所以使用form.fields['category']获取category字段。如果你是自定义的普通form,应使用form.category获取category字段。

小结

如果你想对表单里显示的各个字段的内容或数量做出限制,你应该在视图里操作,而不是表单里操作。记住了吗?

大江狗

2019.12

ee6412897a3179a60f5fb0ad4b34e3be.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值