How to handle PUT request in Django RestFramework - python

I am trying to update my data in 'VoterList' model by using PUT api, but i don't know which function should i use in my 'views.py' file to handle the coming PUT request because in PUT api, we use parameters from URL to pick the relevent entry from model for updation and then update it by using data received from PUT api.
model.py
class VoterList(models.Model):
# id = models.IntegerField(auto_created= True, primary_key=True)
name = models.CharField( max_length=20)
email = models.EmailField()
mobile = models.IntegerField()
city = models.CharField( max_length=20)
type = models.CharField(max_length=20)
def __str__(self):
return self.name
serializers.py
class FillVoterListSerializers(serializers.HyperlinkedModelSerializer):
class Meta:
model = VoterList
fields = ('id','name', 'email', 'mobile', 'city', 'type')
def update(self, instance, validated_data):
instance.name = validated_data.pop("name", instance.name)
instance.email = validated_data.pop("email", instance.email)
instance.save()
return instance
I will manage the code for PUT in serializers by myself.
views.py
class UpdateVoter(APIView):
serializer_class = FillVoterListSerializers
permission_classes = (AllowAny,)
def post(self, request,*args,**kwargs):
isDataExist = VoterList.objects.get(id=request.data.get('id'))
if not isDataExist:
return Response({"message":"No Voter exist with this id."})
else:
isDataUpdated = self.serializer_class(isDataExist, request.data, partial=True)
if isDataUpdated.is_valid():
isDataUpdated.save()
return Response({"message": "Voter updated."})
else:
return Response({"message": "All fields are Mandatory."})
urls.py
urlpatterns = [
url('api/updateVoter/(?P<id>[0-9]+)/$', UpdateVoter.as_view(), name= "updateVoter")]
So what code should i write in my view.py to handle the PUT request.
Note: I want to tell you that i am preparing api for mobile applications, so please respond accordingly.
Any help is appreciated.

You can use the put() function in your view similar to the post() which you've used
def put(self, request, pk, format=None):
# Your code here
Refer the DRF docs : https://www.django-rest-framework.org/tutorial/3-class-based-views/

Related

How to have a permission-based user system in Django?

