Reputation: 41
I'm currently doing a personal project to have a better understanding of how the Django REST framework works. Essentially, I'm trying to build a web application that allows users to share files, kind of a simplified version of Google Drive/Dropbox.
However, I'm having some trouble with many to many relationships in my models. Essentially, I want each user to have its own folders, in each folder they would have zero or more files. A user could then share (read only access or allow write/delete) an entire folder or only individual files.
I'm trying to model this relationships as follows:
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)
However, I get this error that I wasn't able to fix when I try to run the server:
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'.
I'm still a beginner and only know the basic of SQL. This being said, is this an approach appropriate or is there any other way you would model these relationships?
Upvotes: 2
Views: 210
Reputation: 476659
You have two ManyToManyField
s to the same model, so the related_name=…
s [Django-doc] are the same, and will clash. You should specify the related_name=…
s, so:
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'
)
But it might be better to define a single ManyToManyField
with a through=…
model [Django-doc] that then encodes the permissions of that user-file combination, this will require less tables, and makes filtering, etc. more effective.
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 theUser
model [Django-doc] directly. For more information you can see the referencing theUser
model section of the documentation.
Upvotes: 2