Saving FieldIn Django Via API Call - python

I'm trying to create a new CustomerDetail object whenever an api is called.But the issue is, Whenever I try to create something for the favorite meal multi-selectfield, I get this error:
MultiValueDictKeyError at /api/customer/favorite_meal/
"'favorite_meal'"
This is the api:
#csrf_exempt
def favorite_meal(request):
if request.method == "POST":
access_token = AccessToken.objects.get(token = request.GET.get("access_token"),
expires__gt = timezone.now())
customer = access_token.user.customer
details = CustomerDetailSerializer(
CustomerDetails.objects.create(
customer = customer,
favorite_mean = request.POST["favorite_meal"]
))
return JsonResponse({"status" : "success"})
Here are my models:
class CustomerDetails(models.Model):
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='customer')
TYPE = (
('Time', (
('Breakfast', 'Breakfast'),
('Lunch', 'Lunch'),
('Dinner', 'Dinner'),
)),
)
favorite_meal = MultiSelectField(choices=TYPE)
interested_in = MultiSelectField(choices=CATEGORIES)
likes = models.ManyToManyField('Product')
completed_orders = models.IntegerField(default = "0", blank=True)
shares = models.IntegerField(default = "0", blank=True)
average_order = models.FloatField(default = "0.0", blank=True)
def __str__(self):
return self.customer.user.get_full_name()
In the request, I'm trying to select breakfast and lunch via the api. How would I do this?
Sending Params:
The status says success but, there is no Customer data in details

The MultiValueDictKeyError error raises when you are trying to access favorite_meal from request.POST, but the favorite_meal doesn't exist in request.POST
Try this
#csrf_exempt
def favorite_meal(request):
if request.method == "POST":
if not 'access_token' in request.POST:
return JsonResponse({"status": "'access_token' missing in POST payload"})
access_token = AccessToken.objects.get(token=request.POST.get("access_token"),
expires__gt=timezone.now())
customer = access_token.user.customer
if not 'favorite_meal' in request.POST and not request.POST["favorite_meal"]:
return JsonResponse({"status": "'favorite_meal' missing in POST payload"})
details = CustomerDetailSerializer(
CustomerDetails.objects.create(
customer=customer,
favorite_mean=request.POST["favorite_meal"]
))
return JsonResponse({"status": "success"})
Screenshot
UPDATE
#csrf_exempt
def favorite_meal(request):
if request.method == "POST":
if not 'access_token' in request.POST:
return JsonResponse({"status": "'access_token' missing in POST payload"})
access_token = AccessToken.objects.get(token=request.POST.get("access_token"),
expires__gt=timezone.now())
customer = access_token.user.customer
if not 'favorite_meal' in request.POST and not request.POST["favorite_meal"]:
return JsonResponse({"status": "'favorite_meal' missing in POST payload"})
for favorite_meal in request.POST["favorite_meal"]:
details = CustomerDetailSerializer(
CustomerDetails.objects.create(
customer=customer,
favorite_mean=favorite_meal
))
return JsonResponse({"status": "success"})

Related

PUT Request not Updating data-Django

