1

I'm making a task tracker webapp (the full source code is also available) and I have a database structure where each task has a title, a description, and some number of instances, that can each be marked incomplete/incomplete:

class Task(models.Model):
    title = OneLineTextField()
    description = models.TextField(blank=True)


class TaskInstance(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    is_complete = models.BooleanField()

The task and the instances can be shared separately, although access to the instance should imply read access to the task. This is intended for classroom situations, where the teacher creates a task and assigns it to their students.

class TaskPermission(models.Model):
    task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='permissions')
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='task_permissions_granted')
    shared_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, related_name='task_permissions_granting')
    can_edit = models.BooleanField(default=False)

    class Meta:
        unique_together = 'task', 'user', 'shared_by',


class TaskInstancePermission(models.Model):
    task_instance = models.ForeignKey(TaskInstance, on_delete=models.CASCADE, related_name='permissions')
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='task_instance_permissions_granted')
    shared_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, related_name='task_instance_permissions_granting')
    can_edit = models.BooleanField(default=False)

    class Meta:
        unique_together = 'task_instance', 'user', 'shared_by',

My question is how to create a form for TaskInstances with fields for its is_complete, as well as its Task's title and description. Would something like this work? Or would I need to implement my own save and clean methods?

class TaskForm(ModelForm):
    class Meta:
        model = TaskInstance
        fields = ('is_complete', 'task__title', 'task__description')
Solomon Ucko
  • 5,724
  • 3
  • 24
  • 45
  • You don't need to implement them unless you want to override them – ruddra Mar 24 '19 at 17:16
  • I don't really understand your requirements. An arbitrary title and description need not correspond to any `Task` instance. It would be more normal to simply select the task from a list of existing ones - which you can easily get to display them using title and/or description. This all comes down to how you want the user interface to work. – Robin Zigmond Mar 24 '19 at 17:18
  • @RobinZigmond I see what you're saying. However, I was thinking of having each task have a list of instances, so it goes in the other direction. It would then be possible to modify the task's title & description from the task instance. I might reconsider that, but I want to simplify things for the case of one instance per task, though... – Solomon Ucko Mar 24 '19 at 17:32
  • 1
    Oh, so you want a page for editing a particular `TaskInstance` instance, in which you can change the title and description of the underlying task? That's perfectly possible (if you don't mind the "action at a distance" of one instance affecting every other based on the same `Task`) - in that case use a regular `Form` rather than a `ModelForm` and do all the necessary database inserts/updates in your view. – Robin Zigmond Mar 24 '19 at 17:36
  • @RobinZigmond Exactly. I wanted to know if there was an easier / better / less repetitive way, but I might just do it semi-manually. – Solomon Ucko Mar 24 '19 at 17:38
  • 1
    Possible duplicate of [form for simultaneously editing two django models with foreign key relationship](https://stackoverflow.com/questions/48453061/form-for-simultaneously-editing-two-django-models-with-foreign-key-relationship) – Paandittya Mar 24 '19 at 21:54

1 Answers1

0

I think inlineformset_factory is what I'm looking for!

Actually, it does not seem to be useful: it is for multiple forms of the same type, not different types...

Solomon Ucko
  • 5,724
  • 3
  • 24
  • 45
  • @BogdanPrădatu I don't remember. You can check [the source code](https://repl.it/@solly_ucko/Task-Tracker). I'm on my phone right now. – Solomon Ucko Oct 18 '19 at 10:33
  • @BogdanPrădatu It looks like I just implemented it manually. See `main/templates/main/task-instance.html` and `main/views.py`'s `view_task_instance`. – Solomon Ucko Oct 18 '19 at 14:04