I want to build a REST API where user can do operations on objects, based on their permissions. Consider a record that represents a car - it contains the license number, the type of the car and extra information. Also consider the following user system:
Owners - Who own the car object. Can modify it and delete it.
Editors - Who can only modify the object properties.
Viewers - Can only view the object properties.
Each record can contain multi owners/editors/viewers (The user who created the object should be automatically the owner). Also, owners can add or remove editors/viewers. In my head, I see it as a list of owners/editors/viewers.
So in case of a GET request, I want to be able to return all objects that the user has permissions for, separated into those three categories.
So under my api app, I have the following code:
The models.py file contains:
class CarRecord(models.Model):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
The serializers.py file contains:
class CarRecordSerializer(serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
class Meta:
model = CarRecord
fields = ('__all__')
In view.py I have:
class CarRecordViews(APIView):
def get(self, request):
if not request.user.is_authenticated:
user = authenticate(username=request.data.username, password=request.data.password)
if user is not None:
return Response(data={"error": "invalid username/password"}, status=status.HTTP_401_UNAUTHORIZED)
# return all records of cars that user some type of permission for
Now, I want to get all the records of user that he has permissions to query (along with their permission type). I thought of adding a three extra fields under CarRecord - each one is a list of users that contains that permission type. But I'm not sure if it's the "Django way". So wanted to consult first with SO.
EDIT: I tried to add the following field to my CarRecord class:
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[])
Also I added:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username']
lass CarRecordSerializer(serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = UserSerializer(many=True)
class Meta:
model = CarRecord
fields = ('__all__')
And the way I create the CarRecordSerializer instance is:
serializer = CarRecordSerializer(data=request.data)
But I get:
{
"error": {
"owners": [
"This field is required."
]
}
}
How to make it work? I guess is my problem is how to serialize a ManyToMany object?
EDIT2: My second attempt is:
class CarRecord(models.Model):
date_created = models.DateTimeField()
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[]))
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
# ...
class CarRecordSerializer(serializers.ModelSerializer):
date_created = serializers.DateTimeField(default=datetime.now(timezone.utc))
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
creator = serializers.StringRelatedField()
owners = serializers.PrimaryKeyRelatedField(many=True,read_only=True)
class Meta:
model = CarRecord
fields = '__all__'
def create(self, validated_data):
self.owners = [self.context['creator']]
record = CarRecord(**validated_data, creator=self.context['creator'])
record.save()
return record
# ...
# In post method:
serializer = CarRecordSerializer(data=request.data, context={ 'creator': user })
But now, in GET method, I filter the owners list with the user and it can't find the objects:
> CarRecord.objects.filter(owners=user)
<QuerySet []>
Also, in the Admin section I see that all of the objects automatically have all the users in the owners/editors/viewers lists. Why is that? Owners should contain only the user that created the record and editors and viewers should be empty lists. In another query, owner can add additional owners/editors/viewers.
Here is the solution I might think is the right one
class CarRecord(models.Model):
date_created = models.DateTimeField(auto_now_add=True)
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners')
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
class CarRecordSerializer(serializers.ModelSerializer):
creator = serializers.PrimaryKeyRelatedField(queryset=User.objects.all(), required=False)
owners_details = UserSerializer(source='owners', many=True, read_only=True)
class Meta:
model = CarRecord
fields = '__all__'
def create(self, validated_data):
try:
new_owners = validated_data.pop('owners')
except:
new_owners = None
car_record = super().create(validated_data)
if new_owners:
for new_owner in new_owners:
car_record.owners.add(new_owner)
return car_record
In views.py
from rest_frameword import generics
from rest_framework import permissions
class CustomCarRecordPermissions(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if request.method == 'GET':
return True
elif request.method == 'PUT' or request.method == 'PATCH':
return request.user == obj.creator or request.user in obj.owners.all()
elif request.method == 'DELETE':
return request.user == obj.creator
return False
class CarRecordListCreate(generics.ListCreateAPIView):
permission_classes = (IsAuthenticated, )
serializer_class = CarRecordSerializer
queryset = CarRecord.objects.all()
def post(self, request, *args, **kwargs):
request.data['creator'] = request.user.id
return super().create(request, *args, **kwargs)
class CarRecordDetailView(generics.RetrieveUpdateDestroyAPIView):
permission_classes = (CustomCarRecordPermissions, )
serializer_class = CarRecordSerializer
lookup_field = 'pk'
queryset = CarRecord.objects.all()
models is self explanatory;
In CarRecord serializers we set creator as required False and primary key related field so that we can supply request user id before create as shown in views.py post method.
In Detail view we set our custom permission; If the request is GET we allow permissions. But if the request is PUT or PATCH the owners and the creator are allowed. But if it is a delete request only creator is allowed.
I think the django-rest-framework-guardian package fits here. This package is based on django-guardian.
django-guardian is an implementation of object permissions for Django providing an extra authentication backend.
There is no change on your models.py
You should change serializers.py and views.py.
For example, your serializer should look like this
from rest_framework_guardian.serializers import ObjectPermissionsAssignmentMixin
class CarRecordSerializer(ObjectPermissionsAssignmentMixin, serializers.ModelSerializer):
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
class Meta:
model = CarRecord
fields = ('__all__')
def get_permissions_map(self, created):
current_user = self.context['request'].user
readers = Group.objects.get(name='readers')
editors = Group.objects.get(name='editors')
owners = Group.objects.get(name='owners')
return {
'view_car_record': [current_user, readers, owners],
'change_car_record': [current_user, editors],
'delete_car_record': [current_user, owners]
}
and your views should look like this:
from rest_framework_guardian import filters
class CarRecordModelViewSet(ModelViewSet):
queryset = CarRecord.objects.all()
serializer_class = CarRecordSerializer
filter_backends = [filters.ObjectPermissionsFilter]
Edit settings.py like this:
INSTALLED_APPS = [
'rest_framework',
'guardian',
]
AUTHENTICATION_BACKENDS = [
"django.contrib.auth.backends.ModelBackend",
"guardian.backends.ObjectPermissionBackend",
]
You can define filter backends globally in your settings, too:
REST_FRAMEWORK = {
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend",
"rest_framework_guardian.filters.ObjectPermissionsFilter",
],
}
Don't forget! If you define the ObjectPermissionsFilter in the settings.py, your all views are affected by this filter.
If you want to restrict post request per user, you shoul implement custom permission class, like this:
from rest_framework import permissions
class CustomObjectPermissions(permissions.DjangoObjectPermissions):
"""
Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
"""
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}
Check this link to get the detailed information for the CustomObjectPermissions
You can write permission class car owner user.
Your model.
class CarRecord(models.Model):
date_created = models.DateTimeField()
type = models.CharField(max_length=50)
license = models.CharField(max_length=50)
owners = models.ManyToManyField(User, related_name='car_owners', verbose_name=('owners'), default=[]))
creator = models.ForeignKey(User,on_delete=models.DO_NOTHING)
Permission class permission.py
from rest_framework.permissions import BasePermission,
from cars.models import CarRecord
class isCarAccess(BaseCommand):
def has_permission(self, request, view):
if request.method == 'OPTIONS':
return True
check_user = CarRecord.objects.filter(owners__in=[request.user])
return request.user is not None and request.user.is_authenticated and check_user
this permission class will check that does user exists, user is authenticated and as well the user belongs to the card record or not.
And you can pass this permission in your view.
from .permission import isCarAccess
from .models import CarRecord
class CarRecordViews(APIView):
permission_classes = [isCarAccess]
def get(self, request):
car_record = CarRecord.objects.filter(owners__in=[request.user])
# return all records of cars that user some type of permission for
and your settings.py
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
"oauth2_provider.contrib.rest_framework.OAuth2Authentication",
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.TokenAuthentication",
),
}

