Django Rest Framework: SerializerMethodField and get_queryset
In my database I have two tables - users
and user_properties
I need to filter output using GET parameter phone
. But both this tables has column phone
and has different values.
When I doing GET request (ex. "?phone=123456789") I need to search User by phone number using not only user_properties.phone, but user.phone too!
I googled and found a way partially to do this using get_queryset(filtering) and SerializerMethodField(to modify output):
models.py
class User(models.Model):
balance = models.DecimalField(decimal_places=35, max_digits=40)
fio = models.CharField(max_length=64)
phone = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
db_table = 'user'
class UserProperties(models.Model):
user_id = models.IntegerField(primary_key=True)
phone = models.CharField(max_length=11)
class Meta:
managed = False
db_table = 'user_properties'
views.py
class UserPropertiesViewSet(viewsets.ModelViewSet):
queryset = UserProperties.objects.all()
serializer_class = serializers.UserPropertiesSerializer
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
# Search users matches in user_properties using by phone number
if phone:
queryset = UserProperties.objects.all()
users = queryset.filter(phone__contains=phone)
return users
else:
return queryset
serializers.py
class UserPropertiesSerializer(serializers.ModelSerializer):
all_phones = serializers.SerializerMethodField()
class Meta:
model = models.UserProperties
fields = ['user_id', 'phone', 'fio', 'url', 'all_phones',]
# phone numbers from user and user_properties tables
def get_all_phones(self, obj):
# search phones in <user> table by user_id
user_phones = models.User.objects.filter(id__exact=obj.user_id).values_list('phone', flat=True)
# add phones from user_properties table
result = [obj.phone,]
# add phones from user table
for phone in user_phones[0].split(','):
result.append(''.join(filter(lambda x: x.isdigit(), phone)))
# return list with all phones
return set(result)
And I get all_phones
column in my filtered results:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"user_id": 17897,
"phone": "123456789", <--- user_properties table
"fio": "....",
"url": "....",
"all_phones": [
"123456789",
"5512222",
"49543"
] <--- user_properties.phone + user.phone
}
]
}
But in the get_queryset
I filtering only using "real" phone
column in user_properties table. How to filter results using "virtual" all_phones
column? Or search in two tables and get User who has one of this phone numbers? Is it's possible? Or my way is not correct?
Thanks!
django rest api django-rest-framework
add a comment |
In my database I have two tables - users
and user_properties
I need to filter output using GET parameter phone
. But both this tables has column phone
and has different values.
When I doing GET request (ex. "?phone=123456789") I need to search User by phone number using not only user_properties.phone, but user.phone too!
I googled and found a way partially to do this using get_queryset(filtering) and SerializerMethodField(to modify output):
models.py
class User(models.Model):
balance = models.DecimalField(decimal_places=35, max_digits=40)
fio = models.CharField(max_length=64)
phone = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
db_table = 'user'
class UserProperties(models.Model):
user_id = models.IntegerField(primary_key=True)
phone = models.CharField(max_length=11)
class Meta:
managed = False
db_table = 'user_properties'
views.py
class UserPropertiesViewSet(viewsets.ModelViewSet):
queryset = UserProperties.objects.all()
serializer_class = serializers.UserPropertiesSerializer
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
# Search users matches in user_properties using by phone number
if phone:
queryset = UserProperties.objects.all()
users = queryset.filter(phone__contains=phone)
return users
else:
return queryset
serializers.py
class UserPropertiesSerializer(serializers.ModelSerializer):
all_phones = serializers.SerializerMethodField()
class Meta:
model = models.UserProperties
fields = ['user_id', 'phone', 'fio', 'url', 'all_phones',]
# phone numbers from user and user_properties tables
def get_all_phones(self, obj):
# search phones in <user> table by user_id
user_phones = models.User.objects.filter(id__exact=obj.user_id).values_list('phone', flat=True)
# add phones from user_properties table
result = [obj.phone,]
# add phones from user table
for phone in user_phones[0].split(','):
result.append(''.join(filter(lambda x: x.isdigit(), phone)))
# return list with all phones
return set(result)
And I get all_phones
column in my filtered results:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"user_id": 17897,
"phone": "123456789", <--- user_properties table
"fio": "....",
"url": "....",
"all_phones": [
"123456789",
"5512222",
"49543"
] <--- user_properties.phone + user.phone
}
]
}
But in the get_queryset
I filtering only using "real" phone
column in user_properties table. How to filter results using "virtual" all_phones
column? Or search in two tables and get User who has one of this phone numbers? Is it's possible? Or my way is not correct?
Thanks!
django rest api django-rest-framework
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05
add a comment |
In my database I have two tables - users
and user_properties
I need to filter output using GET parameter phone
. But both this tables has column phone
and has different values.
When I doing GET request (ex. "?phone=123456789") I need to search User by phone number using not only user_properties.phone, but user.phone too!
I googled and found a way partially to do this using get_queryset(filtering) and SerializerMethodField(to modify output):
models.py
class User(models.Model):
balance = models.DecimalField(decimal_places=35, max_digits=40)
fio = models.CharField(max_length=64)
phone = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
db_table = 'user'
class UserProperties(models.Model):
user_id = models.IntegerField(primary_key=True)
phone = models.CharField(max_length=11)
class Meta:
managed = False
db_table = 'user_properties'
views.py
class UserPropertiesViewSet(viewsets.ModelViewSet):
queryset = UserProperties.objects.all()
serializer_class = serializers.UserPropertiesSerializer
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
# Search users matches in user_properties using by phone number
if phone:
queryset = UserProperties.objects.all()
users = queryset.filter(phone__contains=phone)
return users
else:
return queryset
serializers.py
class UserPropertiesSerializer(serializers.ModelSerializer):
all_phones = serializers.SerializerMethodField()
class Meta:
model = models.UserProperties
fields = ['user_id', 'phone', 'fio', 'url', 'all_phones',]
# phone numbers from user and user_properties tables
def get_all_phones(self, obj):
# search phones in <user> table by user_id
user_phones = models.User.objects.filter(id__exact=obj.user_id).values_list('phone', flat=True)
# add phones from user_properties table
result = [obj.phone,]
# add phones from user table
for phone in user_phones[0].split(','):
result.append(''.join(filter(lambda x: x.isdigit(), phone)))
# return list with all phones
return set(result)
And I get all_phones
column in my filtered results:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"user_id": 17897,
"phone": "123456789", <--- user_properties table
"fio": "....",
"url": "....",
"all_phones": [
"123456789",
"5512222",
"49543"
] <--- user_properties.phone + user.phone
}
]
}
But in the get_queryset
I filtering only using "real" phone
column in user_properties table. How to filter results using "virtual" all_phones
column? Or search in two tables and get User who has one of this phone numbers? Is it's possible? Or my way is not correct?
Thanks!
django rest api django-rest-framework
In my database I have two tables - users
and user_properties
I need to filter output using GET parameter phone
. But both this tables has column phone
and has different values.
When I doing GET request (ex. "?phone=123456789") I need to search User by phone number using not only user_properties.phone, but user.phone too!
I googled and found a way partially to do this using get_queryset(filtering) and SerializerMethodField(to modify output):
models.py
class User(models.Model):
balance = models.DecimalField(decimal_places=35, max_digits=40)
fio = models.CharField(max_length=64)
phone = models.CharField(max_length=64, blank=True, null=True)
class Meta:
managed = False
db_table = 'user'
class UserProperties(models.Model):
user_id = models.IntegerField(primary_key=True)
phone = models.CharField(max_length=11)
class Meta:
managed = False
db_table = 'user_properties'
views.py
class UserPropertiesViewSet(viewsets.ModelViewSet):
queryset = UserProperties.objects.all()
serializer_class = serializers.UserPropertiesSerializer
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
# Search users matches in user_properties using by phone number
if phone:
queryset = UserProperties.objects.all()
users = queryset.filter(phone__contains=phone)
return users
else:
return queryset
serializers.py
class UserPropertiesSerializer(serializers.ModelSerializer):
all_phones = serializers.SerializerMethodField()
class Meta:
model = models.UserProperties
fields = ['user_id', 'phone', 'fio', 'url', 'all_phones',]
# phone numbers from user and user_properties tables
def get_all_phones(self, obj):
# search phones in <user> table by user_id
user_phones = models.User.objects.filter(id__exact=obj.user_id).values_list('phone', flat=True)
# add phones from user_properties table
result = [obj.phone,]
# add phones from user table
for phone in user_phones[0].split(','):
result.append(''.join(filter(lambda x: x.isdigit(), phone)))
# return list with all phones
return set(result)
And I get all_phones
column in my filtered results:
{
"count": 1,
"next": null,
"previous": null,
"results": [
{
"user_id": 17897,
"phone": "123456789", <--- user_properties table
"fio": "....",
"url": "....",
"all_phones": [
"123456789",
"5512222",
"49543"
] <--- user_properties.phone + user.phone
}
]
}
But in the get_queryset
I filtering only using "real" phone
column in user_properties table. How to filter results using "virtual" all_phones
column? Or search in two tables and get User who has one of this phone numbers? Is it's possible? Or my way is not correct?
Thanks!
django rest api django-rest-framework
django rest api django-rest-framework
edited Nov 22 '18 at 8:16
asked Nov 21 '18 at 13:49
Serg
286
286
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05
add a comment |
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05
add a comment |
1 Answer
1
active
oldest
votes
This question is more about the Django ORM than Django REST framework, but rewriting the get_queryset
method like this will search on the phone
fields of both models:
from django.db.models import Q
...
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
if phone:
queryset = queryset.filter(
Q(phone__contains=phone)
| Q(user__phone__contains=phone)
)
return queryset
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -ForeignKey
orOneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?
– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change theuser_id
field definition and try again:user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed fromuser_id
touser
)
– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
|
show 2 more comments
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
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%2f53413542%2fdjango-rest-framework-serializermethodfield-and-get-queryset%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
This question is more about the Django ORM than Django REST framework, but rewriting the get_queryset
method like this will search on the phone
fields of both models:
from django.db.models import Q
...
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
if phone:
queryset = queryset.filter(
Q(phone__contains=phone)
| Q(user__phone__contains=phone)
)
return queryset
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -ForeignKey
orOneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?
– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change theuser_id
field definition and try again:user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed fromuser_id
touser
)
– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
|
show 2 more comments
This question is more about the Django ORM than Django REST framework, but rewriting the get_queryset
method like this will search on the phone
fields of both models:
from django.db.models import Q
...
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
if phone:
queryset = queryset.filter(
Q(phone__contains=phone)
| Q(user__phone__contains=phone)
)
return queryset
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -ForeignKey
orOneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?
– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change theuser_id
field definition and try again:user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed fromuser_id
touser
)
– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
|
show 2 more comments
This question is more about the Django ORM than Django REST framework, but rewriting the get_queryset
method like this will search on the phone
fields of both models:
from django.db.models import Q
...
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
if phone:
queryset = queryset.filter(
Q(phone__contains=phone)
| Q(user__phone__contains=phone)
)
return queryset
This question is more about the Django ORM than Django REST framework, but rewriting the get_queryset
method like this will search on the phone
fields of both models:
from django.db.models import Q
...
def get_queryset(self):
queryset = self.queryset
# phone number from GET
phone = self.request.query_params.get('phone')
if phone:
queryset = queryset.filter(
Q(phone__contains=phone)
| Q(user__phone__contains=phone)
)
return queryset
edited Nov 21 '18 at 14:24
answered Nov 21 '18 at 14:19
kristaps
1,360712
1,360712
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -ForeignKey
orOneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?
– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change theuser_id
field definition and try again:user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed fromuser_id
touser
)
– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
|
show 2 more comments
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -ForeignKey
orOneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?
– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change theuser_id
field definition and try again:user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed fromuser_id
touser
)
– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
Hi. Thank You for your answer. I gets an error: ""Cannot resolve keyword 'user' into field. Choices are: email, phone, " ... etc (columns list from user_properties table). Will Q work with two tables without relationships? Seems like no
– Serg
Nov 21 '18 at 17:40
For the example to work, the tables will need to have a relation defined -
ForeignKey
or OneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?– kristaps
Nov 22 '18 at 1:37
For the example to work, the tables will need to have a relation defined -
ForeignKey
or OneToOneField
. Can you update your post include the relevant parts of your User and UserProperties models?– kristaps
Nov 22 '18 at 1:37
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
Updated my post. I couldn't change my database tables - read only.
– Serg
Nov 22 '18 at 8:26
That's ok, changing the model definition should be enough. Change the
user_id
field definition and try again: user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed from user_id
to user
)– kristaps
Nov 22 '18 at 13:24
That's ok, changing the model definition should be enough. Change the
user_id
field definition and try again: user = models.OneToOneField(User, primary_key=True)
(Note that the field has been renamed from user_id
to user
)– kristaps
Nov 22 '18 at 13:24
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
THANK YOU!!! This is what I need. But could You explain me: table user_properties will not be changed by Django after I run "migrate" command in future? I have managed=False and when i running migrate command I add --fake keyword.
– Serg
Nov 22 '18 at 13:53
|
show 2 more comments
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%2f53413542%2fdjango-rest-framework-serializermethodfield-and-get-queryset%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
You cannot depend on the Django ORM to search through 2 different tables. You will either have to query twice and join the results, or normalize your data and move all phone numbers to one table.
– LaundroMat
Nov 21 '18 at 14:05