简体   繁体   中英

How to design a many-to-many relation in Django?

I'm working on a webapp in Django 1.11 and it consists of:

  1. Users can add tasks and assign it to other users.
  2. Users should be able to see tasks assigned to him and created by him.

Here is my models.py :

from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(max_length=500)

How should I relate my task model to user model ? Should I put the many-to-many field in the user model or the task model ? How do I go about doing it ?

Edit: A user can be assigned one or more tasks. But the same task cannot be assigned to other users. I suppose that is a OneToMany relation. What are your thoughts on that ?

For your case you can use relationships like below

from django.db.models import Q
from django.db import models

class User(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def get_tasks(self):
        return Task.objects.filter(
            Q(created_by=self) | Q(assignee=self)

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(max_length=500)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    assignee = models.ManyToMany(User)

# how to use it

user = User.objects.get(pk=5)
tasks = user.get_tasks()

I would use a ManyToManyField with the through option. This way you are able to store more information in relation between Task and User.

class User(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

class Task(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField(max_length=500)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)
    assigned_users = models.ManyToManyField(
        User, 
        through='Assignment',
        related_name='tasks'
        )

class Assignment(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    task = models.ForeignKey(Task, on_delete=models.CASCADE)
    contribution_note = models.TextField()
    role = models.CharField(max_length=100)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

Role could be much more complex, if you like :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM