在Django中使用每个FK /用户的数据库对象

时间:2018-02-11 17:24:27

标签: python django forms

我对使用表单处理每个用户的对象有疑问。我想只与与登录用户相关的对象进行交互。

如果我提交表单,它会检查数据库中的每个对象并返回2!当有2个具有相同product_id的对象时出错。 我使用product_id字段作为条形码,每个产品都是唯一的,有些用户使用相同的产品。

我尝试先找到一种方法来隔离用户对象,然后再使用数据库。或者还有另一种方法来处理这个问题吗?

据我所知,objects.filter(user=request.user)无效,因为我需要objects.get将表单字段的barcode_input与某个数据库字段相匹配,以减少量。

我在问这个问题之前经常搜索,但我没有搜索技术关键字。

models.py

class ProductModel(models.Model):
user                = models.ForeignKey(User)
sku                 = models.CharField(max_length=100)
product_id          = models.CharField(max_length=30, unique=False)
category            = models.ForeignKey(ProductCategories, on_delete=models.CASCADE)
quantity            = models.IntegerField(default=0)
amount_sold         = models.IntegerField(default=0)


def __str__(self):
    return self.product_line

forms.py

class ScanProductForm(forms.Form):
barcode_input = forms.CharField(widget=forms.TextInput(attrs={'autofocus': 'autofocus'}))
amount_input = forms.IntegerField(initial=1)

def clean_barcode_input(self):
    barcode_input = self.cleaned_data['barcode_input']
    qs = ProductModel.objects.filter(product_id=barcode_input)

    if qs.exists():
        return barcode_input

    raise forms.ValidationError("Barcode does not exist")

views.py

def barscan_view(request):
if request.method == 'POST':
    form = forms.ScanProductForm(request.POST or None)
    if form.is_valid(): 
        barcode_input = form.cleaned_data.get("barcode_input")
        amount_input = form.cleaned_data.get("amount_input")
        p = ProductModel.objects.get(product_id=barcode_input)
        if p.user.username == request.user.username:
            if p.quantity >= 0 and amount_input <= p.quantity:
                p.amount_sold = F("amount_sold") + amount_input
                p.quantity = F("quantity") - amount_input
                p.save()
                messages.success(request, '%s - %s was successfully scanned' % (p.product_line, p.sku))
                return HttpResponseRedirect('overview/scan/')
            else:
                if p.quantity > 0:
                    messages.error(request, 'Only %s in stock' %p.quantity) 
                elif p.quantity is 0:
                    messages.error(request, 'This product is out of stock')
        else:
            messages.error(request, 'ID does not match any of your stock')
else:
    form = forms.ScanProductForm()
return render(request, 'maninv/scan_product.html', {'form': form})

谢谢,桑德

1 个答案:

答案 0 :(得分:0)

也许稍微重新设计一下您的视图逻辑将帮助您实现所需的结果。您可以将ScanProductForm表单更改为ModelForm ProductModel。然后,您可以先使用ProductModel + barcode_input检索request.user个实例。

<强> forms.py

class ScanProductForm(forms.ModelForm):
    barcode_input = forms.CharField(widget=forms.TextInput(attrs={'autofocus': 'autofocus'}))
    amount_input = forms.IntegerField(initial=1)

    class Meta:
        model = ProductModel
        fields = ('barcode_input', 'amount_input')

    def clean(self):
        cleaned_data = super().clean()
        amount_input = cleaned_data.get('amount_input')
        if self.instance.quantity == 0:
            self.add_error(None, 'This product is out of stock')
        elif amount_input > self.instance.quantity:
            self.add_error(None, 'Only %s in stock' % self.instance.quantity)
        return cleaned_data

    def save(self, commit=True):
        product = super().save(commit=False)
        amount_input = cleaned_data.get('amount_input')
        product.amount_sold = F('amount_sold') + amount_input
        product.quantity = F('quantity') - amount_input
        if commit:
            product.save()
        return product

<强> views.py

def barscan_view(request):
    if request.method == 'POST':

        product = None
        barcode = request.POST.get('barcode_input')
        queryset = ProductModel.objects.filter(product_id=barcode)
        if queryset.exists():
            try:
                # the queryset is already filtered by the barcode
                # now we apply an extra filter to check if this user has the product
                product = queryset.get(user=request.user)
            except ProductModel.DoesNotExist:
                # here we are sure this product exists, but this user doesnt have it in the stock.
                messages.error(request, 'ID does not match any of your stock.')
        else:
            # here we know this product doesnt exist
            messages.error(request, 'Barcode does not exist.')

        if product is not None:
            form = forms.ScanProductForm(request.POST, instance=product)
            if form.is_valid():
                form.save()
                messages.success(request, '%s - %s was successfully scanned' % (product.product_line, product.sku))
                return HttpResponseRedirect('overview/scan/')

    else:
        form = forms.ScanProductForm()
    return render(request, 'maninv/scan_product.html', {'form': form})

但是在一些错误处理方面有一点变化。通过messages.error传达给用户的一些内容现在是非字段错误。