I have this model:
class MyModel(User):
#others fields
and this serializer:
class MySerializer(serializers.ModelSerializer):
class Meta:
model = MyModel
fields = ('username', 'password', 'some_field')
I get data from ajax to make a login and I handle it like this:
serializer = MySerializer(data=request.DATA)
print(serializer.is_valid())
The problem: When I send any data my serializer works but when my username field, which must be unique as User model describe, matches with one at the database the serialize become invalid, so serializer.is_valid() return False
Why? can not I create a serialize object with data which must be unique and already exists in the database?
Because you are using ModelSerializer which automatically generates validators for your serializer. You should use normal Serializer class instead.
Validation in REST framework
Related
I have a Django admin class defined like this:
class MyModelAdmin(admin.ModelAdmin):
form = MyForm
class MyForm(forms.ModelForm):
class Meta:
model = Task
fields = ('project', 'title', 'description', 'internal_assignees', 'task_list',
'additional_description', 'labels', 'skill_level', 'estimated_hours',
'merge_request_url', 'branch_name',)
def clean(self):
super().clean()
print(self.errors)
Assume my model has a required field, which the user does not submit when performing POST request. The expected behavior in this case is that Django will not enter my overriden clean method. But it actually does. And self.errors contain error message.
The expected behavior was that Django will not enter the clean method if any of the required fields have not been submitted and will raise Bad request. Do I understand something incorrectly ? If so, does it mean that I have to check whether required fields are not or not in my clean method?
I have a serializer and I want it to get a field from another model for POST requests. Below is an example of what I'm trying to do (code taken from this tutorial: https://www.youtube.com/watch?v=h48Fxecu7EY)
class BlogPostSerializer(serializers.ModelSerializer):
username = serializers.SerializerMethodField('get_username_from_author_table')
class Meta:
model = BlogPost
fields = ['title', 'author_id', 'username']
def get_username_from_author_table(self, author_id):
return Author.objects.get(id=author_id).username
And my BlogPost model has the following fields: title, username.
Is it possible to create this serializer for a POST request? I haven't been able to get it to work, and I'm seeing that SerializerMethodField is only for GET requests in other posts.
I made a Updateview method in Django to update firstname, lastname, mobile etc..but how can I check the data received by the generic view through the form is previously exist in DB. For example, I want to avoid duplicating of mobile number with the model User in the database I tried by approaching def post() method, but I got a lot of errors can you teach me the exact way for avoiding duplicate data inserting
View code
class UpdateMprofile(mixin1, mixin2, UpdateView):
login_url = reverse_lazy('loginurlhere')
model = User
fields = ['first_name', 'last_name', 'mobile', 'avatar']
success_url = reverse_lazy('redirectedviewurlhere')
You should use unique=True in the model field definition, then Django will check this automatically when validating the form.
I am trying to make models and serializers that allow GET and POST
The GET will allow the client to see a list of all Users, and will show info like first name, last name, etc, but not access_token
However, the POST just needs the access_token and can pull all info like first name, last name, etc from Facebook.
How can I express and code this assymetric nature of get and post in the serializer
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
"""
User Serializer
"""
class Meta:
model = models.User
fields = ('id', 'username', 'first_name', 'last_name', 'image_url', 'activities', 'url', 'access_token')
views.py
class UserViewSet(viewsets.ModelViewSet):
"""
List all users - this should be taken out as it would never be used in app, and we wont want this as well, as app can only view friend details
Gives details of an user - this should stay
"""
queryset = models.User.objects.all()
serializer_class = UserSerializer
Any of these options:
Use read_only on fields that you don't want the user to be able to supply on creation.
Either override get_queryset and return a different serializer for GET vs POST.
Write the retrieve() and create() methods on the ViewSet explicitily.
However, the POST just needs the access_token and can pull all info like first name, last name, etc from Facebook.
You'll probably need a custom restore_object on the serializer to pull that info in.
This is related to the question : Assymetric nature of GET and POST in a Django REST framework Serializer . I've put it as a fresh question, instead of putting more questions in that thread, accordingly to SO guidelines
I am writing a Viewset and a ModelSerializer for the User model to provide a /user endpoint
GET - returns list and information about all users, in the standard DRF way
POST - all I want the client to post is the facebook access_token (hence have put all other fields as read_only in serializer. The pre_save() in ViewSet is wired to use this access token and it uses django-facebook to pull data from facebook api (using access token) and automatically create a new user with that information. Since this new user is created automatically, I want to suppress the normal DRF flow during POST and not create another user via DRF. How do i do this?
views.py
from open_facebook import OpenFacebook
from django_facebook.api import FacebookUserConverter
from django_facebook.connect import connect_user
class UserViewSet(viewsets.ModelViewSet):
queryset = models.User.objects.all()
serializer_class = UserSerializer
def pre_save(self, obj):
access_token = obj.access_token
facebook = OpenFacebook(access_token)
conv = FacebookUserConverter(facebook)
action, user = connect_user(self.request, access_token)
# this creates an entire new row, just as required, in the variable "user", so all I want to do is suppress any other row creation in the standard POST method. connect_user fills in data like first_name, last_name, etc from facebook already, and that is exactly what I need to do.
conv.get_and_store_friends(user)
obj = user
user.delete()
# I am trying to do that by copying user to obj and deleting user, but at the end of it i
print obj.username
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
"""
User Serializer
"""
class Meta:
model = models.User
fields = ('id', 'username', 'first_name', 'last_name', 'activities', 'image_url', 'url', 'access_token')
read_only_fields = ('username', 'first_name', 'last_name', 'image_url', 'activities') #todo: find out a shortcut to invert selection
# show activities with user details rather than separately to remove an extra server call
depth = 1
using the create() function of ModelViewSet worked, instead of pre_save - to suppress saving the object