Django:在表单中使用request.user

4

我该如何获取用户详情并在表单中使用?在视图中我可以这样做:

currentUser=request.user

但是如果我在表单中使用,会出现以下错误“'request' is not defined”。

class SelectTwoTeams(BootstrapForm):

    currentUser=request.user

    date_joined = currentUser.date_joined.replace(tzinfo=pytz.utc)

    timeless30 = datetime.datetime.now() - datetime.timedelta(seconds=3610)
    timeless30 = timeless30.replace(tzinfo=pytz.utc)

    if date_joined > timeless30:
        currentCharities = forms.ModelChoiceField(queryset=Charity.objects.filter(enabled=1), empty_label=None, widget=forms.Select(attrs={"class":"select-format"}))

    team1 = forms.ModelChoiceField(queryset=StraightredTeam.objects.none(), empty_label=None,
                               widget=forms.Select(attrs={"class":"select-format"}))
    team2 = forms.ModelChoiceField(queryset=StraightredTeam.objects.none(), empty_label=None,
                               widget=forms.Select(attrs={"class":"select-format"}))

提前感谢您的帮助。

以下展示了此表单的init,以防有所帮助。我知道如何使用kwargs访问用户数据:

def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    self.currentSelectedTeam1 = kwargs.pop('currentSelectedTeam1', None)
    self.currentSelectedTeam2 = kwargs.pop('currentSelectedTeam2', None)
    self.currentfixturematchday = kwargs.pop('currentfixturematchday', None)
    self.currentCampaignNo = kwargs.pop('currentCampaignNo', None)
    super(SelectTwoTeams, self).__init__(*args, **kwargs)

    cantSelectTeams = UserSelection.objects.select_related().filter(~Q(fixtureid__fixturematchday=self.currentfixturematchday),campaignno=self.currentCampaignNo, )

    if not cantSelectTeams:
        queryset = StraightredTeam.objects.filter(currentteam = 1).order_by('teamname')
    else:
        queryset = StraightredTeam.objects.filter(currentteam = 1).exclude(teamid__in=cantSelectTeams.values_list('teamselectionid', flat=True)).order_by('teamname')

    teamsAlreadyPlaying = StraightredFixture.objects.filter(soccerseason=1025, fixturematchday=self.currentfixturematchday, fixturedate__lte = timezone.now())
    postponedGames = StraightredFixture.objects.filter(soccerseason=1025, fixturematchday=self.currentfixturematchday,fixturestatus = "P")

    queryset = queryset.exclude(teamid__in=teamsAlreadyPlaying.values_list('home_team_id', flat=True)).order_by('teamname')
    queryset = queryset.exclude(teamid__in=teamsAlreadyPlaying.values_list('away_team_id', flat=True)).order_by('teamname')
    queryset = queryset.exclude(teamid__in=postponedGames.values_list('home_team_id', flat=True)).order_by('teamname')
    queryset = queryset.exclude(teamid__in=postponedGames.values_list('away_team_id', flat=True)).order_by('teamname')

    self.fields['team1'].queryset = queryset
    self.fields['team2'].queryset = queryset
    self.fields['team1'].initial = self.currentSelectedTeam1
    self.fields['team2'].initial = self.currentSelectedTeam2

    self.fields['team1'].label = False
    self.fields['team2'].label = False

    date_joined = user.date_joined.replace(tzinfo=pytz.utc)

    timeless30 = datetime.datetime.now() - datetime.timedelta(seconds=3610)
    timeless30 = timeless30.replace(tzinfo=pytz.utc)

    if date_joined > timeless30:
        self.fields['currentCharities'].label = False

尝试在视图中的 form.save(request) 中发送请求,并覆盖 def save(self, user): 方法。 - Matheus Veleci
请问您能否详细说明一下?在我看来,这里创建了一个表单(form),包括了参数:用户(user)、当前选定的第一支队伍(currentSelectedTeam1)、当前选定的第二支队伍(currentSelectedTeam2)、当前比赛日(currentfixturematchday)和当前活动编号(currentCampaignNo)。 - Alan Tingey
3个回答

15

当模块被加载时,表单类已经定义。这意味着你无法设置currentUser = request.user,因为你还没有访问请求对象的权限。你应该从代码中删除那一行。

正确的做法是重写__init__方法,使其接受user参数。如果你的字段定义取决于user,那么你需要将它们移到__init__方法中。

class SelectTwoTeams(BootstrapForm):
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super(SelectTwoTeams, self).__init__(*args, **kwargs)

        date_joined = self.user.date_joined.replace(tzinfo=pytz.utc)

        timeless30 = datetime.datetime.now() - datetime.timedelta(seconds=3610)
        timeless30 = timeless30.replace(tzinfo=pytz.utc)

        if date_joined > timeless30:
            self.fields['currentCharities'] = forms.ModelChoiceField(queryset=Charity.objects.filter(enabled=1))
        ...

如果user不是必须的,您应该只在弹出时使用None作为默认值。但在您的情况下,它是必需的,因为您在__init__方法中访问了self.user.date_joined。通过将用户存储为self.user,如果需要,您可以在其他方法中访问它。

最后,您需要更改视图以在实例化表单时传递用户。

if request.method == "POST"
    form = SelectTwoTeams(request.POST, user=request.user)
    ...
else:
    form = SelectTwoTeams(user=request.user)

我有与您相同的视图: form = SelectTwoTeams(request.POST,user=request.user,currentSelectedTeam1=currentSelectedTeam1,currentSelectedTeam2=currentSelectedTeam2,currentfixturematchday=fixturematchday,currentCampaignNo=currentCampaignNo)我现在已经拥有与您相同的表单,但是我仍然无法在init之外访问用户... 有什么想法吗? - Alan Tingey
我已经做了这个,但是这些字段被声明在类的根部,而该类没有访问self的权限。我知道我一定做错了什么基本的事情,非常感谢您的时间。 - Alan Tingey
如果字段定义取决于用户,则需要将其移动到__init__方法中。 - Alasdair
谢谢Alasdair,我只需要将它移动到__init__中。感谢其他所有人的帮助。 - Alan Tingey
如果你使用了 super().__init__,那么你需要在 __init__ 中从 kwargs 中弹出 user,否则你会遇到 TypeError 异常。 - Chiheb Nexus

1

您可以覆盖保存方法并在其中发送请求。

viewys.py

if request.method == "POST"
   if forms.is_valid():
       form.save(request=request.user)

在你的forms.py文件中:

def save(self, request=None, *args, **kwargs
    self.currentUser = request.user
    super(SelectTwoTeams, self).save(*args, **kwargs)
    instance.save()
    return instance

0
要在表单中获取任何变量,必须将其作为 kwarg 参数传递,然后在 init 中获取它。
在表单中:
class someForm(forms.ModelForm):
    ...code...

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

        self.Name = kwargs.pop('SomeName')

在你的观点中:

yourform = someForm(request.POST or None, initial={'foo': foo}, SomeName= someVar)

通常尽可能限制依赖性更好,所以如果需要的实际上是一个“用户”,那么只传递一个“用户”,而不是完整的请求(提示:尝试为表单编写一些单元测试...您会发现仅需传递一个“用户”而不是完整请求要容易得多<g>)。 - bruno desthuilliers
同时,一个裸露的 except 子句是非常糟糕的想法 - 只有捕获您期望并愿意和能够处理的最具体的异常(在这里应该是 except KeyError:)。 - bruno desthuilliers
再次确认,你是正确的。我是从一个特定的文件中复制的,在一般情况下最好避免这样做。 - Zartch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接