当前位置: 首页 > 知识库问答 >
问题:

Django传递自我给模型。设置on_delete

章昊
2023-03-14

我想修改一个外键值,当它从数据库中删除。所以我看了医生,用on_delete=模型。SET(foo)方法.https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.SET

这是我的模型定义

class OrderLine(models.Model):
    product = models.ForeignKey(Product, on_delete=models.SET(getDuplicateProduct), null=True)
    quantity = models.PositiveSmallIntegerField(default=1)
    finalPricePerUnit = models.PositiveIntegerField()
    order = models.ForeignKey(Order, on_delete=models.PROTECT)
    dateCreated = models.DateTimeField(auto_now=False, auto_now_add=True)

这是我的方法,被称为删除

def getDuplicateProduct(orderline):
    productToDelete = orderline.product
    # some logic to generate duplicate copy and returning it

然而这里的问题是,我不能将参数传递给这个方法,这就是为什么我不能知道删除了哪个产品。我还试着在_deletepass self to models.SET()上使用这个应答django模型中指定的信号

我也试过使用信号,但也没用。我似乎找不到合适的解决办法。如果有人对如何实现这一点有想法,请告诉我。

编辑

这是我在信号中使用的代码

@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
    product = kwargs['instance']
    orderlines = product.orderline_set.all()
    #further processing

现在的问题是django也试图删除我的订单行(因为默认的\u delete设置为cascade)。如果我将on_Delete设置为set_NULL,它会将外键设置为NULL。

这是我正在使用的代码

@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
    product = kwargs['instance']
    orderlines = product.orderline_set.all()
    product.name = product.name + ' ' + product.get_type_display()
    newProduct = deepcopy(product)
    newProduct.name = product.name + ' ' + product.get_type_display()
    newProduct.pk=None
    newProduct.id=None
    newProduct.save()
    product.duplicateProductId = newProduct.id
    product.old_orderlines = orderlines
    product.save()


@receiver(post_delete, sender=Product)
def handlePostDelete(sender, **kwargs):
    product = kwargs['instance']
    newProduct = Product.objects.get(id=product.duplicateProductId)
    for orderline in product.old_orderlines:
        orderline.product = newProduct
        orderline.save()

编辑-3发布完整的实施情况。

@receiver(pre_delete, sender=Product)
def handlePreDelete(sender, **kwargs):
    product = kwargs['instance']
    orderlines = product.orderline_set.all()
    shouldCreate=False
    for orderline in orderlines:
        if orderline.order.status>1:
            shouldCreate=True
    product.shouldCreate = shouldCreate
    if shouldCreate:
        product.old_orderlines = orderlines
        product.save()
    else:
        product.save()
        return None


@receiver(post_delete, sender=Product)
def handlePostDelete(sender, **kwargs):
    product = kwargs['instance']
    shouldCreate = product.shouldCreate
    if shouldCreate:
        newProduct = deepcopy(product)
        newProduct.name = product.name + ' ' + product.get_type_display()
        newProduct.pk=None
        newProduct.id=None
        newProduct.save()
        # Do whatever you want with product.old_orderlines
        for orderline in product.old_orderlines:
            orderline.product = newProduct
            orderline.save()            

共有2个答案

何安宜
2023-03-14

支持@ SalARISSUP答案,我认为正确的解决方案,但给你更多的选择,我将张贴此。如果您拥有产品实例,则可以拥有其订单行。例如,如果将相关的\u名称添加到订单行.product中,如下所示:

class OrderLine(models.Model):
    product = models.ForeignKey(Product, related_name='orderlines')

然后,您可以在信号中执行以下操作:

@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
    product = kwargs['instance']
    orderlines = product.orderlines.all()

另一种方法是获取订单行。

朱兴安
2023-03-14

信号是正确的方法。

您可以从信号接收器获取订单行

@receiver(pre_delete, sender=Product)
def getDuplicateProduct(sender, **kwargs):
    product = kwargs['instance']
    orderlines = product.orderline_set.all()
    # orderlines contains all the OrderLines foreign keyed to the product.

orderlines是一个查询集,您可以对其进行迭代或批量更新。

编辑

事实证明,上面建议的方法是行不通的,因为当pre_delete信号发出时,Django已经确定了它需要用on_delete处理哪些相关模型,并将覆盖这些更改。

这种方法会起作用,尽管有点笨重:

首先,在pre_中删除receiver:from copy import copy

@receiver(pre_delete, sender=Product)
def handlePreDelete(sender, **kwargs):
    product = kwargs['instance']
    # Store the OrderLines as a property of the object
    # Have to copy it otherwise it will be empty later
    product.old_orderlines = copy(product.orderline_set.all())

然后,在一个post_delete接收器中:

@receiver(post_delete, sender=Product)
def handlePostDelete(sender, **kwargs):
    product = kwargs['instance']
    # Do whatever you want with product.old_orderlines
    for line in product.old_orderlines:
        # ... 

在这两个事件之间,Django将在订单行上执行SET_NULL(或您配置的任何内容)。

 类似资料:
  • 问题内容: 我正在建立一个包括条目之间关系的通讯簿。我为个人,公司,场地和角色有单独的模型。在我的索引页面上,我想列出每个模型的所有实例,然后对其进行过滤。这样一个人可以轻松地搜索和查找条目。我已经能够使用通用视图列出单个模型,并使用get_extra_context显示另一个模型: 我还可以使用自定义视图列出单个模型: 这是这两个测试的urls.py: 所以我的问题是“如何修改此参数以将更多模型

  • 问题内容: 我有一个猫鼬模型与用户模型有关联,例如 当我实例化一个新模型时,我会做: 模型的构造函数需要使用许多参数,这些参数在架构更改时编写和重构很繁琐。有没有办法做类似的事情: 还是创建帮助器方法以生成JSON对象甚至将userId附加到请求正文的最佳方法?还是我什至没有想到的方式? 问题答案: 或者如果您要将userId复制到req.body中:

  • 问题内容: 是否有可能做类似这样的一个东西,还是其他什么东西? 如果我可以扩展它,那就更好了: 问题答案: 如果和是模型中的字段,则可以使用**运算符将关键字参数传递到字典中。 假设你的模型称为MyModel: 至于第二个问题,字典必须是最后一个参数。同样,并且应该是模型中的字段。

  • 问题内容: 这在Django 1.9中用form_kwargs修复。 我有一个看起来像这样的Django表单: 我称这种形式的东西是这样的: 登录用户在哪里。这按预期工作。 我的问题是,我现在想将此单一表单转换为表单集。我不知道的是在创建表单集时如何将会员信息传递给各个表单。根据文档来制作一个表单集,我需要做这样的事情: 然后我需要这样创建它: 现在如何以这种方式将affiliate = requ

  • 为了使saucelabs代理能够在旧版本的量角器中工作,我们通过在下面的index.js中设置主机和端口来覆盖sendRequest方法: 量角器\node_modules\selenium-webdriver\http\index.js 现在,量角器允许您通过capabilities对象(如下所示)设置代理,该对象应该传递给index.js sendRequest名为'opt_proxy'的新参

  • 我知道接受参数和,所以我已经尝试了2次(失败)来包装函数和args...: a.创建一个C样式的函数,该函数将调用传递给它的对象: 这会在GCC 4.8.5中导致以下错误: /usr/include/c++/4.8.2/functional:在'struct std::_bind_simple(std::_placeholder<1>,int))(int*)>>()>'的实例化中:/usr/inc