【问题标题】:How to make only the owner of a Product able to edit or delete it如何使只有产品的所有者能够编辑或删除它
【发布时间】:2021-03-09 16:19:39
【问题描述】:

我正在开发一个供应商管理系统。我有不同的管理员和不同的供应商,我希望只有添加产品的特定供应商能够编辑或删除它,这样即使其他供应商也无法编辑或删除它。

还有,我们怎样才能让一个产品的所有者在查看所有产品时只能看到编辑或删除产品按钮。

models.py

class User(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(max_length=254, unique=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    # CUSTOM USER FIELDS
    firstname = models.CharField(max_length=30)
    lastname = models.CharField(max_length=30)

class user_type(models.Model):
    is_admin = models.BooleanField(default=False)
    is_supplier = models.BooleanField(default=False)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

class Product(models.Model):
    name = models.CharField(max_length=36)
    price = models.PositiveIntegerField()
    description = models.TextField()
    user = models.ForeignKey(User, on_delete=models.CASCADE)

views.py

@login_required
@supplier_required
def Editproduct(request, pk):
    title = "Edit Product"
    product = Product.objects.get(id=pk)

    form = AddProductForm(instance=product)
    if request.method == 'POST':
        form = AddProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            form.instance.user = request.user
            form.save()
            messages.success(request, "Product Edited Successfully")
            return redirect('product')

    context = {"form":form, "title":title}

    return render(request, "core/editproduct.html", context)

@login_required
@supplier_required
def DeleteProduct(request, pk):
    title = "Delete Product"
    product = Product.objects.get(id=pk)
    try:
        product.delete()
        messages.success(request, "Product Deleted Successfully.")
        return redirect('product')
    except:
        messages.error(request, "Failed to Delete Product.")
        return redirect('product')

products.html

{% for product in all_products %}
<div class="col-md-4">
    <div class="card">
        <img class="card-img-top" style="height: 200px!important;" src="{{product.image.url}}" alt="Card image cap">
        <div class="card-body">
            <div class="card-title mb-3">
                <span>{{product.name}}</span>
                <span style="float: right;">
                    <form action="{% url 'add-favourite' product.id %}" method="post" style="display: inline-flex;">
                        {% csrf_token %}
                        <button type="submit">
                            {% if product.favourited_by_user %}
                                <i style="font-size: 22px!important;" class="fas fa-star m-r-10"></i>
                            {% else %}
                                <i style="font-size: 22px!important;" class="far fa-star m-r-10"></i>
                            {% endif %}
                        </button>
                    </form>
                    {% if request.user.user_type.is_supplier %}
                    <a href="{% url 'edit-product' product.id %}"><i style="font-size: 22px!important;" class="zmdi zmdi-edit m-r-10"></i></a>
                    <a href="{% url 'delete-product' product.id %}"><i style="font-size: 22px!important;" class="zmdi zmdi-delete"></i></a>
                    {% endif %}
                </span>
            </div>
            <p class="card-text">
                <span>Price: {{product.price}}</span>
                <span style="float: right;">Quantity: {{product.quantity}}</span>
            </p>
        </div>
    </div>
</div>
{% endfor %}

【问题讨论】:

  • 添加产品到供应商的外键并编写装饰器检查产品的供应商是否与当前用户相同?
  • 你能提供一个代码吗,我不太明白
  • 虽然看你的代码你有form.instance.user = request.user 你的Product 模型对用户有外键吗?
  • 是的。该行代码将当前登录的用户分配给添加的任何产品,因此他不需要填写哪个供应商拥有该产品的字段。
  • 我在模型中没有看到该字段,请您添加它。

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


【解决方案1】:

您可以过滤user 字段:

from django.shortcuts import get_object_or_404

@login_required
@supplier_required
def Editproduct(request, pk):
    title = 'Edit Product'
    #                            filter on the user &downarrow;
    product = get_object_or_404(Product, id=pk, user=request.user)

    form = AddProductForm(instance=product)
    if request.method == 'POST':
        form = AddProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            form.save()
            messages.success(request, 'Product Edited Successfully')
            return redirect('product')

    context = {'form': form, 'title': title}

    return render(request, 'core/editproduct.html', context)

如果用户不是所有者,他们将看到 HTTP 404 响应。

【讨论】:

  • 在我的模板中,如何让只有产品所有者才能看到产品上的删除或编辑按钮,类似于 stackoverflow cmets 的工作方式。我已经编辑了问题并添加了模板。
  • @coderboy:在模板中,您使用条件{% if product.user == request.user %}... render button{% endif %}。但是通过改变视图,按钮即使显示在模板中也将无法正常工作。
【解决方案2】:

根据documentation,您可以使用obj 参数在User 类中定义自定义has_perm 方法,该参数“检查[...] 此特定对象的权限”:

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(max_length=254, unique=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    # CUSTOM USER FIELDS
    firstname = models.CharField(max_length=30)
    lastname = models.CharField(max_length=30)

    def has_perm(self, perm, obj=None):

        if(perm == 'product.edit_or_delete'):
            if(instanceof(obj, Product)):
                if(obj.owner == self):
                    return True

        return True

class user_type(models.Model):
    is_admin = models.BooleanField(default=False)
    is_supplier = models.BooleanField(default=False)
    user = models.OneToOneField(User, on_delete=models.CASCADE)

class Product(models.Model):
    name = models.CharField(max_length=36)
    price = models.PositiveIntegerField()
    description = models.TextField()
    owner = models.ForeignKey(User)


@login_required
@supplier_required
def Editproduct(request, pk):
    title = "Edit Product"
    product = Product.objects.get(id=pk)

    form = AddProductForm(instance=product)
    if request.method == 'POST':
        form = AddProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            if(request.user.has_perm('product.edit_or_delete',form.instance)):
                form.instance.user = request.user
                form.save()
                messages.success(request, "Product Edited Successfully")
            else:
                messages.error(request, "User does not have permission to this Product.")
            return redirect('product')

    context = {"form":form, "title":title}

    return render(request, "core/editproduct.html", context)

@login_required
@supplier_required
def DeleteProduct(request, pk):
    title = "Delete Product"
    product = Product.objects.get(id=pk)
    try:
        if(request.user.has_perm('product.edit_or_delete',form.instance)):
            product.delete()
            messages.success(request, "Product Deleted Successfully.")
        else:
            messages.error(request, "User does not have permission to this Product.")
        return redirect('product')
    except:
        messages.error(request, "Failed to Delete Product.")
        return redirect('product')

你也可以使用django-role-permissions:

from rolepermissions.permissions import register_object_checker

@register_object_checker()
def edit_or_delete_product(user, product):

    if product.owner == user:
        return True

    return False

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(max_length=254, unique=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    # CUSTOM USER FIELDS
    firstname = models.CharField(max_length=30)
    lastname = models.CharField(max_length=30)


@login_required
@supplier_required
def Editproduct(request, pk):
    title = "Edit Product"
    product = Product.objects.get(id=pk)

    form = AddProductForm(instance=product)
    if request.method == 'POST':
        form = AddProductForm(request.POST, request.FILES, instance=product)
        if form.is_valid():
            if has_object_permission('edit_or_delete_product', user, product):
                form.instance.user = request.user
                form.save()
                messages.success(request, "Product Edited Successfully")
            else:
                messages.error(request, "User does not have permission to this Product.")
            return redirect('product')

    context = {"form":form, "title":title}

    return render(request, "core/editproduct.html", context)

@login_required
@supplier_required
def DeleteProduct(request, pk):
    title = "Delete Product"
    product = Product.objects.get(id=pk)
    try:
        if has_object_permission('edit_or_delete_product', user, product):
            product.delete()
            messages.success(request, "Product Deleted Successfully.")
        else:
            messages.error(request, "User does not have permission to this Product.")
        return redirect('product')
    except:
        messages.error(request, "Failed to Delete Product.")
        return redirect('product')


【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-04
    • 2023-03-28
    相关资源
    最近更新 更多