如何在CreateView中处理对象引用

时间:2017-02-09 10:39:25

标签: python django python-2.7 django-views

我有一个项目。一件商品可以有很多评论。我希望在项目的上下文中创建评论。因此,我从url捕获pk并将其添加到上下文中。

这是我陷入困境的地方,我不确定如何访问form_valid中的上下文,更重要的是,我关注的是我尝试下去的路径似乎很糟糕。

基本上,当用户准备提交评论时,应用程序将知道它所引用的项目。什么是pythonic / django-onic最方便的方式?

模型

class Item(models.Model):
    name = models.CharField(max_length=100)
    source = models.ForeignKey('Source')   

class Review(models.Model):
    rating = models.CharField(max_length=30)
    value = models.CharField(max_length=30)
    date = models.DateField(auto_now_add=True)
    comment = models.CharField(blank=True,max_length=100) 

    item = models.ForeignKey(Item,blank=True)
    user = models.ForeignKey(User)

网址

url(r'^review/create/item/(?P<itempk>\d+)',views.ReviewCreate.as_view(),name='review_create'),

浏览

class ReviewCreate(CreateView):
    model = Review
    fields = ['rating', 'value', 'comment']

    def get_context_data(self, **kwargs):
        context = super(ReviewCreate, self).get_context_data(**kwargs)
        itempk = self.kwargs['itempk']
        item = get_object_or_404(Item, pk=itempk)
        context['item'] = item
        return context

    def form_valid(self, form):
        review = form.save(commit=False)
        review.user = self.request.user
        context = super(ReviewCreate, self).get_context_data(**kwargs) '''doesn't work'''
        review.item = context['item']

        return super(ReviewCreate, self).form_valid(form)


    template_name = 'food/review_form.html'

1 个答案:

答案 0 :(得分:1)

get_context_data方法是为了返回模板的上下文,所以我同意在form_valid中调用它有点hacky。

您可以在dispatch方法中获取该项目,并将其存储为self.item。然后,您可以在get_context_dataform_valid中找回该项目。

form_valid中,您可以修改form.instance - 这样您就不必使用commit=False进行保存。

class ReviewCreate(CreateView):
    model = Review
    fields = ['rating', 'value', 'comment']

    def dispatch(self, request, *args, **kwargs):
        itempk = self.kwargs['itempk']
        self.item = get_object_or_404(Item, pk=itempk)
        return super(ReviewCreate, self).dispatch(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super(ReviewCreate, self).get_context_data(**kwargs)
        context['item'] = self.item
        return context

    def form_valid(self, form):
        form.instance.user = self.request.user
        form.instance.item = self.item
        return super(ReviewCreate, self).form_valid(form)

    template_name = 'food/review_form.html'