首页 > 解决方案 > 过滤表单的 Django 用户选择字段使用

问题描述

我正在做一个困难的 django 项目,但我又被困住了。我在用户配置文件中有一个字段,称为部队:

class UserProfile(models.Model):

    scout_username = models.OneToOneField(User, on_delete=models.CASCADE)
    Group_Choice = Groups.Scout_Groups()
    troop = models.SlugField(max_length=27, choices=Group_Choice, default='None', blank=False)
    date_of_birth = models.DateField(default=date.today)


    def __str__(self):
        return '%s'% (self.scout_username)

def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile = UserProfile.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

然后我有一个表格,它填写发送到我的 stData 模型的数据。在表单中,用户可以选择添加有关另一个用户的详细信息。除了他们只能向具有相同troop详细信息的另一个用户添加详细信息。表格.py

from django import forms
from leaders.models import stData
from django.contrib.auth.models import User
from accounts.models import UserProfileManager, UserProfile

st_username_list=[
    (None, 'Choose a user'),
    (user1, 'user1'),
    (i, 'no progress'),
    ]

class BadgeForm(forms.ModelForm):
    def set_user(self, user):
        global st_username_list
        troop = user.userprofile.troop
        userprofile = UserProfile.objects.all()
        selected_st = userprofile.filter(troop=troop)
        for st in selected_st:
            username = str(st.st_username)
            st_username_list.append((username, username))
    st_username = forms.ChoiceField(choices=st_username_list)
    class Meta:
        model = stData
        fields = ('st_username', 'Pioneer_Badge', 'Explorer_Badge', 'Adventurer_Badge', 'Proficiency_Badge', 'Other_Badge') 

请注意 在上面的示例中,我使用了一个全局变量。我知道这远非理想。由于解释了过滤器的正确方法(在换行后找到),我已经删除了它。我只是出于教育原因为可能发现他们有类似问题的其他人保留这个。

我在我的视图中通过用户,如下所示:

user = request.user
user_form_setting = BadgeForm.set_user(self, user)

模型.py

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

from accounts.st_badge_list import st_List

class stData(models.Model):

    Pioneer_Choices = st_List.Target_Badges()
    Blue_Choices = st_List.Target_Badges()
    Black_Choices = st_List.Target_Badges()
    Proficiency_Choices = st_List.Proficiency_Badges()
    Other_Choice = st_List.Other_Badges()

    Pioneer_Badge = models.CharField(max_length=16, choices=Pioneer_Choices, default='None', blank=True)
    Blue_Star = models.CharField(max_length=16, choices=Blue_Choices, default='None', blank=True)
    Black_Star = models.CharField(max_length=16, choices=Black_Choices, default='None', blank=True)
    Proficiency_Badge = models.CharField(max_length=22, choices=Proficiency_Choices, default='None', blank=True)
    Other_Badge = models.CharField(max_length=27, choices=Other_Choice, default='None', blank=True)


    st_username = models.ForeignKey(User, on_delete=models.CASCADE)
    date = models.DateTimeField(auto_now=True)
    print (User)

    def __str__(self):
        return '%s'% (self.st_username)

我将如何使用它,以便任何具有相同troop详细信息的用户都将出现在 st_username_list 中作为选择?在用代码研究和尝试之后,我得到了: ValueError Cannot assign "'user1'": "stData.st_username" must be a "User" instance. 我希望这不会太混乱。


编辑 好的,所以我发现我可以通过执行过滤 st_username 的选项

def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)
        self.fields['st_username'].queryset = UserProfile.objects.filter(troop='''user's troop''')

问题更新 我现在的主要问题是我无法通过模型中的用户实例。我在这里看到了这个问题。所以我将它添加到我的表单的 init 方法中:

    self.user = kwargs.pop('user')

然而,当我尝试使用用户时,self.user我得到一个无用的错误 KeyError 说user。外壳表明这可能是由于self.user = kwargs.pop(user) 我相信这可能是因为我没有通过用户。因此,当我在视图中调用表单时,我尝试form = BadgeForm(user=request.user)并得到了同样的错误。

我的查询集现在看起来像这样:

self.fields['scout_username'].queryset=UserProfile.objects.filter(troop=user.userprofile.troop)

更多信息: 为了更好地理解问题,我在查询集中传递了一个部队的集合变量。所以在这种情况下

self.fields['scout_username'].queryset=UserProfile.objects.filter(troop='BC')

虽然现在我得到错误 AttributeError: 'BadgeForm' object has no attribute ' name ' shell 将它与我使用表单的表单集链接。我提供的详细信息是:

line 435, in formset_factory
    return type(form.__name__ + 'FormSet', (formset,), attrs)

我希望这对你比对我更有意义!任何帮助将不胜感激!

标签: pythondjangodjango-modelsdjango-forms

解决方案


最后一个问题在于表单集的使用。根据文档,添加 kwargs 的正确方法是这样做:

    BadgeFormsSet = formset_factory(BadgeForm)
    formset = BadgeFormsSet(form_kwargs={'user': request.user})

希望这对其他人有帮助!


推荐阅读