How to create or save Data using RestFramework viewsets.? - python

I created two models that are interlinked with each other.
class Company(models.Model):
company_name = models.CharField(max_length=50, unique=True)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.company_name
class Order_Placement(models.Model):
company = models.ForeignKey(Company, on_delete=models.SET_NULL, null=True)
product_quantity = models.IntegerField()
product_price = models.FloatField()
product_total_price = models.FloatField(blank=True, null=True)
other_cost = models.FloatField()
cost_of_sale = models.FloatField(blank=True, null=True)
advance_payment = models.FloatField()
remaining_payment = models.FloatField(default=0.0, blank=True)
date = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
self.product_total_price = self.product_price * self.product_quantity
self.cost_of_sale = self.product_total_price + self.other_cost
self.remaining_payment = self.cost_of_sale - self.advance_payment
super(Order_Placement, self).save(*args, *kwargs)
def __str__(self):
return str(self.company) + ' : ' + str(self.date.date())
I am trying to create a view that will help me to create an object or instant of the Order_placemen model
But when I try to post Data it rises an error while saving with post request:
Here I created a serializer for both company and Order_placement
class CompanySerializer(s.ModelSerializer):
class Meta:
model = m.Company
fields = '__all__'
class Order_PlacementSerializer(s.ModelSerializer):
class Meta:
model = m.Order_Placement
fields = '__all__'
def to_representation(self, instance):
response = super().to_representation(instance)
response['company'] = CompanySerializer(instance.company).data
return response
and I created a view for OrderPlacement using Django rest_framework.viewsets.ViewSet
class OrderProccessViewset(viewsets.ViewSet):
def create(self, request):
try:
serializer = s.Order_PlacementSerializer(data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
serializer.save()
dict_response = {"error": False, "message": "Order Save Successfully"}
except:
dict_response = {"error": True, "message": "Error During Saving Data"}
return Response(dict_response)
def list(self, request):
orderProccess = m.Order_Placement.objects.all()
serializer = s.Order_PlacementSerializer(orderProccess, many=True, context={"request": request})
response_dict = {"error": False, "message": "All List Data", "data": serializer.data}
return Response(response_dict)
When i print the prin(request.data) in create method its shown like this:
<QueryDict: {'company': ['1'], 'product_quantity': ['500'],
'product_price': ['530'], 'other_cost': ['1000'], 'advance_payment':
['0']}>

You need to fix your save method, because you misspeled kwargs's argument.
You wrote:
super(Order_Placement, self).save(*args, *kwargs)
and it should be:
super(Order_Placement, self).save(*args, **kwargs)

Related

Why is PUT request not updating the Django rest framework database?

I am trying to update the database using a PUT request. Currently, I am able to update the database from the Django Admin successfully but I want to do same using a PUT request.
When ever I make a PUT request, I get a 200 OK response with no errors but the data is not updating in the database. I dont know why. I am confused. Someone please help me. Thank you.
models.py
class User_Order(models.Model):
order = models.OneToOneField(Orders, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
id = models.IntegerField(primary_key=True)
shirts = models.IntegerField(default=0)
shorts = models.IntegerField(default=0)
trousers = models.IntegerField(default=0)
total_units = models.CharField(max_length=2000, blank=True)
shirts_amount = models.CharField(max_length=2000, blank=True)
shorts_amount = models.CharField(max_length=2000, blank=True)
trousers_amount = models.CharField(max_length=2000, blank=True)
total = models.CharField(max_length=200,blank=True)
verified = models.BooleanField(null=True)
doing_laundry = models.BooleanField(null=True)
delivery_underway = models.BooleanField(null=True)
delivered = models.BooleanField(null=True)
address = models.TextField(default='')
time = models.DateTimeField(auto_now=True)
def save(self, *args, **kwargs):
self.user = self.order.user
self.id = self.order.id
self.shirts = self.order.shirts
self.shorts = self.order.shorts
self.trousers = self.order.trousers
self.total_units = self.order.total_units
self.shirts_amount = self.order.shirts_amount
self.shorts_amount = self.order.shorts_amount
self.trousers_amount = self.order.trousers_amount
self.total = self.order.total
self.verified = self.order.verified
self.doing_laundry = self.order.doing_laundry
self.delivery_underway = self.order.delivery_underway
self.delivered = self.order.delivered
self.address = self.order.address
super().save(*args, **kwargs)
def __str__(self):
return f'{self.order.user.username} Order'
serializers.py
class UserUser_OrderSerializer(serializers.ModelSerializer):
class Meta:
model = User_Order
fields = '__all__'
views.py
#api_view(['PUT'])
def UserOrdersUpdate(request, pk):
permission_classes = [IsAuthenticated]
user_order = User_Order.objects.get(id=pk)
if request.method == 'PUT':
serializer = UserUser_OrderSerializer(instance=user_order, data=request.data, many = False, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
Maybe it's because in User_Order.save() method you replace all fields from User_Order where all the data from serializer is stored with Order instance values.
Also you can use class based view UpdateAPIView to simplify it:
class UserOrdersUpdateView(generics.ListCreateAPIView):
queryset = User_Order.objects.all()
serializer_class = UserUser_OrderSerializer
permission_classes = [IsAuthenticated]
Docs:
UpdateAPIView
Used for update-only endpoints for a single model instance.
Provides put and patch method handlers.
Extends: GenericAPIView, UpdateModelMixin.

Cannot create list of objects in django rest framework

I am using ListSerializer for updating and creating list of objects, update() works fine but cannot create list of objects (bulk_create).
models.py
class TutorUser(models.Model):
tutor_user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='tutor')
full_name = models.CharField(max_length=255, blank=True)
phone_number = models.CharField(max_length=14, blank=True)
class WorkExperiance(models.Model):
tutor_work = models.ForeignKey(TutorUser,
related_name='tutor_work',
on_delete=models.CASCADE)
organization = models.CharField(max_length=255, blank=True)
start_year = models.IntegerField(null=True, blank=True)
serializers.py
class WorkExperianceListSerializer(serializers.ListSerializer):
def update(self, instance, validated_data):
tutor_work_mapping = {tutor_work.id: tutor_work for tutor_work in instance}
data_mapping = {item['id']: item for item in validated_data}
ret = []
for tutor_work_id, data in data_mapping.items():
print(tutor_work_id)
tutor_work = tutor_work_mapping.get(tutor_work_id, None)
# print(tutor_work_id)
if tutor_work is None:
ret.append(self.child.create(data))
# print(ret)
else:
ret.append(self.child.update(tutor_work, data))
for tutor_work_id, tutor_work in tutor_work_mapping.items():
if tutor_work_id not in data_mapping:
tutor_work.delete()
class WorkExperianceSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(read_only=False)
class Meta:
list_serializer_class = WorkExperianceListSerializer
model = WorkExperiance
fields = [
'id',
'organization',
'start_year',
]
def update(self, instance, validated_data):
instance.organization = validated_data.get('organization', instance.organization)
instance.start_year = validated_data.get('start_year', instance.start_year)
instance.save()
return instance
views.py
class TutorWorkExperiance(APIView):
def get_object(self, request):
tutor = TutorUser.objects.get(tutor_user__id=request.user.id)
tutor_work = WorkExperiance.objects.filter(tutor_work=tutor)
return tutor_work
def put(self, request):
serializer = WorkExperianceSerializer(self.get_object(request), data = request.data, partial = True, many=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response(serializer.data)
return Response({"data": "Not valid"})
In my opinion the problem is here with ID, because WorkExperiance model foreign key with TutorUser model, and I cannot pass its ID when object is created. I am using only put method for both creating and updating.
Problem solved.
The issue is requesting post without ID, cause id = serializers.IntegerField(read_only=False) defined in serializer, and also forgot to pass TutorUser Id which foreign key with WorkExperiance.
views.py:
def put(self, request):
tutor = TutorUser.objects.get(tutor_user__id=request.user.id)
serializer = WorkExperianceSerializer(self.get_object(request), data = request.data, partial = True, many=True)
if serializer.is_valid(raise_exception=True):
serializer.save(tutor_user=tutor)
return Response(serializer.data)
return Response({"data": "Not valid"})

Cannot assign "<User: kdkd#gmail.com>": "Movie.owner" must be a "Suppliers" instance

I am trying to assign an owner as an object and I must be doing it wrong because it is still raising
Cannot assign "<User: kdkd#gmail.com>": "Movie.owner" must be a "Suppliers" instance.
Request Method: POST
This is my serializer for my Movie model.
class MovieTicketSerializer(serializers.ModelSerializer):
class Meta:
model = Movie
fields = ['owner', 'title', 'price', 'date', 'description', 'seat', 'choice', 'active']
def create(self, validated_data):
owner = self.context['request'].user
movie = Movie.objects.create(owner=owner, active=True, **validated_data)
return movie
And this is the View
#api_view(['POST', ])
#permission_classes([IsAuthenticated, ])
def movie_ticket_detail(request):
if request.method == 'POST':
serializer = MoveTicketSerializer(data=request.data, context={'request': request})
data = {}
if serializer.is_valid():
ticket = serializer.save()
data['request'] = ' ticket is instantiated '
data['title'] = ticket.title
data['owner'] = ticket.owner
else:
data = serializer.errors
return Response(data)
class TicketModel(models.Model):
owner = models.ForeignKey(Suppliers, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=30, default='TICKET')
price = models.IntegerField()
date = models.CharField(max_length=20)
description = models.TextField(max_length=300, blank=False)
posted = models.DateTimeField(default=now, editable=False)
active = models.BooleanField(default=False)
class Meta:
abstract = True
class Movie(TicketModel):
seat = models.IntegerField(null=True)
choice = models.IntegerField(choices=TYPE_OF_MOVIES_CONCERT_OTHERS, default=1)
def __repr__(self):
return {'title': self.title, 'price': self.price, 'description': self.description, 'date': self.date}
You can not return model instances or queryet instead you need to return native python data type in the format json, xml or other content types. First Create Serialzier
class SupplierSerializer(ModelSerializer):
class Meta:
model = Supplier
fields = '__all__' # Or sepecific fields ['id','name']
Then Use serializer as below.
# you need to get Supplier object
supplier_obj = get_object_or_404(Supplier,user=ticket.owner)
data['owner'] = SupplierSerializer(supplier_obj).data
OR
supplier_obj = get_object_or_404(Supplier,user=ticket.owner)
data['owner'] = supplier_obj.id # just return id
def create(self, validated_data):
owner = Suppliers.objects.get(email=self.context['request'].user)
movie = Movie.objects.create(owner=owner, active=True, **validated_data)
return HttpResponse(movie, content_type="text/json-comment-filtered")
is there something wrong with implementing it like this. it works.

How to create the one to many relationship based file upload using serialization

Only save the Project model fields doesn't create the project documents model fields
Models.py
class Project(BaseModel):
name = models.CharField(max_length=100, blank=True, null=True)
class Meta:
db_table = 'project_details'
ordering = ['is_active']
class ProjectDocuments(BaseModel):
file = models.FileField(upload_to="files/%Y/%m/%d")
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='projectdocuments')
class Meta:
db_table = 'project_document_details'
ordering = ['is_active']
views.py:
def post(self, request, format=None):
user_id = request.user.id
current_date = datetime.now()
data = copy.deepcopy(request.data)
file_fields = list(request.FILES.values()) # list to be passed to the serializer
data['is_active'] = True
data['created_by'] = user_id
data['created_date'] = current_date
data['modified_by'] = user_id
data['modified_date'] = current_date
serializer = ProjectSerializer(data=data, file_fields=file_fields)
if serializer.is_valid():
serializer.save()
serializer.py:
class ProjectSerializer(serializers.ModelSerializer):
def init(self, *args, **kwargs):
file_fields = kwargs.pop('file_fields', None)
super(ProjectSerializer, self).__init__(*args, **kwargs)
if file_fields:
field_update_dict = {str(field): serializers.FileField(required=False, write_only=True) for field in file_fields}
print "FILE UPDATE DICT ------------>",field_update_dict
self.fields.update(**field_update_dict)
def create(self, validated_data):
validated_data_copy = validated_data.copy()
validated_files = []
for key, value in validated_data_copy.items():
if isinstance(value, InMemoryUploadedFile):
validated_files.append(value)
validated_data.pop(key)
submission_instance = super(ProjectSerializer, self).create(validated_data)
for file in validated_files:
ProjectDocuments.objects.create(submission=submission_instance, file=file)
return submission_instance
class Meta:
model = Project
fields = '__all__'

DRF, "required": "This field is required."

I can't get a valid response, always get this error
{"required": "This field is required.", "null": "This field may not be null.", "not_a_list": "Expected a list of items but got type \"{input_type}\".", "empty": "This list may not be empty."}
Here is some code (models, serializers, views)
models
class Task(models.Model):
name = models.CharField(max_length=50)
description = models.CharField(max_length=500, blank=True, default='')
pub_datetime = models.DateTimeField()
priority = models.CharField(choices=PRIORITY_CHOICES, max_length=1)
status = models.BooleanField(default=False)
owner = models.ForeignKey('auth.User', on_delete=models.CASCADE)
agenda = models.ForeignKey(Agenda, on_delete=models.CASCADE, blank=True, default=None, null=True)
def __str__(self):
return self.name
serializers
class TaskSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.username')
agenda = serializers.ReadOnlyField(source='agenda.name')
class Meta:
model = Task
fields = ('id', 'name', 'description', 'pub_datetime', 'priority', 'status', 'owner', 'agenda')
views
class TaskListView(generics.ListCreateAPIView):
serializer_class = TaskSerializer
permission_classes = (permissions.IsAuthenticated,)
renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
template_name = 'task_list.html'
def get(self, request, *args, **kwargs):
queryset = Task.objects.filter(owner=self.request.user)
if self.request.accepted_renderer.format == 'html':
return Response({'tasks': queryset})
else:
serializer = TaskSerializer(data=queryset, many=True)
if serializer.is_valid():
return JsonResponse(serializer.data, safe=False)
else:
return JsonResponse(serializer.error_messages)
def post(self, request, *args, **kwargs):
name = request.data['name']
description = request.data['description']
priority = request.data['priority']
new_task = Task.objects.create(name=name, description=description, pub_datetime=datetime.datetime.now(),
priority=priority, status=False, owner=self.request.user)
new_task.save()
return redirect('task-list')
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
I'm not sure, at what place I'm wrong. Can someone help?
just text to avoid errors
The queryset or object instance should be passed to serializer as instance, not data, so:
queryset = Task.objects.filter(owner=self.request.user)
serializer = TaskSerializer(instance=queryset, many=True)
Also, I believe that serializer can't validate instance, so in this case you should be able to just return return JsonResponse(serializer.data)

Categories