Python Django编辑表格赢得';t在带有用户字段的form.save()上验证

Python Django编辑表格赢得';t在带有用户字段的form.save()上验证,python,django,django-forms,django-views,manytomanyfield,Python,Django,Django Forms,Django Views,Manytomanyfield,我最近在我的游戏模型中添加了一个“用户”字段。我可以创造一个新的游戏,工作良好;当我想允许用户编辑我遇到问题的游戏实例时。我的视图正在调用form=GameForm(request.POST,instance=game)其中game=game.objects.get(pk=id)。表单预先填充了正确的数据,但在提交表单时,无论是否有更新,表单都不会进行验证。它将其视为帖子,但无法进入if表单中。is\u valid()conditional。这是自从我添加用户字段以来。我使用的是默认的Djang

我最近在我的游戏模型中添加了一个“用户”字段。我可以创造一个新的游戏,工作良好;当我想允许用户编辑我遇到问题的游戏实例时。我的视图正在调用
form=GameForm(request.POST,instance=game)
其中
game=game.objects.get(pk=id)
。表单预先填充了正确的数据,但在提交表单时,无论是否有更新,表单都不会进行验证。它将其视为帖子,但无法进入
if表单中。is\u valid()
conditional。这是自从我添加用户字段以来。我使用的是默认的Django用户模型,字段名为“owner”。它被设置为
ManyToManyField(User,blank=True)
,因为用户可以拥有许多游戏,而游戏可以由许多用户拥有。Django形成了多对多“直通”表,但我不希望用户能够更改谁拥有什么。在我的
forms.py中,它是一个隐藏字段,因此用户无法更改它

型号

类游戏(models.Model):
游戏名称=模型。CharField(最大长度=100,
详细名称=‘游戏名称’,
db_column='game',
空白=假,
null=False,
唯一性=真)
游戏开发者=models.CharField(最大长度=100,
详细的\u name='Developer',
db_column='developer',
空白=真,
空=真)
游戏发布=models.DateField(最大长度=50,
详细名称=“发布日期”,
db_column='release_date',
空白=假,
空=真)
rating=models.IntegerField(verbose_name='Game rating',
db_column='rating',
选项=整数选项,
空白=真,
空=真)
游戏类型=模型.CharField(最大长度=100,
冗长的,
db_column='genre',
空白=假,
空=真,
选项=类型(选项)
游戏平台=models.CharField(最大长度=100,
详细名称=‘游戏平台’,
db_column='platform',
空白=真,
选择=平台(选择)
游戏esrb=models.CharField(最大长度=100,
详细的\u name='ESRB评级',
db_column='esrb',
空白=假,
空=真)
所有者=型号.ManyToManyField(用户,空白=真)
objects=models.Manager()
定义(自我):
返回self.game\u标题
类元:
db_表=‘tbl_游戏’
详细名称='游戏'
查看

#允许用户更新游戏信息
def editGame(请求,id):
#按游戏id查找用户选择的游戏
game=game.objects.get(pk=id)
user=request.user.id
如果request.method==“POST”:
打印(“视为邮寄”)
#创建预先填充到表单中的游戏实例
form=GameForm(request.POST,instance=game)
如果form.is_有效():
打印(“表单有效!”)
#保存编辑而不保存到数据库
form.save()
messages.success(请求“游戏已成功更新!”)
返回重定向('库')
其他:
打印('视为获取')
表单=游戏表单(实例=游戏)
打印(“页面加载”)
上下文={'form':form}
返回渲染(请求'library/editGame.html',上下文)
表格

类游戏形式(模型形式):
game_esrb=forms.CharField(必需=False,widget=HiddenInput)
所有者=forms.HiddenInput()
定义初始化(self,*args,**kwargs):
超级(游戏形式,自我)。\uuuuuuuuuuuuuuuuu初始(*args,**kwargs)
类元:
模型=游戏
字段=[
“游戏标题”、“游戏开发者”、“评级”、“游戏发布”,
“游戏类型”、“游戏平台”、“游戏esrb”、“所有者”
]
小部件={
“评级”:选择(属性={'choices':INT_choices}),
“游戏类型”:选择(属性={'choices':类型选择}),
“游戏平台”:选择(属性={'choices':平台选择}),
“esrb_评级”:HiddenInput(),
“所有者”:HiddenInput
}
帮助_文本={
“评级”:
“关键:1-差| 2-好| 3-一般| 4-好| 5-好”
}
模板

{%block-appcontent%}
{%csrf_令牌%}
{{form | crispy}}
更新
{%endblock%}

首先,从分配给游戏窗体类字段的列表中删除“所有者”:

class Meta:
    model = Game
    fields = [
        'game_title', 'game_developer', 'rating', 'game_release',
        'game_genre', 'game_platform', 'game_esrb',      # 'owner' removed
    ]
原因如下:在模型表单中,只需命名要用作表单中输入字段的游戏字段。在您的情况下,您实际上不希望“所有者”字段成为输入字段,所以请将其从列表中删除。这将实现您声明的不允许用户修改所有者字段的目标

现在让我们查看并修改您的视图:

 def editGame(request, id):
     # Finds the user selected game by game id
     game = Game.objects.get(pk=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!")
             form.save()

             game.owner.add(request.user)   # update the game's owner field, assigning the current user
             game.save()

             messages.success(request, 'Game successfully updated!')
             return redirect('library')
  • 您可以在视图中执行此操作:“user=request.user.id”这将为属性“user”分配一个int。我猜您想要的是用户对象,而不是int,但这并不清楚,因为您从来没有在视图中的任何位置使用过该属性

  • 需要做的是:你