【问题标题】:Django -Join 3 model in queryDjango - 在查询中加入 3 个模型
【发布时间】:2020-11-10 10:58:57
【问题描述】:
class Item(models.Model):
    CATEGORY = (
        ('Gudang Kering', 'Gudang Kering'),
        ('Gudang Basah','Gudang Basah'),
        )
    name = models.CharField(max_length=200,null= True)
    stock = models.IntegerField(default='0', blank=False, null=True)
    category = models.CharField(max_length=200,null= True,choices=CATEGORY)
    description = models.CharField(max_length=200,null= True, blank= True)
    date_created = models.DateTimeField(auto_now_add= True)
    tags = models.ManyToManyField(Tag)

class Issue(models.Model):
    STATUS = (
        ('Pending', 'Pending'),
        ('Granted','Granted'),
        ('Denied','Denied'),
        )
    customer = models.ForeignKey(Customer, null=True, on_delete= models.SET_NULL)
    item = models.ForeignKey(Item, null=True, on_delete= models.SET_NULL)
    quantity = models.IntegerField(default='0', blank=False, null=True)
    date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
    status = models.CharField(max_length=200,null= True, choices=STATUS)


class Receive(models.Model):
    STATUS = (
        ('Pending', 'Pending'),
        ('Granted','Granted'),
        ('Denied','Denied'),
        )
    customer = models.ForeignKey(Customer, null=True, on_delete= models.SET_NULL)
    item = models.ForeignKey(Item, null=True, on_delete= models.SET_NULL)
    quantity = models.IntegerField(default='0', blank=False, null=True)
    date_created = models.DateTimeField(auto_now_add=True, auto_now=False)
    status = models.CharField(max_length=200,null= True, choices=STATUS)

“你好,对不起,我正在尝试学习 django 并想问,如何编写查询来计算对象,如果 2 具有相同的项目和状态授予,它将计算库存 - 数量(问题)+ 数量(接收),我想将该值保存为数据库中库存的新值"

【问题讨论】:

    标签: django django-queryset


    【解决方案1】:
    • 首先获取Item()Customer()的对象,因为它们在Issue()中设置为外键
    • 创建Issue()的对象并为字段赋值
    • 要更新Item.stock,请使用我们已有的Issue.quantityItem.stock
    • 保存实例
    # c_id and i_id should be fetched from post or any other way
    customer_obj = Customer.objects.get(id=c_id)
    item_obj = Item.objects.get(id=i_id)
    
    # create an object of Issue and assign values
    issue_obj = Issue()
    issue_obj.customer = customer_obj 
    issue_obj.item = item_obj
    # like so assign values to other fields also and save Issue object
    issue_obj.save()
    
    # calculate stock and save the Item object
    item_obj.stock = item_obj.stock - issue_obj.quantity
    item_obj.save()
    

    当使用外键时,应将模型类的对象分配给该字段。例如:customer = models.ForeignKey(Customer, null=True, on_delete= models.SET_NULL)Issue() 中的一个字段。为了保存Issue() 的实例,我们需要将Customer() 的对象分配给Issue 对象的customer 字段。

    【讨论】:

    【解决方案2】:

    无需将相同的信息存储两次。它会使这个解决方案更加混乱。您可以在运行时添加这些值。例如:

    解决方案一:你可以直接annotate查询集中数量的值。无需将附加信息存储在 Item 模型的 stock 属性中。例如:

    from django.db.models import Q, F, Sum
    
    items = Item.objects.annotate(issue_q=Sum('issue__quantity', filter=Q(issue__status="GRANTED")).annotate(total=F('stock')-F('issue_q'))
    
    for item in items:
       print(item.total)
    

    方案二:增加显示总值的属性方法:

    class Item(models.Model):
       ...
    
       @property
       def total(self):
          return self.stock - self.item_set.filter(status="GRANTED").aggregate(quantity_s=Sum('quantity'))['quantity_s']
    
    
    for item in Item.objects.all():
       print(item.total)
    

    顺便说一句,这个解决方案的效率不如第一个,因为它会对 DB 进行多次查询。

    【讨论】:

    • 我看到了,例如,如果我希望它有效地进行更改,我将第一个查询放在表单保存方法中,这样只有当我这样保存时数量才会改变?(对不起英语不是我的第一语言)
    • 老实说,你不需要保存任何东西。如果您在视图的某处显示总库存信息,则可以使用此处共享的注释数据。或者您可以根据总值运行验证。我不建议两次保存数据,因为以后会变得更加复杂。如果您不清楚如何使用注释,请考虑第二种方法或阅读 django 文档。谢谢
    • sorry ruddra,你能解释一下quantity_s吗?我得到self.stock是从item表中得到的,但我不知道quantity_s
    猜你喜欢
    • 2020-11-24
    • 1970-01-01
    • 2021-06-10
    • 1970-01-01
    • 2017-10-02
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多