Django - ManyToMany through synthetic relation fields
up vote
0
down vote
favorite
I have such models in my application:
class User(AbstractUser):
pass
class MyObject(models.Model):
name = models.CharField(max_length=200, unique=False, db_index=True)
related_users = models.ManyToManyField(
User, through='RelatedUsers', related_name='related_users'
)
class RelatedUsers(models.Model):
my_object = models.ForeignKey(
MyObject, related_name='my_object_related_users'
)
user = models.ForeignKey(User)
type = models.CharField(
max_length=100,
choices=RelatedUsersTypes.choices()
)
class Meta:
unique_together = ('user', 'my_object', 'type')
class FunctionalityRelatedUsersTypes(BaseChoiceEnum):
TYPE_1 = 'TYPE 1'
TYPE_2 = 'TYPE 2'
TYPE_3 = 'TYPE 3'
TYPE_4 = 'TYPE 4'
TYPE_5 = 'TYPE 5'
I'm wondering if there is an option to create some kind of synthetic relations on MyObject
.
I would like to be able to get users by type using one field, example: related_users_type_1
. I'd like to use it in DRF serializer as well (so I can pass just List of ids, and relation will create a Proxy object with the corresponding type).
Pseudocode:
related_users_type_1 = models.RelationField(RelatedUsers, filter={'type': 'TYPE_1'})
Sample payload I want to send:
{
"related_users_type_1": [1, 2, 3],
"related_users_type_2": [3]
}
Expected result:
- 3
RelatedUsers
withTYPE_1
- 1
RelatedUser
withTYPE_2
python django django-rest-framework
add a comment |
up vote
0
down vote
favorite
I have such models in my application:
class User(AbstractUser):
pass
class MyObject(models.Model):
name = models.CharField(max_length=200, unique=False, db_index=True)
related_users = models.ManyToManyField(
User, through='RelatedUsers', related_name='related_users'
)
class RelatedUsers(models.Model):
my_object = models.ForeignKey(
MyObject, related_name='my_object_related_users'
)
user = models.ForeignKey(User)
type = models.CharField(
max_length=100,
choices=RelatedUsersTypes.choices()
)
class Meta:
unique_together = ('user', 'my_object', 'type')
class FunctionalityRelatedUsersTypes(BaseChoiceEnum):
TYPE_1 = 'TYPE 1'
TYPE_2 = 'TYPE 2'
TYPE_3 = 'TYPE 3'
TYPE_4 = 'TYPE 4'
TYPE_5 = 'TYPE 5'
I'm wondering if there is an option to create some kind of synthetic relations on MyObject
.
I would like to be able to get users by type using one field, example: related_users_type_1
. I'd like to use it in DRF serializer as well (so I can pass just List of ids, and relation will create a Proxy object with the corresponding type).
Pseudocode:
related_users_type_1 = models.RelationField(RelatedUsers, filter={'type': 'TYPE_1'})
Sample payload I want to send:
{
"related_users_type_1": [1, 2, 3],
"related_users_type_2": [3]
}
Expected result:
- 3
RelatedUsers
withTYPE_1
- 1
RelatedUser
withTYPE_2
python django django-rest-framework
1
Name your classes with singular nouns!RelatedUser
instead ofRelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a newRelatedUser
, just a single one, not many of them.
– cezar
Nov 8 at 7:49
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Main purpose is simplifying API request/responses, so user does not have to pass list of structures withuser_id
andtype
torelated_users
field in payload. He passes just list of ids torelated_users_type_1
, and he can update only users withTYPE_1
via patch (doesn't have to send whole list of already existing users of other types)
– Blejwi
Nov 8 at 7:54
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have such models in my application:
class User(AbstractUser):
pass
class MyObject(models.Model):
name = models.CharField(max_length=200, unique=False, db_index=True)
related_users = models.ManyToManyField(
User, through='RelatedUsers', related_name='related_users'
)
class RelatedUsers(models.Model):
my_object = models.ForeignKey(
MyObject, related_name='my_object_related_users'
)
user = models.ForeignKey(User)
type = models.CharField(
max_length=100,
choices=RelatedUsersTypes.choices()
)
class Meta:
unique_together = ('user', 'my_object', 'type')
class FunctionalityRelatedUsersTypes(BaseChoiceEnum):
TYPE_1 = 'TYPE 1'
TYPE_2 = 'TYPE 2'
TYPE_3 = 'TYPE 3'
TYPE_4 = 'TYPE 4'
TYPE_5 = 'TYPE 5'
I'm wondering if there is an option to create some kind of synthetic relations on MyObject
.
I would like to be able to get users by type using one field, example: related_users_type_1
. I'd like to use it in DRF serializer as well (so I can pass just List of ids, and relation will create a Proxy object with the corresponding type).
Pseudocode:
related_users_type_1 = models.RelationField(RelatedUsers, filter={'type': 'TYPE_1'})
Sample payload I want to send:
{
"related_users_type_1": [1, 2, 3],
"related_users_type_2": [3]
}
Expected result:
- 3
RelatedUsers
withTYPE_1
- 1
RelatedUser
withTYPE_2
python django django-rest-framework
I have such models in my application:
class User(AbstractUser):
pass
class MyObject(models.Model):
name = models.CharField(max_length=200, unique=False, db_index=True)
related_users = models.ManyToManyField(
User, through='RelatedUsers', related_name='related_users'
)
class RelatedUsers(models.Model):
my_object = models.ForeignKey(
MyObject, related_name='my_object_related_users'
)
user = models.ForeignKey(User)
type = models.CharField(
max_length=100,
choices=RelatedUsersTypes.choices()
)
class Meta:
unique_together = ('user', 'my_object', 'type')
class FunctionalityRelatedUsersTypes(BaseChoiceEnum):
TYPE_1 = 'TYPE 1'
TYPE_2 = 'TYPE 2'
TYPE_3 = 'TYPE 3'
TYPE_4 = 'TYPE 4'
TYPE_5 = 'TYPE 5'
I'm wondering if there is an option to create some kind of synthetic relations on MyObject
.
I would like to be able to get users by type using one field, example: related_users_type_1
. I'd like to use it in DRF serializer as well (so I can pass just List of ids, and relation will create a Proxy object with the corresponding type).
Pseudocode:
related_users_type_1 = models.RelationField(RelatedUsers, filter={'type': 'TYPE_1'})
Sample payload I want to send:
{
"related_users_type_1": [1, 2, 3],
"related_users_type_2": [3]
}
Expected result:
- 3
RelatedUsers
withTYPE_1
- 1
RelatedUser
withTYPE_2
python django django-rest-framework
python django django-rest-framework
edited Nov 8 at 7:47
Rohit Verma
1,4562724
1,4562724
asked Nov 8 at 7:45
Blejwi
360417
360417
1
Name your classes with singular nouns!RelatedUser
instead ofRelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a newRelatedUser
, just a single one, not many of them.
– cezar
Nov 8 at 7:49
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Main purpose is simplifying API request/responses, so user does not have to pass list of structures withuser_id
andtype
torelated_users
field in payload. He passes just list of ids torelated_users_type_1
, and he can update only users withTYPE_1
via patch (doesn't have to send whole list of already existing users of other types)
– Blejwi
Nov 8 at 7:54
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32
add a comment |
1
Name your classes with singular nouns!RelatedUser
instead ofRelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a newRelatedUser
, just a single one, not many of them.
– cezar
Nov 8 at 7:49
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Main purpose is simplifying API request/responses, so user does not have to pass list of structures withuser_id
andtype
torelated_users
field in payload. He passes just list of ids torelated_users_type_1
, and he can update only users withTYPE_1
via patch (doesn't have to send whole list of already existing users of other types)
– Blejwi
Nov 8 at 7:54
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32
1
1
Name your classes with singular nouns!
RelatedUser
instead of RelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a new RelatedUser
, just a single one, not many of them.– cezar
Nov 8 at 7:49
Name your classes with singular nouns!
RelatedUser
instead of RelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a new RelatedUser
, just a single one, not many of them.– cezar
Nov 8 at 7:49
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Main purpose is simplifying API request/responses, so user does not have to pass list of structures with
user_id
and type
to related_users
field in payload. He passes just list of ids to related_users_type_1
, and he can update only users with TYPE_1
via patch (doesn't have to send whole list of already existing users of other types)– Blejwi
Nov 8 at 7:54
Main purpose is simplifying API request/responses, so user does not have to pass list of structures with
user_id
and type
to related_users
field in payload. He passes just list of ids to related_users_type_1
, and he can update only users with TYPE_1
via patch (doesn't have to send whole list of already existing users of other types)– Blejwi
Nov 8 at 7:54
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
From the comments we've had, I think your problem can be solved with models as such:
# just for completeness. should probably use an actual user model
class User (models.Model):
name = models.CharField(max_length=64)
class MyObject(models.Model):
name = models.CharField(max_length=64)
users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)
def add_relations(self, relations):
for key, list in relations.items():
for id in list:
users.add(user=User.objects.get(pk=id), rel_type=key)
class MyObjectUsers(models.Model):
REL_TYPE_CHOICES=(
('TYPE1','TYPE1'),
('TYPE2','TYPE2')
)
myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)
The django documentation shows you how to traverse the relationship.
With the above implementation of MyObject
, you should be able to to call .add_relations({'TYPE1':[1,2,3]})
on a MyObject
instance to create the relationships you need.
I wrote this on my phone so I don't really know if it runs (will test tomorrow)
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
From the comments we've had, I think your problem can be solved with models as such:
# just for completeness. should probably use an actual user model
class User (models.Model):
name = models.CharField(max_length=64)
class MyObject(models.Model):
name = models.CharField(max_length=64)
users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)
def add_relations(self, relations):
for key, list in relations.items():
for id in list:
users.add(user=User.objects.get(pk=id), rel_type=key)
class MyObjectUsers(models.Model):
REL_TYPE_CHOICES=(
('TYPE1','TYPE1'),
('TYPE2','TYPE2')
)
myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)
The django documentation shows you how to traverse the relationship.
With the above implementation of MyObject
, you should be able to to call .add_relations({'TYPE1':[1,2,3]})
on a MyObject
instance to create the relationships you need.
I wrote this on my phone so I don't really know if it runs (will test tomorrow)
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
add a comment |
up vote
0
down vote
From the comments we've had, I think your problem can be solved with models as such:
# just for completeness. should probably use an actual user model
class User (models.Model):
name = models.CharField(max_length=64)
class MyObject(models.Model):
name = models.CharField(max_length=64)
users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)
def add_relations(self, relations):
for key, list in relations.items():
for id in list:
users.add(user=User.objects.get(pk=id), rel_type=key)
class MyObjectUsers(models.Model):
REL_TYPE_CHOICES=(
('TYPE1','TYPE1'),
('TYPE2','TYPE2')
)
myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)
The django documentation shows you how to traverse the relationship.
With the above implementation of MyObject
, you should be able to to call .add_relations({'TYPE1':[1,2,3]})
on a MyObject
instance to create the relationships you need.
I wrote this on my phone so I don't really know if it runs (will test tomorrow)
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
add a comment |
up vote
0
down vote
up vote
0
down vote
From the comments we've had, I think your problem can be solved with models as such:
# just for completeness. should probably use an actual user model
class User (models.Model):
name = models.CharField(max_length=64)
class MyObject(models.Model):
name = models.CharField(max_length=64)
users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)
def add_relations(self, relations):
for key, list in relations.items():
for id in list:
users.add(user=User.objects.get(pk=id), rel_type=key)
class MyObjectUsers(models.Model):
REL_TYPE_CHOICES=(
('TYPE1','TYPE1'),
('TYPE2','TYPE2')
)
myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)
The django documentation shows you how to traverse the relationship.
With the above implementation of MyObject
, you should be able to to call .add_relations({'TYPE1':[1,2,3]})
on a MyObject
instance to create the relationships you need.
I wrote this on my phone so I don't really know if it runs (will test tomorrow)
From the comments we've had, I think your problem can be solved with models as such:
# just for completeness. should probably use an actual user model
class User (models.Model):
name = models.CharField(max_length=64)
class MyObject(models.Model):
name = models.CharField(max_length=64)
users = models.ManyToMany(User, through='MyObjectUsers', symmetrical=False)
def add_relations(self, relations):
for key, list in relations.items():
for id in list:
users.add(user=User.objects.get(pk=id), rel_type=key)
class MyObjectUsers(models.Model):
REL_TYPE_CHOICES=(
('TYPE1','TYPE1'),
('TYPE2','TYPE2')
)
myobject = models.ForeignKey('MyObject', null=True, on_delete=models.SET_NULL)
user = models.ForeignKey('User', null=True, on_delete=models.SET_NULL)
rel_type = models.CharField(max_length=32, choices = REL_TYPE_CHOICES)
The django documentation shows you how to traverse the relationship.
With the above implementation of MyObject
, you should be able to to call .add_relations({'TYPE1':[1,2,3]})
on a MyObject
instance to create the relationships you need.
I wrote this on my phone so I don't really know if it runs (will test tomorrow)
edited Nov 8 at 9:30
answered Nov 8 at 8:05
robotHamster
343115
343115
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
add a comment |
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:
related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
Thanks for an answer, but I know how to create such through relationship. For example in SQLAlchemy I can create multiple relationship through same table using primaryjoin. So it would look like:
related_users_type_1 = db.relationship('RelatedUsers', primaryjoin='RelatedUsers.type==TYPE_1')
– Blejwi
Nov 8 at 8:28
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
I see what you mean. I think what you are looking for is doable with model managers and/or model methods or some involved logic in the view to implement custom methods such as the ones you are looking for. Will edit the answer to reflect that tomorrow. For now, I need sleep! :P @Blewji
– robotHamster
Nov 8 at 9:06
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53203298%2fdjango-manytomany-through-synthetic-relation-fields%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Name your classes with singular nouns!
RelatedUser
instead ofRelatedUsers
, and so on. This is a best-practice naming convention. When you instantiate an object of the class you're creating a newRelatedUser
, just a single one, not many of them.– cezar
Nov 8 at 7:49
Are you just looking to create a structure to label relationships between users and be able to use that relationship as a filter? I;m having a little bit of trouble understanding...
– robotHamster
Nov 8 at 7:50
Main purpose is simplifying API request/responses, so user does not have to pass list of structures with
user_id
andtype
torelated_users
field in payload. He passes just list of ids torelated_users_type_1
, and he can update only users withTYPE_1
via patch (doesn't have to send whole list of already existing users of other types)– Blejwi
Nov 8 at 7:54
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
Nov 8 at 8:02
Updated my answer, hopefully this helps you out :)
– robotHamster
Nov 8 at 9:32