How to pass data to serializers in django

I want to pass user_id from view to serializer
I have model Answer
class Answer(models.Model) :
text = models.CharField(max_length=500)
question_id = models.CharField(max_length=25)
user_id = models.CharField(max_length=25, default=1)
This is my Serializer
class CreateAnswer(generics.CreateAPIView) :
def get_serializer_context(self):
context = super().get_serializer_context()
context["id"] = self.request.user.id
return context
serializer_class = AnswerQuestionSerializer
queryset = Answer.objects.all()
What I need to write in my view to take user_id and create model with this user_id ?
You can override the perform_create method & pass the user_id field to save method of the serializer.
class CreateAnswerView(generics.CreateAPIView) :
serializer_class = AnswerQuestionSerializer
def perform_create(self, serializer):
serializer.save(user_id=self.request.user.id)
You can use serializers.Hiddenfield to get current user in serializer class
https://www.django-rest-framework.org/api-guide/fields/#hiddenfield
There are multiple ways to do this task. One of them is to override create in your serializer.
Following is the code snippet:
class BlogSerializer(serializers.Serializer):
def create(self, validated_data):
user = self.context['request'].user
blog = Blog.objects.create(
user=user,
**validated_data
)
return blog
Explanation: A context is passed to the serializer which contains the request by default. So you can access the user easily with self.context['request'].user

update_or_create in my django rest framework api work wrong

