如何在导航栏中放置django表单,使其显示在每页上?

如何在导航栏中放置django表单,使其显示在每页上?,django,django-forms,django-views,Django,Django Forms,Django Views,我有一个表单,其queryset依赖于request.user,其初始值依赖于会话密钥。主要模型是用户(默认用户模型的轻微修改)和帐户,它们之间存在多对多关系。表单允许用户更改他/她正在查看的帐户,并且该选择必须在用户导航站点时保留。在单个视图中创建表单并传递给单个模板时,表单工作正常,但我希望表单显示在顶部导航栏中,以便用户可以从任何位置更改帐户 表格如下: class ChangeAccountContextForm(forms.ModelForm): def __init__(s

我有一个表单,其queryset依赖于request.user,其初始值依赖于会话密钥。主要模型是用户(默认用户模型的轻微修改)和帐户,它们之间存在多对多关系。表单允许用户更改他/她正在查看的帐户,并且该选择必须在用户导航站点时保留。在单个视图中创建表单并传递给单个模板时,表单工作正常,但我希望表单显示在顶部导航栏中,以便用户可以从任何位置更改帐户

表格如下:

class ChangeAccountContextForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        self.current_account_id = kwargs.pop('account_id')
        super(ChangeAccountContextForm, self).__init__(*args, **kwargs)
        self.fields['account_choices'].queryset = self.user.accounts.all()
        try:
            self.fields['account_choices'].initial = Account.objects.get(id=self.current_account_id)
        except(Account.DoesNotExist):
            self.fields['account_choices'].initial = None
    #queryset and initial are set to None, because they are assigned dynamically in the constructor (see above)
    account_choices = forms.ModelChoiceField(queryset=None, initial=None, label='Account:', widget=forms.Select(attrs={'onChange':'this.form.submit()', 'class': 'custom-select mr-sm-2 ml-2'}), required=True )

    class Meta:
        model = User
        fields = ['account_choices']
这是使用表单的现有视图:

@login_required
def welcome_view(request):
    user = request.user
    context = {}
    accounts = user.accounts.all().order_by('account_name')
    context['accounts'] = accounts
    context['num_accounts'] = len(accounts)

    try:
        account_id = request.session['current_account_id']
    except (KeyError):
        account_id = None

    if request.method == 'POST':
        form = ChangeAccountContextForm(request.POST, user=user, account_id=account_id)
        context['form'] = form
        if form.is_valid():
            new_account_context = form.cleaned_data['account_choices']           
            request.session['current_account_name'] = new_account_context.account_name
            request.session['current_account_id'] = new_account_context.id

    else:
        form = ChangeAccountContextForm(user=user, account_id=account_id)
        context['form'] = form

    return render(request, 'welcome.html', context)
(顺便提一下,会话密钥是在用户登录时设置的。)


考虑到对request.user和会话中存储的变量的依赖性,我不确定如何在每个页面上包含表单,而不在每个视图中重建表单,如上图所示。我想那会管用的,但我相信一定会有一个更干净利落的方法

这是对我自己问题的部分回答。我在这里添加它是因为我认为缺少将表单添加到自定义模板标记的文档

1.)创建名为templatetags的文件夹(当然,使用_init__uuu.py)并添加account_context_form.py(或任何对您有意义的名称)。我的看起来像:

from django import template
from userauth.forms import ChangeAccountContextForm

register = template.Library()

@register.inclusion_tag('account_context_form.html')
def account_context_form(**kwargs):
    user = kwargs['user']
    account_id = kwargs['account_id']
    form = ChangeAccountContextForm(user=user, account_id=account_id)
    return {'account_context_form' : form }
  • 创建一个传递给标记的html文件并保存到templates文件夹。在我的例子中,“account\u context\u form.html”

  • 至于如何实际处理POST请求,请参见我的问题(和我的答案):

    这是对我自己问题的部分回答。我在这里添加它是因为我认为缺少将表单添加到自定义模板标记的文档

    1.)创建名为templatetags的文件夹(当然,使用_init__uuu.py)并添加account_context_form.py(或任何对您有意义的名称)。我的看起来像:

    from django import template
    from userauth.forms import ChangeAccountContextForm
    
    register = template.Library()
    
    @register.inclusion_tag('account_context_form.html')
    def account_context_form(**kwargs):
        user = kwargs['user']
        account_id = kwargs['account_id']
        form = ChangeAccountContextForm(user=user, account_id=account_id)
        return {'account_context_form' : form }
    
  • 创建一个传递给标记的html文件并保存到templates文件夹。在我的例子中,“account\u context\u form.html”
  • 至于如何实际处理POST请求,请参见我的问题(和答案):

    {% load account_context_form %}
    {% account_context_form user=request.user account_id=request.session.current_account_id %}