【问题标题】:Django models - create items which have to pass various tasksDjango 模型 - 创建必须通过各种任务的项目
【发布时间】:2017-10-21 19:16:08
【问题描述】:

我正在尝试为以下场景创建模型:

一个项目被交付并且必须以一定的顺序通过各种任务。 一旦项目通过任务,该任务就会被标记为已完成。 任务的名称是预先知道的。

例如:

  • 创建项目
  • 任务 1“注册项目”
  • 任务 2“安装项目”
  • 任务 3“检查项目日志”

我从一个像这样的简单模型开始,但对我来说它看起来非常静态,而不是我真正想要的。

models.py

class Item(models.Model):

    item_id = models.PositiveIntegerField()
    item_priority = models.PositiveSmallIntegerField(default=2)
    item_date_created = models.DateField(auto_now_add=True)

    task1_name = models.CharField(max_length=128)
    task1_done_by = models.CharField(max_length=64, blank=True)
    task1_done_date = models.DateField(null=True, blank=True)

    task2_name = models.CharField(max_length=128)
    task2_done_by = models.CharField(max_length=64, blank=True)
    task2_done_date = models.DateField(null=True, blank=True)

    # ... next 20 tasks

    def __str__(self):
        return str(self.item_id)

尝试使用关系字段,例如一个多对多字段来预定义任务,我最终得到了这个:

class Task(models.Model):

    name = models.CharField(max_length=128)
    done_by = models.CharField(max_length=64, blank=True)
    done_date = models.DateField(null=True, blank=True)


class Item(models.Model):

    item_id = models.PositiveIntegerField()
    item_priority = models.PositiveSmallIntegerField(default=2)
    item_date_created = models.DateField(auto_now_add=True)
    tasks = models.ManyToManyField(Task)

但是,如果我创建两个具有相同任务的项目并将第一个项目的任务标记为已完成,那么第二个项目中的任务也会被标记为已完成 -- 这不是我想要的。

如何将任务分配给特定项目?或者哪种其他模型最适合我的场景?

【问题讨论】:

    标签: django django-models


    【解决方案1】:

    为了在对象创建时执行代码,您通常会覆盖 save() 方法。所以当一个 Item 被创建时,在 save() 方法中你创建并动态链接 Tasks 到 Item.tasks

    class Item(models.Model):
        item_id = models.PositiveIntegerField()
        item_priority = models.PositiveSmallIntegerField(default=2)
        item_date_created = models.DateField(auto_now_add=True)
    
        # remove m2m !!!
    
        def save(self, *args, **kwargs):
            # If it has no pk then it is a *new* item
            if not self.pk:
    
                # Save by manually
                # Call save of parent class (models.Model) creating the custom class
                super(Item, self).save(*args, **kwargs)
    
                # Now you have the PK
                t1 = Task( name='T1', item=self )
                t1.save()
                #...
    
    class Task(models.Model):
        name = models.CharField(max_length=128)
        done_by = models.CharField(max_length=64, blank=True)
        done_date = models.DateField(null=True, blank=True)
    
        # Add Item FK
        item = models.ForeignKey(Item)
    

    代码更新注意事项:

    1)我改变了方向:任务链接到项目,而不是相反。见https://docs.djangoproject.com/en/1.11/topics/db/examples/many_to_one/

    2)我还是检查一下是不是新实例,然后调用super save,然后我为这个item创建任务。

    确保检查 self.pk 值,否则更新对象时代码也会被执行。

    还要注意,您必须每次都创建一个链接到 Item 对象的新 Task 对象。如果您将一个任务对象链接到两个项目,那么当 item_a 完成一项任务时,该任务似乎也为 item_b 完成。

    您需要做的是为 item_a 创建 task1,为 item_b 创建 task2。这样你就可以分离任务。

    继续阅读:

    https://docs.djangoproject.com/en/1.11/ref/models/instances/#saving-objects

    https://docs.djangoproject.com/en/1.11/topics/db/models/#relationships

    【讨论】:

    • 我已经稍微调整了我的问题以澄清我的问题:如果我创建两个具有相同任务的项目并将第一项的任务标记为已完成,它将在第二项中标记为已完成同样——这不是我想要的,我正在寻找解决方案。
    • Item(models.Models) 类是数据库对象的模板。您从中创建实例。如果您将一个任务实例链接到两个项目实例,并更新任务,那么链接到那里的两个项目将是相同的。您需要做的是为 item1 创建 task1,为 item2 创建 task2。这样你就可以分离任务。
    • 我开始明白了。我必须创建新任务并将其链接到每个新项目,并且不能重复使用它们。您是否碰巧有手动创建和添加任务的代码示例?
    猜你喜欢
    • 2016-04-10
    • 2013-03-25
    • 2016-11-11
    • 2011-12-27
    • 2018-09-29
    • 2016-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多