Django restframework: How serialize two models queryset? - python

I have the following situation: A user can have more than one profile. Here is my models class. Something like this example:
models.py:
class Profile:
name=models.Charfield()
class UserProfile:
user=models.ForeignKey(User)
profile = models.ForeignKey(Profile)
serializers.py:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = '__all__'
Here I'm returning all my users by JSON but I would like to add a new field called profiles that returns all ids profiles that the user have.
{ "id": 1,
"name" : "John"
....
profiles = [1, 2]
}
How can I get(query) all profiles that the user have and add them on my final JSON?

on the UserSerializer declare the field profile as PrimaryKeyRelatedField
profiles = serializers.PrimaryKeyRelatedField()
By default this field is read-write, although you can change this behavior using the read_only flag.
see docs

1) Simplify relations - only User and Profile models needed in this case, you don't have to store explicit relation in UserProfile table as the same could be done in Profile model, as long as you don't need Users to share profiles with other Users.
2) Create ProfileSerializer
3) Add profiles field to UserSerializer with many=True property & provide reference in 'source' property
Please reffer to these docs as they are really good
http://www.django-rest-framework.org/api-guide/serializers/
Another thing to mention, creating UserProfile is depricated and in new versions of Django you can extend basic User model using setting property AUTH_USER_MODEL

Related

How to add the current user to a many-to-many field when creating via a viewset?

I have a Django project which has "workspaces", and users can belong to multiple workspaces, so there's a many-to-many relationship between the users and the workspaces.
Now, everything else works fine so far, but I'm having trouble adding the current user to the workspace's list of users when the user creates that workspace.
The model looks like this:
class Workspace(models.Model):
name = models.CharField(max_length=100)
users = models.ManyToManyField(User, related_name='workspaces')
The serializer looks like this:
class WorkspaceSerializer(serializers.ModelSerializer):
class Meta:
model = Workspace
fields = ('name', 'users')
And finally, the view:
class WorkspaceViewSet(viewsets.ModelViewSet):
queryset = Workspace.objects.all().order_by('name')
serializer_class = WorkspaceSerializer
permission_classes = [permissions.IsAuthenticated,]
So, to elaborate, when a user creates a new workspace, I'd like the workspace's users field to refer to that user. Currently, that field remains empty. How would I populate the field so that the current user is added there right on creation?
You can override the create method of the serializer class:
class WorkspaceSerializer(serializers.ModelSerializer):
# ...
def create(self, validated_data):
instance = super(WorkspaceSerializer, self).create(validated_data)
instance.users.add(self.context['request'].user)
return instance
Note that you have access to the request in the serializer via the context attribute. This is passed in by the corresponding view (source).

Storing new field to Django Admin "user" section from registration form

I have managed to add an additional field to the Registration form, "where did you hear about us?".
But I am not sure which files to edit in order to store the data from this field along with the users info.
i.e. When logging into the Admin section and go to "users" and view a users info I would like to see this field there.
Simplest way would be to store additional data in a UserProfile model about the user, e.g.
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
where_heard_about_us = models.TextField()
You can then register the object as an inline object in your Django Admin

Issues with OneToOne Field in Serializer in django rest framework

I have model UserProfile related with User Model via one-to-one relationship.
UserProfileSerializer is defined correctly and it serializes userprofile object well.
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key=True)
country = models.CharField(max_length=255)
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('user','country')
But it gives error {'user':['This field is required']} on passing data.
>>> s = UserProfileSerializer(data = {'user':1,'country':'YY'} )
>>> s.is_valid()
False
>>> s.errrors
{'user':['This field is required']}
This might be too late to help, and I'm not sure exactly what you're trying to do, but try setting the user field in your serializer to use a PrimaryKeyRelatedField so that you can represent a User with an ID, or set the user field to be readonly if you only want to update UserProfile things. If you don't want to use a primary key, other relationship fields are here.
If you change the user field to be a PrimaryKeyRelatedField and you want the user data to return as it is now, you might want to make two UserProfile serializers - one for write operations, and one for reading. After a create or an update, you can switch to the read serializer to populate the response.

Django inlines for manyToMany field

I have a Profile model that has OneToOne relationship with User model.
I also have a Group model that has users field as ManyToMany to User.
I am trying to achieve a simple thing in Django Admin: being able to create a group with some new users and allowing to fill out some of the profile fields for those new users.
I tried a couple of things
class ProfileInline(admin.StackedInline):
model = Profile
class UserInline(admin.StackedInline):
model = Group.users.through
inlines = [ ProfileInline ]
class GroupAdmin(admin.ModelAdmin):
inlines = [
UserInline,
]
exclude = ('users',)
This is not working for me. I only see dropdown fields for user in my group admin and if I try to add a user the form does not have any profile fields.
You can't do that. Django admin inlines are only available if model has foreign key to other model. For you setup you have to find other solution related to your models relation.

Django: given a user object, how do I get a corresponding UserProfile object?

Have a UserProfile object that successfully extends the django default user class:
class UserProfile(models.Model):
user = models.OneToOneField(User)
and have updated the settings.py file accordingly:
AUTH_PROFILE_MODULE = 'authorization.UserProfile'
Everything works fine, just wondering: how do I get to objects associated with UserProfile for a given context within a view?
Assume that I can just get context.user if the user is logged in, but then how do I grab the corresponding UserProfile object?
In view:
request.user.get_profile().field_name
In template:
{{user.userprofile.field_name}}
You can get it like -
context.user.userprofile
Detail here.

Categories