【问题标题】:Making a CreateView in Django using kwargs from a different model template使用来自不同模型模板的 kwargs 在 Django 中创建 CreateView
【发布时间】:2018-12-31 21:02:22
【问题描述】:

我无法使用 CreateView 创建对象 review 我不确定我做错了什么。下面是一个简短的介绍

简介:“我的订单”历史页面是用户可以查看他/她购买的所有商品的地方。在订单历史记录页面中,我有一个按钮,可以让买家为卖家留下评论。下面是按钮

<a href="{% url 'accounts:review' username=item.made_by pk=item.pk %}">
   <button class="text-success">Leave Review</button>
</a> 

从这里我得到项目 item.id 和卖家用户名

{% for item in order.items_in_this_order.all %} <!--models below -->
url(r'^(?P<username>[-\w]+)/(?P<pk>\d+)/review/$', views.ReviewCreate.as_view(), name='review'),
{% endfor %}

当我点击留下评论时,网址在地址栏中正确表达。然后它显示一个表格。我输入feedbackratingsfeedback_imagefeedback_video 的其余字段应该在views.py 中进行。在我填写表格并点击提交后。网址仍然正确。但我收到以下错误

IntegrityError at /accounts/nikhil/10/review/
NOT NULL constraint failed: accounts_review.item_id
Request Method: POST
Request URL:    http://127.0.0.1:8000/accounts/nikhil/10/review/
Django Version: 1.11
Exception Type: IntegrityError
Exception Value:    
NOT NULL constraint failed: accounts_review.item_id

下面是 views.py 这是在帐户应用程序中

class ReviewCreate(LoginRequiredMixin, CreateView):
    model = Review
    form_class = ReviewCreateForm

    def form_valid(self, form):
        self.object = form.save(commit=False)
        self.object.review_from = self.request.user
        print(self.object.review_from) #This prints
        self.item = OrderItem.objects.get(pk=self.kwargs.get('pk'))
        print(self.item) #This prints
        self.object.review_for = User.objects.get(username=self.kwargs.get('username'))
        print(self.object.review_for) #This prints
        self.object.save()
        return super().form_valid(form)

下面是 models.py 用于查看模型

class Review (models.Model):
    review_from = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='review_from')
    review_for = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='review_for')
    item = models.ForeignKey(OrderItem, related_name='items')
    created = models.DateTimeField(auto_now_add=True)
    feedback = models.TextField(blank=True, null=True)
    feedback_image = models.ImageField(blank=True, null=True)
    feedback_video = models.FileField(blank=True, null=True)
    rating_choices = (
        ('1', 'One'), ('2', 'Two'), ('3', 'Three'), ('4', 'Four'), ('5', 'Five'),
        ('6', 'Six'), ('7', 'Seven'), ('8', 'Eight'), ('9', 'Nine'), ('10', 'Ten')
    )
    ratings = models.CharField(max_length=2, choices=rating_choices)

    def __str__(self):
        return 'Review from {} to {} for {}'.format(self.review_from, self.review_for, self.item.product)

以下是 OrderItemmodels.py 以防万一

class OrderItem(models.Model):
    product = models.CharField(max_length=350)
    quantity = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='USD Price')
    order = models.ForeignKey(Order, on_delete=models.CASCADE, related_name='items_in_this_order')
    date = models.DateField()
    time_from = models.TimeField()
    time_to = models.TimeField()
    made_by = models.ForeignKey(User, on_delete=models.SET_NULL, blank=True, null=True, related_name='product_by')
    image = models.ImageField()
    order_date = models.DateField(auto_now_add=True)
    picked = models.ManyToManyField(User, blank=True, related_name='item_picked')

【问题讨论】:

    标签: django django-models django-forms django-templates django-views


    【解决方案1】:

    你的 form_valid 方法很奇怪。除此之外,您将项目设置为self.item,它不会在任何地方使用,当然也不会在创建的实例上设置。此外,您可以直接在那里创建并保存对象,然后调用超类方法,该方法将在没有您添加的情况下再次执行此操作。

    您应该在form.instance 上设置所有这些属性,然后让超级方法进行保存:

    def form_valid(self, form):
        form.instance.review_from = self.request.user
        form.instance.item = OrderItem.objects.get(pk=self.kwargs.get('pk'))
        form.instance.review_for = User.objects.get(username=self.kwargs.get('username'))
        return super().form_valid(form)
    

    【讨论】:

    • +1 但可能值得注意的是,OrderItem 应该首先是 filtered 以仅包括用户实际购买的项目。
    • @DanielHepper 订单历史页面显示 OrderItems 与正确的用户,所以当 request.user 点击离开审查。它会选择正确的商品和出售商品的用户
    • @SamirTendulkar 是的,但是恶意用户可以简单地更改 URL 中的 pk。见owasp.org/index.php/Top_10-2017_A5-Broken_Access_Control
    • @DanielHepper 我正在使用form.instance.item = OrderItem.objects.get(pk=self.kwargs.get('pk')) 我如何在同一代码中使用filterget
    • @DanielHepper 谢谢我修复了过滤后的代码以仅包含用户实际购买的项目if self.request.user in form.instance.item.order.buyer: ` form.instance.review_for = User.objects.get(username=self.kwargs.get('用户名'))`super().form_valid(form)return redirect('home')
    猜你喜欢
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2014-08-20
    • 1970-01-01
    • 2014-09-20
    • 2013-03-25
    • 1970-01-01
    • 2016-01-24
    相关资源
    最近更新 更多