My problem in GIF
Instead of updating the user's rating DRF creating new.
Maybe i made a mistake in serializer?
I wrote documentation but i dont kwon where i wrong.
My code:
views.py:
class CreateReviewView(APIView):
def post(self, request):
review = CreateReviewSerializer(data= request.data)
if review.is_valid():
review.save()
return Response(status=201)
class CreateRatingView(APIView):
def get_user(self, request):
user= request.user
if user =="AnonymousUser":
return "noname in CreateRaringView"
return user
def post(self, request):
serializer = CreateRatingSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(user=self.get_user(request))
return Response(status=201)
else:
return Response(status=400)
serializers.py:
class Meta:
model = Rating
fields = ('star','movie')
def new(self,validated_data):
rating = Rating.objects.update_or_create(
user= validated_data.get('user',None),
movie= validated_data.get('movie',None),
defaults={'start': validated_data.get("star")}
)
return rating
models.py:
class Rating(models.Model):
"""Рейтинг"""
user = models.ForeignKey(User,on_delete=models.CASCADE,verbose_name="Пользователь",related_name='user')
star = models.ForeignKey(RatingStar, on_delete=models.CASCADE, verbose_name="Звезда",related_name="star")
movie = models.ForeignKey(Movie, on_delete=models.CASCADE, verbose_name="Фильм",related_name="movie")
def __str__(self):
return f"{self.star} - {self.movie}"
class Meta:
#unique_together = ['user','movie','star']
verbose_name = "Рейтинг"
verbose_name_plural = "Рейтинги"
According to documentation, Calling .save() will either create a new instance, or update an existing instance, depending on if an existing instance was passed when instantiating the serializer class:
# .save() will create a new instance.
serializer = CommentSerializer(data=data)
# .save() will update the existing `comment` instance.
serializer = CommentSerializer(comment, data=data)
In your case you are only passing new data and missing existing instance.
def post(self, request):
serializer = CreateRatingSerializer(data=request.data)
I renamed def new(self,validated_data): to def create(self,validated_data): in serializers.py and all started working. >.<

Django: Update a specific field with a GET instead of a PATCH

