使用 CreateView 在 Django 中保存外键(不是用户对象)
Saving a Foreign Key (that isn't a User object) in Django using a CreateView
TL;DR:我想使用 CreateView class 保存外键——我可以保存我的用户组,但不能保存我自己的模型对象。
Context:我正在编写一个处理组、Posts 和用户的 Django 应用程序。 Post 条目包含组和用户的外键(post 必须属于组和用户)。我希望用户能够从群组页面本身向群组添加 post——即,当他们访问这个新 post 的 CreateView 表单时,不应该有 'Group'场地。
我的问题:我想用CreateView class保存一个新的post对象,并在幕后插入组(来自 slug)和用户(来自 self.request.user)。通常,我使用 form_valid() 方法来执行此操作,它可以很好地插入 User 对象;但是,我不明白为什么我的组对象不会保存。
一些其他信息:
我知道我能够成功地从 kwargs 中的 slug 中获取 Group 对象。我已将此对象分配给 get() 方法中的变量 self.form_group 并且我已确认对象的 'type' 是我的组 class.
的正确实例
我已经尝试 'getting' form_valid() 方法本身中的 Group 对象:仍然没有成功。
我分别在 form_valid() 方法中尝试了注释和未注释的代码块。
型号:
class Post(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE, related_name = 'posts')
title = models.CharField(max_length = 100,default = '')
created_at = models.DateTimeField(auto_now = True)
post_text = models.TextField()
post_text_html = models.TextField(editable = False)
group = models.ForeignKey(Group, on_delete = models.CASCADE, related_name = 'posts', null = True, blank = True)
-
class Group(models.Model):
name = models.CharField(max_length = 255, unique = True)
slug = models.SlugField(allow_unicode = True, unique = True)
description = models.CharField(max_length = 5000, blank = True, default = '')
description_html = models.TextField(editable = False, blank = True, default = '') # Cannot be Edited
members = models.ManyToManyField(User, through = 'GroupMember')
Views.py
class CreatePostInGroup(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
model = Post
fields = ['title', 'post_text']
template_name = 'posts/post_in_group_form.html'
def get(self, request, *args, **kwargs):
print(self.kwargs)
print(type(self.request.user))
self.form_group = get_object_or_404(Group, slug=self.kwargs.get('slug'))
print(type(self.form_group))
return super(CreatePostInGroup, self).get(request, *args, **kwargs)
def form_valid(self, form):
form.instance.user = self.request.user
try:
form.instance.group = self.form_group
except:
return Http404
return super(CreatPostInGroup, self).form_valid(form)
def get_context_data(self, *args, **kwargs):
context = super(CreatePostInGroup, self).get_context_data(*args, **kwargs)
context['group'] = Group.objects.get(slug=self.kwargs.get('slug'))
return context
感谢您的帮助,这让我抓狂!
我认为您的错误是试图调用 super 方法。本质上,如果您查看 form_valid 的作用:
def form_valid(self, form):
"""If the form is valid, save the associated model."""
self.object = form.save()
return super().form_valid(form)
换句话说,在您保存 post 并添加组和用户后,表单会再次保存而不保存,覆盖您的第一次保存。以下是我的建议:
self.object = form.save(commit = False)
self.object.group = self.form_group
self.object.user = self.request.user
self.object.save()
然后使用return redirect()
重定向到您需要去的地方
事实证明问题不在视图或模型文件中,而是在模板中。我的表单将数据发送到我的常规 'new post' CreateView,所以这就是为什么我的 form_valid() 方法从未被调用并且该组从未被插入的原因。
TL;DR:我想使用 CreateView class 保存外键——我可以保存我的用户组,但不能保存我自己的模型对象。
Context:我正在编写一个处理组、Posts 和用户的 Django 应用程序。 Post 条目包含组和用户的外键(post 必须属于组和用户)。我希望用户能够从群组页面本身向群组添加 post——即,当他们访问这个新 post 的 CreateView 表单时,不应该有 'Group'场地。
我的问题:我想用CreateView class保存一个新的post对象,并在幕后插入组(来自 slug)和用户(来自 self.request.user)。通常,我使用 form_valid() 方法来执行此操作,它可以很好地插入 User 对象;但是,我不明白为什么我的组对象不会保存。
一些其他信息:
我知道我能够成功地从 kwargs 中的 slug 中获取 Group 对象。我已将此对象分配给 get() 方法中的变量 self.form_group 并且我已确认对象的 'type' 是我的组 class.
的正确实例我已经尝试 'getting' form_valid() 方法本身中的 Group 对象:仍然没有成功。
我分别在 form_valid() 方法中尝试了注释和未注释的代码块。
型号:
class Post(models.Model):
user = models.ForeignKey(User, on_delete = models.CASCADE, related_name = 'posts')
title = models.CharField(max_length = 100,default = '')
created_at = models.DateTimeField(auto_now = True)
post_text = models.TextField()
post_text_html = models.TextField(editable = False)
group = models.ForeignKey(Group, on_delete = models.CASCADE, related_name = 'posts', null = True, blank = True)
-
class Group(models.Model):
name = models.CharField(max_length = 255, unique = True)
slug = models.SlugField(allow_unicode = True, unique = True)
description = models.CharField(max_length = 5000, blank = True, default = '')
description_html = models.TextField(editable = False, blank = True, default = '') # Cannot be Edited
members = models.ManyToManyField(User, through = 'GroupMember')
Views.py
class CreatePostInGroup(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
model = Post
fields = ['title', 'post_text']
template_name = 'posts/post_in_group_form.html'
def get(self, request, *args, **kwargs):
print(self.kwargs)
print(type(self.request.user))
self.form_group = get_object_or_404(Group, slug=self.kwargs.get('slug'))
print(type(self.form_group))
return super(CreatePostInGroup, self).get(request, *args, **kwargs)
def form_valid(self, form):
form.instance.user = self.request.user
try:
form.instance.group = self.form_group
except:
return Http404
return super(CreatPostInGroup, self).form_valid(form)
def get_context_data(self, *args, **kwargs):
context = super(CreatePostInGroup, self).get_context_data(*args, **kwargs)
context['group'] = Group.objects.get(slug=self.kwargs.get('slug'))
return context
感谢您的帮助,这让我抓狂!
我认为您的错误是试图调用 super 方法。本质上,如果您查看 form_valid 的作用:
def form_valid(self, form):
"""If the form is valid, save the associated model."""
self.object = form.save()
return super().form_valid(form)
换句话说,在您保存 post 并添加组和用户后,表单会再次保存而不保存,覆盖您的第一次保存。以下是我的建议:
self.object = form.save(commit = False)
self.object.group = self.form_group
self.object.user = self.request.user
self.object.save()
然后使用return redirect()
重定向到您需要去的地方
事实证明问题不在视图或模型文件中,而是在模板中。我的表单将数据发送到我的常规 'new post' CreateView,所以这就是为什么我的 form_valid() 方法从未被调用并且该组从未被插入的原因。