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
6 hours ago
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
6 hours ago
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
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago
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 6 hours ago
Rohit Verma
1,4372623
1,4372623
asked 6 hours ago
Blejwi
358417
358417
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
6 hours ago
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
6 hours ago
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
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago
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
6 hours ago
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
6 hours ago
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
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago
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
6 hours ago
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
6 hours ago
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
6 hours ago
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
6 hours ago
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
6 hours ago
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
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago
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
6 hours ago
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
5 hours ago
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
6 hours ago
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
5 hours ago
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
6 hours ago
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
5 hours ago
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 5 hours ago
answered 6 hours ago
robotHamster
698
698
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
6 hours ago
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
5 hours ago
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
6 hours ago
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
5 hours ago
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
6 hours ago
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
6 hours ago
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
5 hours ago
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
5 hours ago
add a comment |
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
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
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
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
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
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
6 hours ago
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
6 hours ago
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
6 hours ago
working on an answer... it's pretty simple to the point where I still feel like I don't understand the whole picture...
– robotHamster
6 hours ago
Updated my answer, hopefully this helps you out :)
– robotHamster
5 hours ago