I'm building a REST web service, the GET method seems to be working all right
but when it comes to POST error message always shows up:
'dict' object has no attribute 'save'
models.py
from django.db import models
class Users(models.Model):
Fullname = models.CharField(max_length=50)
Username = models.CharField(max_length=15)
Password = models.CharField(max_length=8)
Email = models.CharField(max_length=50, unique=True)
Type = models.CharField(max_length=5)
TwitterName = models.CharField(max_length=15, unique=True)
FacebookName = models.CharField(max_length=15, unique=True)
CreationDate = models.DateTimeField()
serializer.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Users
fields = ('Fullname', 'Username', 'Email', 'Password', 'Type', 'TwitterName', 'FacebookName')
views.py
#api_view(['GET', 'POST'])
def users_list(request, format=None):
if request.method == 'GET':
users = Users.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = UserSerializer(request.DATA, many=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
I'm using PyCharm and Django 1.7
If you want to save the POST data then you should pass the data to data keyword argument:
serializer = UserSerializer(data=request.DATA, many=True)
if serializer.is_valid():
...
Also I would suggest you to use Class based views with Mixins as that will make your code much cleaner and shorter:
from rest_framework import generics, mixins
class UserList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Users.objects.all()
serializer_class = UserSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
Related
I am trying to write a create method but got a error i cannot fix. Would you be kind look at it and give me some advises? Seems like i am doing it totally wrong. I was also fighting with keyword argument but seems liked i fixed it... It should create Courses with Contacts and Branches.
models.py
class Branch(models.Model):
latitude = models.CharField(max_length=150)
longitude = models.CharField(max_length=150)
address = models.CharField(max_length=150)
def __str__(self):
return self.address
class Contact(models.Model):
CHOICES = (
(1,'Facebook'),
(2,'Email'),
(3, 'phone')
)
status = models.IntegerField(choices=CHOICES)
def __str__(self):
return f'{self.status}'
class Category(models.Model):
name = models.CharField(max_length=150)
imgpath = models.CharField(max_length=150)
def __str__(self):
return self.name
class Course(models.Model):
name = models.CharField(max_length=150)
description = models.CharField(max_length=150)
category = models.ForeignKey('Category', on_delete=models.CASCADE,
related_name='category', null=True)
logo = models.CharField(max_length=150)
contacts = models.ManyToManyField(Contact, related_name='contacts', null=True)
branches = models.ManyToManyField(Branch, related_name='branches', null=True)
def __str__(self):
return self.name
serializers.py (Here i am trying to create new course, branches and contacts)
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = ('id', 'name', 'imgpath')
class BranchSerializer(serializers.ModelSerializer):
class Meta:
model = Branch
fields = ('latitude', 'longitude', 'address')
class ContactSerializer(serializers.ModelSerializer):
class Meta:
model = Contact
fields = ('__all__')
class CourseSerializer(serializers.ModelSerializer):
category = CategorySerializer()
contacts = ContactSerializer(many=True)
branches = BranchSerializer(many=True)
class Meta:
model = Course
fields = ['name', 'description','logo', 'category', 'contacts', 'branches']
def create(self, validated_data):
category_data = validated_data.pop('category')
category = Category.objects.create(**category_data)
contacts_data = validated_data.pop('contacts')
branches_data = validated_data.pop('branches')
course = Course.objects.create(**validated_data)
for contact_data in contacts_data:
Contact.objects.create(course=course, **contact_data)
for branch_data in branches_data:
Branch.objects.create(course=course, **branch_data)
return course
views.py
class CoursesView(views.APIView):
def get(self, request, *args, **kwargs):
course = Course.objects.all()
serializer = CourseSerializer(course, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
serializer = CourseSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response({'data': 'OK'}, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors)
class CoursesDetailView(views.APIView):
def get(self, request, *args, **kwargs):
doctor = Course.objects.get(id=kwargs['course_id'])
serializer = CourseSerializer(doctor)
return Response(serializer.data)
def delete(self, request, *args, **kwargs):
course = Course.objects.get(id=kwargs['course_id'])
course.delete()
return Response({"data": "Delete successful!"})
class CategoryView(views.APIView):
def get(self, request, *args, **kwargs):
category = Category.objects.all()
serializer = CategorySerializer(category, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
serializer = CategorySerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class BranchView(views.APIView):
def get(self, request, *args, **kwargs):
branch = Branch.objects.all()
serializer = CategorySerializer(branch, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
serializer = BranchSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ContactView(views.APIView):
def get(self, request, *args, **kwargs):
contact = Contact.objects.all()
serializer = CategorySerializer(contact, many=True)
return Response(serializer.data)
def post(self, request, *args, **kwargs):
serializer = ContactSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Your Contact model has one field: status.
In Course serializer, in create method you have:
Contact.objects.create(course=course, **contact_data). But your Contact model doesn't have course field.
I suggest to start looking here.
MY model
class XP(models.Model):
bizuser = models.ForeignKey(BizUser, on_delete=models.CASCADE)
current_xp_price = models.IntegerField(default=0)
xp_created_at = models.DateTimeField(auto_now_add=True)
xp_updated_at = models.DateTimeField(auto_now_add=True)
i have this function that creates an XP i want if the current user is authenticated(jwttokens) the user can then go ahead to create the XP .when i go to post this data i get to fields that i have to fill that is current_xp_price and bizuser which is a ForeignKey
Views
class create_xp(APIView):
def post(self, request):
if request.user.is_authenticated:
current_user = request.BizUser
serializer = XPSerializer(data=request.data)
request.data["bizuser"] = current_user.id
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(status=status.HTTP_401_UNAUTHORIZED)
serializers
class XPSerializer(serializers.ModelSerializer):
class Meta:
model = XP
fields = ['current_xp_price', ]
I have UserProfile model that contains phone, profile_photo and some fields of Django default User model like first_name, last_name, email and I am trying to update some of these fields.
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, verbose_name="User")
phone = models.CharField(max_length=16, verbose_name="Phone")
profile_photo = models.ImageField(null=True, blank=True, upload_to=user_directory_path, verbose_name="Profile Photo")
serializers.py
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('url', 'first_name', 'last_name', 'email')
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(partial=True)
class Meta:
model = UserProfile
fields = '__all__'
def create(self, validated_data):
user_profile = UserProfile.objects.create(**validated_data)
return user_profile
views.py
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
authentication_classes = (TokenAuthentication,)
#detail_route(methods=['PATCH'], url_path='update-partial')
def user_profile_update_partial(self, request, pk=None):
profile = UserProfile.objects.get(id=pk)
serializer = self.get_serializer(profile, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
If I send profile_photo, phone, first_name or last_name data with this #detail_route I am only able to update phone and profile_photo fields. Also getting Bad Request error when profile_photo data not sending.
How can I implement the partial_update with PATCH method?
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
authentication_classes = (TokenAuthentication,)
def partial_update(self, request, *args, **kwargs):
profile = self.get_object()
serializer = self.get_serializer(profile, data=request.data, partial=True)
if serializer.is_valid():
user_serializer = UserSerializer(profile.user, data=request.data, partial=True)
if user_serializer.is_valid():
user_serializer.save()
serializer.save()
return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
else:
return Response(data=user_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(data=serializer.errors,status=status.HTTP_400_BAD_REQUEST)
Q1:How to implement PATCH method?
A1:Override partial_update method.
Q2:How to update first_name or last_name?
A2:Update it with another Serializer named UserSerializer.(If you want update password,you need use make_password method to create encoded password before save raw password to database)
I need code for editing user details like first_name , last_name by using APIView Class based. THe serializers.py and views.py are given under but it is not making the changes according to the user details . i am passing token for user authentication. Any assistance will be appreciated.
Serializers.py
class UserEditSerializer(serializers.Serializer):
email = serializers.EmailField(required=True)
first_name = serializers.CharField(required=True)
last_name = serializers.CharField(required=True)
def update(self, validated_data, instance):
instance.first_name = validated_data.get('first_name')
instance.email = validated_data.get('email')
instance.last_name = validated_data.get('last_name')
instance.save()
return instance
Views.py
class UserEditProfile(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def get_object(self):
return self.request.user
def post(self, request):
self.object = self.get_object()
serializer = UserEditSerializer(data=request.data)
if serializer.is_valid():
self.object.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors,status=status.HTTP_400_BAD_REQUEST)
How would the serializer know it must update a user if you don't provide it ?
serializer = UserEditSerializer(data=request.data)
should be:
serializer = UserEditSerializer(self.object, data=request.data)
Edit:
Also, remove the () after return instance
This view will work . Thanks Linovia
class UserEditProfile(APIView):
authentication_classes = (authentication.TokenAuthentication,)
permission_classes = (permissions.IsAuthenticated,)
def post(self, request):
obj = User.objects.get(id=request.user.id)
serializer = UserEditSerializer(obj, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
models.py
from django.db import models
from django.contrib.auth.models import User
class Element(models.Model):
name = models.CharField(max_length=20)
class Group(models.Model):
user = models.ForeignKey(User)
name = models.CharField(max_length=100)
elements = models.ManyToManyField(Element)
class Meta:
unique_together = ('user', 'name')
serializers.py
class ElementSerializer(serializers.HyperlinkedModelSerializer):
# group = serializers.ReadOnlyField(source='group.id')
class Meta:
model = Element
fields = ('name')
""" def save(self, group=None, *args, **kwargs):
if group is not None:
self.group = group
super(ElementSerializer, self).save(*args, **kwargs) """
class GroupSerializer(serializers.HyperlinkedModelSerializer):
elements = ElementSerializer(many=True)
class Meta:
model = Group
fields = ('url', 'name', 'elements')
views.py
class AddElement(APIView):
def get(self, request, pk, format=None):
serializer = ElementSerializer(context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, pk):
group = DBHandler.get_group_from_id(pk)
serializer = ElementSerializer(data=request.data, context={'request': request})
if not serializer.is_valid():
return Response(serializer.data, status=status.HTTP_400_BAD_REQUEST)
serializer.save()
# serializer.save(group = group)
return Response({}, status=status.HTTP_201_CREATED)
In my view, I'd like to create an Element from given data, then assign this Element to existing Group.
I tried passing group as a serializer save parameter, and it worked okay (commented code), but I don't know where to go next. How can I get an Element instance from ElementSerializer? Or is there another way of working this out?