我最近在我的游戏模型中添加了一个“用户”字段。我可以创造一个新的游戏,工作良好;当我想允许用户编辑我遇到问题的游戏实例时。我的视图正在调用form = GameForm(request.POST, instance=game)
,其中game = Game.objects.get(pk=id)
。表单预先填充了正确的数据,但在提交表单时,无论是否有更新,表单都不会进行验证。它将其视为POST,但无法进入if form.is_valid()
条件。这是自从我添加用户字段以来。我使用的是默认的Django用户模型,字段名为“owner”。它被设置为ManyToManyField(User, blank=True)
,因为用户可以拥有许多游戏,而游戏可以由许多用户拥有。Django形成了多对多“直通”表,但我不希望用户能够更改谁拥有什么。我在我的forms.py
中有一个隐藏字段,因此用户无法更改它
型号
class Game(models.Model):
game_title = models.CharField(max_length=100,
verbose_name='Game Title',
db_column='game',
blank=False,
null=False,
unique=True)
game_developer = models.CharField(max_length=100,
verbose_name='Developer',
db_column='developer',
blank=True,
null=True)
game_release = models.DateField(max_length=50,
verbose_name='Release Date',
db_column='release_date',
blank=False,
null=True)
rating = models.IntegerField(verbose_name='Game Rating',
db_column='rating',
choices=INT_CHOICES,
blank=True,
null=True)
game_genre = models.CharField(max_length=100,
verbose_name='Genre',
db_column='genre',
blank=False,
null=True,
choices=GENRE_CHOICES)
game_platform = models.CharField(max_length=100,
verbose_name='Game Platform',
db_column='platform',
blank=True,
choices=PLATFORM_CHOICES)
game_esrb = models.CharField(max_length=100,
verbose_name='ESRB Rating',
db_column='esrb',
blank=False,
null=True)
owner = models.ManyToManyField(User, blank=True)
objects = models.Manager()
def __str__(self):
return self.game_title
class Meta:
db_table = 'tbl_games'
verbose_name = 'Game'
查看
# Allows the user to update game information
def editGame(request, id):
# Finds the user selected game by game id
game = Game.objects.get(pk=id)
user = request.user.id
if request.method == 'POST':
print("Seen as POST")
# Create game instance pre-populated into a form
form = GameForm(request.POST, instance=game)
if form.is_valid():
print("Form is valid!")
# Saves the edits without saving to the dB
form.save()
messages.success(request, 'Game successfully updated!')
return redirect('library')
else:
print('Seen as GET')
form = GameForm(instance=game)
print("Page loaded")
context = {'form': form}
return render(request, 'library/editGame.html', context)
表格
class GameForm(ModelForm):
game_esrb = forms.CharField(required=False, widget=HiddenInput)
owner = forms.HiddenInput()
def __init__(self, *args, **kwargs):
super(GameForm, self).__init__(*args, **kwargs)
class Meta:
model = Game
fields = [
'game_title', 'game_developer', 'rating', 'game_release',
'game_genre', 'game_platform', 'game_esrb', 'owner'
]
widgets = {
'rating': Select(attrs={'choices': INT_CHOICES}),
'game_genre': Select(attrs={'choices': GENRE_CHOICES}),
'game_platform': Select(attrs={'choices': PLATFORM_CHOICES}),
'esrb_rating': HiddenInput(),
'owner': HiddenInput
}
help_texts = {
'rating':
'Key: 1 - Bad | 2 - Okay | 3 - Average | 4 - Good | 5 - Great'
}
模板
{% block appcontent %}
<div class="height">
<form method="POST">
{% csrf_token %}
{{ form|crispy }}
<div class="form-btn">
<a class=" btn btn-secondary cancel" type="button" href="{% url 'library' %}">Cancel</a>
<button class="update btn btn-primary" type="submit">Update</button>
</div>
</form>
</div>
{% endblock %}
首先,从分配给GameForm类中字段的列表中删除“所有者”:
原因如下:在模型表单中,只需命名要用作表单中输入字段的游戏字段。在您的情况下,您实际上不希望“所有者”字段成为输入字段,所以请将其从列表中删除。这将实现您声明的不允许用户修改所有者字段的目标
现在让我们查看并修改您的视图:
您可以在视图中执行此操作:“user=request.user.id”这将为属性“user”分配一个int。我猜您想要的是用户对象,而不是int,但这并不清楚,因为您从来没有在视图中的任何位置使用过该属性
需要做的是:视图需要将用户对象连接到游戏对象,然后保存游戏对象。我们已经确保“所有者”不会在表单中显示为输入字段。现在,我们需要手动为该字段提供一个值,然后保存该对象。下面,我们在视图中执行以下is_valid()调用:
总结并澄清:所有这些工作的最终结果是更新了游戏对象。用户通过ModelForm更新值。视图验证这些更改,然后保存表单,从而保存相应的游戏对象。然后,我们手动将用户分配到游戏的“所有者”字段,因为我们有意将该字段保留在表单之外。然后我们再次保存游戏,以便将此更改包含在对象的“最终”状态中
相关问题 更多 >
编程相关推荐