Отношения "многие ко многим" в Django
В настоящее время я занимаюсь личным проектом, чтобы лучше понять, как работает фреймворк Django REST. По сути, я пытаюсь создать веб-приложение, которое позволяет пользователям обмениваться файлами, своего рода упрощенная версия Google Drive/Dropbox.
Однако у меня возникли проблемы с отношениями "многие ко многим" в моих моделях. По сути, я хочу, чтобы у каждого пользователя были свои папки, в каждой папке было бы ноль или более файлов. Затем пользователь может поделиться (доступ только для чтения или разрешить запись/удаление) всей папкой или только отдельными файлами.
- У пользователя может быть одна (домашняя папка) или более папок
- Папка может иметь ноль (пустая папка) или более файлов
- Папку может читать один (владелец) или более пользователей, то же самое относится и к файлам
- Многие пользователи могут получить доступ (только чтение или запись) к папке/файлу в зависимости от их уровня прав
Я пытаюсь смоделировать эти отношения следующим образом:
from django.db import models
from django.contrib.auth.models import User
class Folder(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
users_can_edit = models.ManyToManyField(User)
users_can_see = models.ManyToManyField(User)
class File(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
folder = models.ForeignKey(Folder, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now=True, editable=False)
users_can_edit = models.ManyToManyField(User)
users_can_see = models.ManyToManyField(User)
Однако, я получаю эту ошибку, которую я не смог исправить, когда я пытаюсь запустить сервер:
ERRORS:
api.File.users_can_edit: (fields.E304) Reverse accessor for 'api.File.users_can_edit' clashes with reverse accessor for 'api.File.users_can_see'.
HINT: Add or change a related_name argument to the definition for 'api.File.users_can_edit' or 'api.File.users_can_see'.
api.File.users_can_see: (fields.E304) Reverse accessor for 'api.File.users_can_see' clashes with reverse accessor for 'api.File.users_can_edit'.
HINT: Add or change a related_name argument to the definition for 'api.File.users_can_see' or 'api.File.users_can_edit'.
api.Folder.user: (fields.E304) Reverse accessor for 'api.Folder.user' clashes with reverse accessor for 'api.Folder.users_can_edit'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.user' or 'api.Folder.users_can_edit'.
api.Folder.user: (fields.E304) Reverse accessor for 'api.Folder.user' clashes with reverse accessor for 'api.Folder.users_can_see'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.user' or 'api.Folder.users_can_see'.
api.Folder.users_can_edit: (fields.E304) Reverse accessor for 'api.Folder.users_can_edit' clashes with reverse accessor for 'api.Folder.user'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.users_can_edit' or 'api.Folder.user'.
api.Folder.users_can_edit: (fields.E304) Reverse accessor for 'api.Folder.users_can_edit' clashes with reverse accessor for 'api.Folder.users_can_see'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.users_can_edit' or 'api.Folder.users_can_see'.
api.Folder.users_can_see: (fields.E304) Reverse accessor for 'api.Folder.users_can_see' clashes with reverse accessor for 'api.Folder.user'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.users_can_see' or 'api.Folder.user'.
api.Folder.users_can_see: (fields.E304) Reverse accessor for 'api.Folder.users_can_see' clashes with reverse accessor for 'api.Folder.users_can_edit'.
HINT: Add or change a related_name argument to the definition for 'api.Folder.users_can_see' or 'api.Folder.users_can_edit'.
Я все еще новичок и знаю только основы SQL. Учитывая это, подходит ли такой подход или есть другой способ моделирования этих отношений?
У вас два ManyToManyField к одной модели, поэтому related_name=…s [Django-doc] одинаковы и будут конфликтовать. Вы должны указать related_name=…s, так:
from django.db import models
from django.conf import settings
class Folder(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
users_can_edit = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='folders_that_can_be_edited'
)
users_can_see = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='folders_that_can_be_seen'
)
class File(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
folder = models.ForeignKey(Folder, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now=True, editable=False)
users_can_edit = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='files_that_can_be_edited'
)
users_can_see = models.ManyToManyField(
settings.AUTH_USER_MODEL,
related_name='files_that_can_be_seen'
)
Но может быть лучше определить single ManyToManyField с through=… моделью [Django-doc], которая затем кодирует разрешения этой комбинации пользователь-файл, это потребует меньше таблиц, и сделает фильтрацию и т.д. более эффективной.
Note: It is normally better to make use of the
settings.AUTH_USER_MODEL[Django-doc] to refer to the user model, than to use theUsermodel [Django-doc] directly. For more information you can see the referencing theUsermodel section of the documentation.