我有一个使用Django 2.2.4的项目。
我的Django模型叫做Company。
我使用post_save信号来确保一旦创建新的Company,就会创建一个名为"Billing"的新模型实例,并将其与该公司关联。其中包含公司的计费信息。这很好地起到作用。
由于我的Billing对象与Company相关联,并且我使用了on_delete=models.CASCADE,所以一旦删除公司,与该公司相关联的Billing对象也将自动删除。这也很好地起到作用。
由于每个公司的Billing对象现在都会随着公司的自动创建和删除,因此,管理员使用Django Admin Web界面从未需要手动创建或删除Billing对象。我想将此功能隐藏起来,不让他们看到。
通常,防止Django Admin允许某人添加或删除对象的常见方法是在admin.py中将此内容添加到该模型的ModelAdmin中。
这样做可以隐藏管理员手动创建或删除计费对象实例的能力,但有一个负面影响:Django管理员用户无法再删除公司。当删除公司时,Django会查找所有需要一并删除的关联对象,注意到用户无权删除关联的计费对象,并阻止用户删除公司。
虽然我不希望Django管理员用户手动创建或删除Billing模型的实例,但我仍希望他们能够删除整个公司,这将导致与该公司相关联的Billing模型实例被删除。
在我的情况下,防止用户删除Billing模型实例并不是一项安全功能,而是旨在通过不让数据库处于存在公司但不存在计费对象的状态来防止混乱。显然,Django不会对此感到困惑,但它可能会让用户感到困惑。
有没有解决方法?
更新:
设置了“has_delete_permission”后,如果您尝试通过Django Admin删除公司,则会收到以下消息: 没有抛出任何异常。至少没有未被捕获的异常,并出现在Django日志中。
我的模型看起来像这样:
AutoOneToOneField是django-annoying的一部分。它确保如果您运行MyCompany.billing,并且尚未存在相关联的billing对象,则会自动创建一个对象,而不会引发异常。这里可能不需要,因为我在创建公司时会自动创建对象,但这不会有害,并确保我的代码永远不需要担心相关对象不存在。
还要注意,我没有覆盖我的Billing模型的delete函数。
class BillingAdmin(admin.ModelAdmin):
...
# Prevent deletion from admin portal
def has_delete_permission(self, request, obj=None):
return False
# Prevent adding from admin portal
def has_add_permission(self, request, obj=None):
return False
这样做可以隐藏管理员手动创建或删除计费对象实例的能力,但有一个负面影响:Django管理员用户无法再删除公司。当删除公司时,Django会查找所有需要一并删除的关联对象,注意到用户无权删除关联的计费对象,并阻止用户删除公司。
虽然我不希望Django管理员用户手动创建或删除Billing模型的实例,但我仍希望他们能够删除整个公司,这将导致与该公司相关联的Billing模型实例被删除。
在我的情况下,防止用户删除Billing模型实例并不是一项安全功能,而是旨在通过不让数据库处于存在公司但不存在计费对象的状态来防止混乱。显然,Django不会对此感到困惑,但它可能会让用户感到困惑。
有没有解决方法?
更新:
设置了“has_delete_permission”后,如果您尝试通过Django Admin删除公司,则会收到以下消息: 没有抛出任何异常。至少没有未被捕获的异常,并出现在Django日志中。
我的模型看起来像这样:
class Company(Group):
...
class Billing(models.Model):
company = AutoOneToOneField('Company', on_delete=models.CASCADE, blank=False, null=False, related_name="billing")
monthly_rate = models.DecimalField(max_digits=10, decimal_places=2, default=0, blank=False, null=False)
# Create billing object for a company when it is first created
@receiver(post_save, sender=Company)
def create_billing_for_company(sender, instance, created, *args, **kwargs):
if created:
Billing.objects.create(company=instance)
AutoOneToOneField是django-annoying的一部分。它确保如果您运行MyCompany.billing,并且尚未存在相关联的billing对象,则会自动创建一个对象,而不会引发异常。这里可能不需要,因为我在创建公司时会自动创建对象,但这不会有害,并确保我的代码永远不需要担心相关对象不存在。
还要注意,我没有覆盖我的Billing模型的delete函数。
Billing
模型的“添加表单模板” 。 - dirkgroten