Context
For a specific use case I need to be able to update a single field of my Visitor model using a GET request instead of a PATCH request.
My relevant Visitor model looks like this:
# models.py
class Visitor(models.Model):
visitor_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
customers = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_visitors')
audiences = models.ManyToManyField(Audience, related_name='audience_visitors')
cid = models.CharField(max_length=255, unique=True)
uid = models.CharField(max_length=255)
cup = JSONField(null=True)
def __str__(self):
return self.cid
class Meta:
db_table = 'visitor'
I am using a straightforward serializer like this:
# serializers.py
class VisitorSerializer(serializers.ModelSerializer):
class Meta:
model = Visitor
fields = ('customers', 'cid', 'uid', 'cup')
I am able to update just the cup field for a specific Visitor which is looked up using the unique cid field with a PATCH like this:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.serializer_class(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
Problem
The problem is that I am unable to update the cup field of a Visitor based on a given unique cid field using a GET request.
What I tried
As this answer by Uri Shalit suggested, I tried to override get_serializer() inside my VisitorViewSet and tried to use it in list() like this:
# views.py
class VisitorViewSet(viewsets.ModelViewSet):
serializer_class = VisitorSerializer
queryset = Visitor.objects.all()
lookup_field = 'cid'
def get_serializer(self, *args, **kwargs):
kwargs['partial'] = True
return super(VisitorViewSet, self).get_serializer(*args, **kwargs)
def list(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=True)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data)
However, updating just the cup field of a specific Visitor based on the cid field works with a PATCH request but does not update said field with a GET request. There is no error either.
Expected behaviour
Making a GET request which contains cid to identify a Visitor and cup with data that needs to be updated for the given Visitor. I know it breaks REST principles but for this use case I need to do this partial update using a GET request instead of a PATCH request.
Any help or pointers in the right direction would be much appreciated!
Add a classmethod in your model.
class Visitor(models.Model):
visitor_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
customers = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer_visitors')
audiences = models.ManyToManyField(Audience, related_name='audience_visitors')
cid = models.CharField(max_length=255, unique=True)
uid = models.CharField(max_length=255)
cup = JSONField(null=True)
def __str__(self):
return self.cid
class Meta:
db_table = 'visitor'
#classmethod
def update_cup(cls, cid, cup_new):
instance = cls.objects.get(cid=cid)
instance.cup = new_cup
instance.save()
In ModelViewSet override the get_queryset method, see below:
IDK how u calc new_cup I guess u get it as a queryparam
def get_queryset(self):
queryset = Visitor.objects.all()
cup_new = self.request.query_params.get('cup_new', None)
cid = self.request.query_params.get('cid', None)
[obj.update_cup(obj.cid, cup_new) for obj in queryset if obj.cid == cid]
return queryset
I recommend using an api_view to accomplish what you want. api_view is an annotation provided by the rest framework so it should be available already in your case.
#api_view(["GET"])
def update_function(request):
query_params = request.GET # Getting the parameters from request
cid = query_params["cid"]
cup = query_params["cup"]
visitor = Visitor.objects.get(cid = cid)
visitor["cup"] = cup
serializer = VisitorSerializer(data = visitor, partial=True)
if serializer.is_valid():
serializer.save()
else:
print(serializer.errors)
However I am not sure about the syntax but the approch is sufficient for your problem.
Make sure to add the function to urls.py and have a look to the documentation to get better information than mine Api Views. But dont expect it to have information about you specific problem. In your case you have to understand the api_view concept and adapt it for your needs.
I think I don't understand the problem fully. Why can't you simply override the method get_object() in your view and do custom logic in it to update the object?
def get_object(self):
obj = super().get_object()
serializer = self.get_serializer(obj, data=self.request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return obj

Update user error with Django API rest framework

I can`t update users because Django gives me this error in postman:
AttributeError at /profesionales/
Got AttributeError when attempting to get a value for field `user` on serializer `ProfesionalesSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `User` instance.
Original exception text was: 'User' object has no attribute 'user'.
Request Method: PUT
Request URL: http://127.0.0.1:8000/profesionales/
Django Version: 1.11.6
Python Executable: C:\Users\Ismael\AppData\Local\Programs\Python\Python36\python.exe
Python Version: 3.6.3
Here is my code:
view.py
#Listar todos los profesionales o crear uno
#profesionales/
class ProfesionalesList(APIView):
def get_object(self, pk):
try:
return User.objects.get(username=pk)
except User.DoesNotExist:
raise Http404
def get(self, request ):
usuarios = Profesionales.objects.all()
usuarioSerializer = ProfesionalesSerializer(usuarios, many=True)
return Response(usuarioSerializer.data)
def post(self, request):
profesionalSerializer = ProfesionalesSerializer(data=request.data)
if profesionalSerializer.is_valid():
profesionalSerializer.save()
return Response(profesionalSerializer.data, status=status.HTTP_201_CREATED)
else:
return Response(profesionalSerializer.errors, status=status.HTTP_400_BAD_REQUEST)
def put(self, request, *args, **kwargs):
instance = self.get_object(request.data.get('user').get('username'))
profesionalSerializer = ProfesionalesSerializer(instance, data=request.data)
if profesionalSerializer.is_valid():
profesionalSerializer.save()
return Response(profesionalSerializer.data, status=status.HTTP_201_CREATED)
else:
return Response(profesionalSerializer.errors, status=status.HTTP_400_BAD_REQUEST)
serializers.py
class UserSerializer(serializers.Serializer):
username = serializers.CharField()
first_name = serializers.CharField(allow_blank=True)
last_name = serializers.CharField(allow_blank=True)
email = serializers.CharField(allow_blank=True)
class Meta:
fields = ('username', 'first_name', 'last_name', 'email')
def create(self, validated_data):
user = User.objects.create(**validated_data)
return user
class ProfesionalesSerializer(serializers.Serializer):
user = UserSerializer()
numColegiado = serializers.CharField(allow_blank=False)
class Meta:
fields = ('user', 'numColegiado')
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
profesional = Profesionales.objects.create(user=user, **validated_data)
return profesional
def update(self, instance, validated_data):
num_colegiado = validated_data.get('numColegiado')
user_data = validated_data.pop('user')
user = User.objects.get(**user_data)
profesionales = user.profesionales
if num_colegiado:
profesionales.numColegiado = num_colegiado
profesionales.save()
return instance
model.py
class Profesionales(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
dni = models.CharField(max_length=9, blank=True, default='')
numColegiado = models.CharField(max_length=8, blank=True, default='')
valoracionMedia = models.FloatField(blank=True, default=0)
numVotos = models.IntegerField(blank=True, default=0)
def __str__(self):
return self.numColegiado
Ok, I have it - but to be honest, you should rethink your API design.
The problem is that - there is no problem -I mean from yout code I cannot reproduce the error. It is probably I assumed the User model - if you can paste the user model definition would be great (or if this is a standard django user - also mention that).
So firstly I would change the serializers to model serializers:
serializers.py
class UsernameValidator(object):
def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# Determine the existing instance, if this is an update operation.
self.instance = getattr(serializer_field.parent, 'instance', None)
if not self.instance:
# try to get user from profesionales:
root_instance = getattr(serializer_field.root, 'instance', None)
self.instance = getattr(root_instance, 'user', None)
def __call__(self, value):
if self.instance and User.objects.filter(username=value).exclude(id=self.instance.id).exists():
raise ValidationError('Username already exists.')
if not self.instance and User.objects.filter(username=value).exists():
raise ValidationError('Username already exists.')
class UserSerializer(serializers.ModelSerializer):
username = serializers.CharField(max_length=128, validators=[UsernameValidator()])
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class ProfesionalesSerializer(serializers.ModelSerializer):
user = UserSerializer()
numColegiado = serializers.CharField(allow_blank=False)
class Meta:
model = Profesionales
fields = ('user', 'numColegiado')
def create(self, validated_data):
user_data = validated_data.pop('user')
user = User.objects.create(**user_data)
profesional = Profesionales.objects.create(user=user, **validated_data)
return profesional
def update(self, instance, validated_data):
user_data = validated_data.pop('user')
user = instance.user
userSerializer = UserSerializer(user, data=user_data)
if userSerializer.is_valid(raise_exception=True):
userSerializer.save()
num_colegiado = validated_data.get('numColegiado')
if num_colegiado:
instance.numColegiado = num_colegiado
instance.save()
return instance
As you can note - I've added the UsernameValidator which is pretty important for API to work properly 0- it basically search for existing user instance and check if username exists or not;
I've also changed the update method - now it is using the UserSerializer explicite; Also corrected some bugs - returning validated_data instead of instance and so on.
At the end views.py:
class ProfesionalesList(APIView):
def get_object(self, pk):
try:
return User.objects.get(username=pk)
except User.DoesNotExist:
raise Http404
def get(self, request ):
usuarios = Profesionales.objects.all()
usuarioSerializer = ProfesionalesSerializer(usuarios, many=True)
return Response(usuarioSerializer.data)
def post(self, request):
profesionalSerializer = ProfesionalesSerializer(data=request.data)
if profesionalSerializer.is_valid(raise_exception=True):
profesionalSerializer.save()
return Response(profesionalSerializer.data, status=status.HTTP_201_CREATED)
def put(self, request, *args, **kwargs):
user = self.get_object(request.data.get('user').get('username'))
profesionalSerializer = ProfesionalesSerializer(user.profesionales, data=request.data)
if profesionalSerializer.is_valid(raise_exception=True):
profesionalSerializer.save()
return Response(profesionalSerializer.data, status=status.HTTP_200_OK)
I've shorten the code - using the raise_exception in is_valid method.
Actually - sorry for not following the stackoverflow rules - and do not provide an answer for your actual problem - but I strongly believe that analyzing the example you can figure it out. If you have any more questions - please ask.
On your class ProfesionalesSerializer, you have defined user as an instance of UserSerializer. Instead, user should be a field. You can't use serializers as "fields".
Edit: Ignore this. Turns out you can. See here: http://www.django-rest-framework.org/api-guide/serializers/#dealing-with-nested-objects
(thanks to #opalczynski)

Categories