I am using Postman to get my request. My GET and POST appear to be working fine. It's only when I go to update the data with PUT that its where I am running into the hiccup. Postman actually sends data back as if the object is being updated, but when I go to check via GET it's the same data as before. I have tried adding the hive data to the serializer.save, but it tells me I'm adding too many parameters.
models.py
class Inspection(models.Model):
hive = models.ForeignKey(Hive, on_delete=models.CASCADE)
user = models.ForeignKey(User,on_delete=models.CASCADE)
eggs = models.IntegerField()
larvae = models.IntegerField()
sealed_brood = models.IntegerField()
covered_bees = models.IntegerField()
nectar_honey = models.IntegerField()
pollen = models.IntegerField()
pest_spotted = models.CharField(max_length=200)
pest_action = models.CharField(max_length=200)
notes_concerns = models.CharField(max_length=300)
serializers.py
class InspectionSerializer(serializers.ModelSerializer):
class Meta:
model = Inspection
fields = ['id', 'eggs', 'larvae', 'sealed_brood', 'covered_bees', 'nectar_honey', 'nectar_honey', 'pollen', 'pest_spotted', 'pest_action', 'notes_concerns','user_id','hive','hive_id']
depth = 1
hive_id = serializers.IntegerField(write_only=True)
Views.py
#api_view(['GET', 'POST','PUT'])
#permission_classes([IsAuthenticated])
def inspection_details(request, pk):
hive = get_object_or_404(Hive, pk=pk)
inspection = Inspection.objects.filter(hive_id = hive.id, user=request.user)
if request.method == "GET":
serializer = InspectionSerializer(inspection, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
elif request.method == 'POST':
serializer = InspectionSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(user=request.user)
return Response(serializer.data,status.HTTP_200_OK)
elif request.method == 'PUT':
serializer = InspectionSerializer(hive, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
I think the instance variable is not correct, it should be inspection not hive.
#api_view(['GET', 'POST', 'PUT'])
#permission_classes([IsAuthenticated])
def inspection_details(request, pk):
hive = get_object_or_404(Hive, pk=pk)
inspection = Inspection.objects.filter(hive_id = hive.id, user=request.user)
...
elif request.method == 'PUT':
serializer = InspectionSerializer(inspection, data=request.data) # here
if serializer.is_valid(raise_exception=True):
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_200_OK)
First of all don't use if clause for is_valid. it raise exception anyway so if is not needed.
Next you need to update your serializer not saving it.
elif request.method == 'PUT':
serializer = InspectionSerializer(hive, data=request.data)
serializer.is_valid(raise_exception=True)
serializer.update(object_to_update,serializer.validated_data)
# if you want to return updated serialized data :
updated_serializer = InspectionSerializer(object_to_update)
return Response(updated_serializer.data, status=status.HTTP_200_OK)

I trial make Notification for Comment

I trial make Notification for Comment
by Many-to-many relationships
how fix it
raise TypeError(
TypeError: Direct assignment to the forward side of a many-to-many set is prohibited. Use NotfFaId.set() instead.
[17/Apr/2021 03:37:31] "POST /forum/addcomment/ HTTP/1.1" 500 73061
class CommentT(MPTTModel):
Topic = models.ForeignKey(Topic, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey( User, on_delete=models.CASCADE, related_name='author')
parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
NotfFaId = models.ManyToManyField( User, related_name='NotfFaVId', default=None, blank=True)
content = models.TextField()
publish = models.DateTimeField(auto_now_add=True)
status = models.BooleanField(default=True)
class MPTTMeta:
order_insertion_by = ['publish']
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
user_comment.NotfFaId = request.user
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
# CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })
don't work ,
raise ValueError('"%r" needs to have a value for field "%s" before '
ValueError: "<CommentT: CommentT object (None)>" needs to have a value for field "id" before this many-to-many relationship can be used.
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
user_comment.NotfFaId.set( request.user )
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })
thank Iain Shelvington,
it is word
I Called CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user) after user_comment.save(). You can't add many to many entries before you have saved both sides of the relationship – Iain Shelvington 2 hours ago
def addcomment(request):
if request.method == 'POST':
if request.POST.get('action') == 'delete':
id = request.POST.get('nodeid')
c = CommentT.objects.get(id=id)
c.delete()
return JsonResponse({'remove': id})
else:
comment_form = NewCommentTForm(request.POST)
# print(comment_form)
if comment_form.is_valid():
user_comment = comment_form.save(commit=False)
result = comment_form.cleaned_data.get('content')
user = request.user.username
user_comment.author = request.user
# user_comment.NotfFaId.set( request.user )
user_comment.save()
Topic.objects.get(id = request.POST.get('Topic') ).NotfFaV.add(request.user)
CommentT.objects.get(id=user_comment.id).NotfFaId.add(request.user)
return JsonResponse({'result': result, 'user': user,'id': user_comment.id })

Cannot assign "'7'": "Appointment.your_service" must be a "Service" instance

I'm working on a project "Beauty Parlour Management System" and I got this error (Cannot assign "'7'": "Appointment.your_service" must be a "Service" instance.) anyone here can help me, please.
When I am filling a book appointment form then I got this error.
models.py
class Service(models.Model):
name = models.CharField(max_length=50)
price = models.IntegerField(default=0)
image = models.ImageField(upload_to='uploads/productImg')
class Appointment(models.Model):
your_name = models.CharField(max_length=100)
your_phone = models.CharField(max_length=10)
your_email = models.EmailField(max_length=200)
your_service = models.ForeignKey('Service', on_delete=models.CASCADE, default=1)
your_date = models.DateField()
views.py
def appointments(request):
if request.method == 'GET':
return render(request, 'core/bookappointment.html')
else:
your_name = request.POST.get('your-name')
your_phone = request.POST.get('your-phone')
your_email = request.POST.get('your-email')
your_service = request.POST.get('your-service')
your_date = request.POST.get('your-date')
details = Appointment(
your_name = your_name,
your_phone = your_phone,
your_email = your_email,
your_service = your_service,
your_date = your_date)
details.save()
return render(request, 'core/appointments.html')
You create this by assigining the method to your_service_id field, if you work with your_service, it should be a Service object:
details = Appointment.objects.create(
your_name=your_name,
your_phone=your_phone,
your_email=your_email,
your_service_id=your_service,
your_date=your_date
)
That being said, it is usually better to validate, clean, and save the data with a ModelForm, not manually.
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.
def appointments(request,pk):
record = get_object_or_404(Service,pk=pk)
if request.method == 'POST':
form = appointmentsForm(request.POST,request.FILES)
if form.is_valid():
appointment= form.save(commit=False)
appointment.your_service = record
appointment.save()
return render(request, 'core/bookappointment.html')
else:
return render(request, 'core/appointments.html')

how to set a None value with django form

i have a form with a google map and when the user does not click on the map i need to send latitude and longitude as None to views.py ,this is views.py :
if request.method == "POST":
if request.user.is_authenticated:
if True:
form = CreatMeetingForm(request.POST,request.FILES)
print(request.POST)
if form.is_valid():
if 'id' in request.POST:
obj= get_object_or_404(Meeting, id=request.POST.get('id'))
form = CreatMeetingForm(request.POST or None,request.FILES or None, instance= obj)
meeting= form.save(commit= False)
members = form.cleaned_data['members_email']
try:
meeting.lat= round(form.cleaned_data['lat'],14)
meeting.lng = round(form.cleaned_data['lng'],14)
except :
meeting.lat= None
meeting.lng = None
meeting.host = request.user
update = True
meeting.save()
else :
meeting=form.save(commit=False)
members = form.cleaned_data['members_email']
try:
meeting.lat= round(form.cleaned_data['lat'],14)
meeting.lng = round(form.cleaned_data['lng'],14)
except :
meeting.lat= None
meeting.lng = None
meeting.host = request.user
update=False
meeting.save()
else:
print('form not valid')
form.errors["code"] = 0
return JsonResponse(form.errors)
else:
return HttpResponse('Unauthorized', status=401)
and this is my model fields:
lat = models.DecimalField(max_digits=19, decimal_places=16,blank=True,null=True)
lng = models.DecimalField(max_digits=19, decimal_places=16,blank=True,null=True)
when i want to create a new form my code works but when in edit mode and i send the id in requet.POST it raises this error:
{"lat": ["Enter a number."], "lng": ["Enter a number."], "code": 0}
it seems i get the error in form.is_valid bcs i can see the print('form not valid')
any suggestion?
It might help to add the default value to the field definitions like so:
lat = models.DecimalField(
max_digits=19,
decimal_places=16,
blank=True,
null=True,
default=None
)
lng = models.DecimalField(
max_digits=19,
decimal_places=16,
blank=True,
null=True,
default=None
)
Edit: If this doesn't help, please share the definition of CreatMeetingForm.

Django API Testing : csrf exempt

I'm getting a "Forbidden (CSRF cookie not set.): /user/admin/sign-up" error whenever I test class based views. When I change those views to functional based views with #csrf_exempt on top of the function declaration, it works.
Postman POST Request:
localhost:8000/admin/sign-up
body : {'email' : 'email#gmail.com', 'password' : 123123}
URL path patterns:
...
path(‘/admin/sign-up’, views.AdminSignUpView),
...
Views.py
#csrf_exempt
def token_verification(request,**kwargs):
if request.method == “POST”:
id = kwargs.get(‘id’)
token = kwargs.get(‘token’)
user = User.objects.get(id = id)
redirect_url = ‘/eval/intro’
is_valid = user_activation_token.check_token(user,token)
if is_valid:
user.is_active = True
user.save()
return HttpResponseRedirect(redirect_url,status = 200)
else:
return HttpResponse(status = 403)
class AdminSignInView(View):
#csrf_exempt
def post(self,request):
data = json.loads(request.body)
try:
if User.objects.filter(name = data[‘email’]).exists():
user = User.objects.get(name=data[‘email’])
if bcrypt.checkpw(data[‘password’].encode(‘utf-8’),user.password.encode(‘utf-8’)):
token = jwt.encode({‘email’:data[‘email’]}, SECRET, algorithm = HASH).decode(‘utf-8’)
return JsonResponse({ ‘token’ : token }, status = 200)
return JsonResponse({ ‘message’ : ‘INVALID_USER’ }, status = 401)
return JsonResponse({ ‘message’ : ‘INVALID_USER’ }, status = 401)
except KeyError:
return JsonResponse({ ‘message’ : ‘INVALID_KEYS’ }, status = 400)
class AdminSignUpView(View):
#csrf_exempt
def post(self,request):
try:
data = json.loads(request.body)
if not User.objects.filter(email = data[‘email’]).exists:
password = bcrypt.hashpw(data[‘password’].encode(‘utf-8’),bcrypt.gensalt())
crypted = password.decode(‘utf-8’)
User.objects.create(
name = data[‘name’],
password = bcrypt,
email = data[‘email’],
auth_id = data[‘auth_id’]
)
return HttpResponse(status = 200)
except KeyError:
return JsonResponse({ ‘message’ : ‘INVALID_KEYS’ },status = 4000)
Models.py
class User(models.Model):
name = models.CharField(max_length = 50)
email = models.EmailField(max_length = 200,unique = True, blank = False)
department = models.ForeignKey('Department', on_delete = models.SET_NULL, null = True)
is_active = models.BooleanField(default=False)
question = models.ManyToManyField('eval.Question',through='UserQuestion')
auth = models.ForeignKey('Auth', on_delete = models.SET_NULL, null = True)
class Meta:
db_table = 'users'
token_verification view, which is written in function based, works fine but the last two raised an error. I think the fact that the decorator only goes on top of the function brings up this error, but I'm not sure why #csrf_exempt is necessary for some views.
I have no clue why I'm getting the csrf issue at this time.
I believe the problem is where you're adding the #csrf_exempt.
Django perform the csrf validation before it reaches post
You should check your Django version flowchart to find which method you should override on your View to add the csrf_exempt decorator.
https://docs.djangoproject.com/en/2.2/ref/class-based-views/base/#django.views.generic.base.View.setup
https://docs.djangoproject.com/en/1.8/ref/class-based-views/base/#django.views.generic.base.View
I believe the code bellow should work for django versions < 2.2
#method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(AdminSignInView, self).dispatch(request, *args, **kwargs)

Categories