【问题标题】:Saving a Foreign Key (that isn't a User object) in Django using a CreateView使用 CreateView 在 Django 中保存外键(不是用户对象)
【发布时间】:2018-11-04 05:09:47
【问题描述】:

TL;DR:我想使用 CreateView 类保存外键——我可以保存我的用户组,但不能保存我自己的模型对象。

上下文:我正在编写一个处理组、帖子和用户的 Django 应用程序。帖子条目包含组和用户的外键(帖子必须属于组和用户)。我希望用户能够从群组页面本身向群组添加帖子 - 即当他们访问此新帖子的 CreateView 表单时,不应该有“群组”字段。

我的问题:我想保存一个带有 CreateView 类的新帖子对象,该类在幕后插入 Group(来自 slug)和 User(来自 self.request.user )。通常,我使用 form_valid() 方法来执行此操作,它可以很好地插入 User 对象;但是,我无法弄清楚为什么我的 Group 对象不会保存。

其他一些信息

  • 我知道我能够成功地从 kwargs 中的 slug 中获取 Group 对象。我已将此对象分配给 get() 方法中的变量 self.form_group,并且我已确认该对象的“类型”是我的 Group 类的正确实例。

  • 我已尝试在 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

感谢您的帮助,这让我发疯了!

【问题讨论】:

    标签: python django database django-models django-class-based-views


    【解决方案1】:

    我认为你的错误是试图调用超级方法。本质上,如果您查看 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)
    

    换句话说,在您保存帖子并添加了组和用户后,表单会再次保存,而不会覆盖您的第一次保存。以下是我的建议:

    self.object = form.save(commit = False)
    self.object.group = self.form_group
    self.object.user = self.request.user
    self.object.save()
    

    然后使用return redirect() 重定向到你需要去的任何地方

    【讨论】:

    • 根据 StackOverflow (stackoverflow.com/questions/10382838/…) 上的类似问题,需要 super 调用。此外,我的 User 对象总是成功保存,而不是 Group 对象。
    • 超级调用做了两件事。首先,它保存表单(这是问题所在,也是您需要将其取出的原因。本质上它会覆盖您之前的保存过程)。它所做的另一件重要的事情是它返回一个 HTTP 重定向到视图的成功 URL。您还需要替换它:正如我在上一个答案中提到的,您将需要使用类似的东西:return redirect(self.get_success_url())。如果您不删除(并替换)超级调用,则您尝试使用添加的组和用户保存帖子的尝试将被覆盖,从而导致您的错误。
    • 嗯,我现在已经试过了,但我仍然有同样的问题——保存了用户对象,但没有保存组对象。
    • 好吧,您的代码中没有任何内容可以使组保存。你想在组对象中改变什么?
    • 糟糕,我的意思是:在我试图创建的 Post 对象中,用户成功保存到它,但组(即我分配给变量 self.form_group 的组)没有t.
    【解决方案2】:

    原来问题不在视图或模型文件中,而在模板中。我的表单正在将数据发送到我的常规“新帖子”CreateView,这就是为什么我的 form_valid() 方法从未被调用并且 Group 从未被插入的原因。

    【讨论】:

      猜你喜欢
      • 2015-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-21
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多