我在Django中有一个CreateView,并且尝试使用按以下方式创建的对象。
def get_success_url(self, *args, **kwargs):
team = self.get_team()
match = self.object
if match.home.team == team: lineup = match.home
else: lineup = match.away
return redirect ('matches:update-lineup', kwargs={'pk' : lineup.id})
我只是得到一个错误,说self.object是None
。我认为这意味着该对象尚未保存,那么我该如何实现get_success_url
直到对象被保存然后再使用呢?
编辑 添加了回溯
Traceback:
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
41. response = get_response(request)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/base.py" in view
68. return self.dispatch(request, *args, **kwargs)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/contrib/auth/mixins.py" in dispatch
56. return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
88. return handler(request, *args, **kwargs)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/edit.py" in post
217. return super(BaseCreateView, self).post(request, *args, **kwargs)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/edit.py" in post
183. return self.form_valid(form)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/edit.py" in form_valid
163. return super(ModelFormMixin, self).form_valid(form)
File "/home/henry/Documents/Sites/Development/statmetrix/env/lib/python3.6/site-packages/django/views/generic/edit.py" in form_valid
79. return HttpResponseRedirect(self.get_success_url())
File "/home/henry/Documents/Sites/Development/statmetrix/matches/views.py" in get_success_url
506. if match.home.team == team: lineup = match.home
Exception Type: AttributeError at /matches/1/create-match/
Exception Value: 'NoneType' object has no attribute 'home'
编辑2 已添加整个视图
class CreateMatchView(LoginRequiredMixin, CreateView):
model = Match
form_class = forms.CreateMatchForm
template_name = 'matches/add_match/step1.html'
def get_team(self, *args, **kwargs):
return Team.objects.get(id=self.kwargs['team_id'])
def get_form_kwargs(self, *args, **kwargs):
kws = super(CreateMatchView, self).get_form_kwargs(*args, **kwargs)
kws['team'] = self.get_team()
return kws
def get_context_data(self, *args, **kwargs):
ctx = super(CreateMatchView, self).get_context_data(*args, **kwargs)
ctx['associations'] = Association.objects.all().order_by('country')
ctx['team'] = self.get_team()
return ctx
def get_success_url(self, *args, **kwargs):
team = self.get_team()
match = self.object
if match.home.team == team: lineup = match.home
else: lineup = match.away
return redirect ('matches:update-lineup', kwargs={'pk' : lineup.id})
编辑3 添加了CreateMatchForm
class CreateMatchForm(forms.ModelForm):
side = forms.IntegerField()
opposition = forms.ModelChoiceField(queryset=Team.objects.all())
team = forms.ModelChoiceField(queryset=Team.objects.all())
str_time = forms.CharField()
str_date = forms.CharField()
class Meta:
model = Match
fields = ['str_time','str_date','venue','season','competition','side','opposition','team']
def __init__(self, *args, **kwargs):
team = kwargs.pop('team')
super(CreateMatchForm, self).__init__(*args, **kwargs)
self.fields['opposition'].queryset = Team.objects.filter(association=team.association)
self.fields['season'].initial = team.current_season
self.fields['season'].widget = forms.HiddenInput()
self.fields['competition'].queryset = Competition.objects.filter(association=team.association)
self.fields['team'].initial = team
self.fields['team'].widget = forms.HiddenInput()
def save(self, *args, **kwargs):
team = self.cleaned_data['team']
#We have to then add Lineups so we just take a copy of the most recent, if it exists, or create one if not
if self.cleaned_data['side'] == 1:
home_team = team
away_team = self.cleaned_data['opposition']
else :
away_team = team
home_team = self.cleaned_data['opposition']
home_lineup = Lineup.objects.filter(team=home_team).first()
if home_lineup is None:
#We have no previous lineup to base this lineup on so we select first 11 players from Roster
roster = Roster.objects.filter(team=home_team, season=team.current_season).first()
if roster is None:
#We have no roster and need to create one
create_standard_roster(home_team, team.current_season)
roster = Roster.objects.filter(team=home_team, season=team.current_season).first()
home_lineup = Lineup (team=home_team)
home_lineup.save()
for player in roster.players.all()[:10]:
home_lineup.starters.add(player)
for player in roster.players.all()[11:]:
home_lineup.substitutes.add(player)
else:
home_lineup.pk = None
home_lineup.save()
away_lineup = Lineup.objects.filter(team=away_team).first()
if away_lineup is None:
#We have no previous lineup to base this lineup on so we select first 11 players from Roster
roster = Roster.objects.filter(team=away_team, season=team.current_season).first()
if roster is None:
#We have no roster and need to create one
create_standard_roster(self.away_team, team.current_season)
roster = Roster.objects.filter(team=away_team, season=team.current_season).first()
away_lineup = Lineup (team=self.away_team)
away_lineup.save()
for player in roster.players.all()[:10]:
away_lineup.starters.add(player)
for player in roster.players.all()[11:]:
away_lineup.substitutes.add(player)
else :
away_lineup.pk = None
away_lineup.save()
match = Match (
time = datetime.datetime.strptime(self.cleaned_data['str_date']+'T'+self.cleaned_data['str_time'], '%d %b %YT%H:%M'),
venue = self.cleaned_data['venue'],
season = self.cleaned_data['season'],
competition = self.cleaned_data['competition'],
home = home_lineup,
away = away_lineup
)
match.save()
答案 0 :(得分:2)
Form
(如您的CreateMatchForm
)必须返回在调用.save()
函数时构造/更新的对象。
因此,您应该将表格重写为:
class CreateMatchForm(forms.ModelForm):
# ...
def save(self, *args, **kwargs):
# ...
match.save()
return match
(# ...
仍应包含原始代码,但是引用较长的代码片段不会提高可读性,因此我在答案中将其省略了)
如果忽略此返回,则函数将返回None
(这是Python处理不显式返回任何内容的函数的方式)。
因此,通过“破坏”该合同,self.object
被赋予None
而不是创建的Match
,因此match.home
毫无意义。