I have used djangorest to create an api but when i make a post request it returns an error saying 400 BAD request - reactjs

model :
class Post(models.Model):
author = models.ForeignKey(get_user_model(), related_name="posts", on_delete=models.CASCADE, unique=False)
title = models.CharField(max_length=300)
text = models.TextField(blank=True)
creationDate = models.DateTimeField(default=timezone.now())
publicationDate = models.DateTimeField(blank=True, null=True)
def publish(self):
self.publicationDate = timezone.now()
self.save()
def __str__(self):
return self.title
this is the serializer :
class PostSerializer(serializers.ModelSerializer):
def create(self, validated_data):
post = Post.objects.create(
author=validated_data["author"], title=validated_data["title"], text=validated_data["text"]
)
post.save()
return post
class Meta:
model = Post
fields = ["author", "title", "text", "pk", 'publicationDate']
this is the api view :
class PostList(GenericAPIView, ListModelMixin, CreateModelMixin):
queryset = Post.objects.all()
serializer_class = PostSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
and this is the request I`m making :
axios.post('/api/posts/', form, {
"headers": {
'Content-Type': 'application/json',
}
})
.then(response => console.log(response.data))
this is the error it returns
"POST http://127.0.0.1:8000/api/posts/ 400 (Bad Request)"
I have been at this problem for days now and i have tried everything but it just wont work

Related

Model field not updating in save()

In my Django MyModel I've created a new field last_status_change (a timestamp). Should be updated when that status changes.
However, even when a print shows that last_status_change is computed correctly, it doesn't get saved.
Is any field modification prohibited within save? What's the reason behind it? How to work around it?
class MyModel(models.Model):
first_name = models.CharField(max_length=100, verbose_name='Name')
confirmation_status = models.CharField(
choices=CONFIRMATION_STATUS_CHOICES,
default='registered', max_length=20
)
last_status_change = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
if self.pk:
original = MyModel.objects.get(pk=self.pk)
if original.confirmation_status != self.confirmation_status:
last_status_change = datetime.now()
return super(MyModel, self).save(*args, **kwargs)
You need to assign it to the self object, so:
from django.utils import timezone
class MyModel(models.Model):
first_name = models.CharField(max_length=100, verbose_name='Name')
confirmation_status = models.CharField(
choices=CONFIRMATION_STATUS_CHOICES, default='registered', max_length=20
)
last_status_change = models.DateTimeField(null=True, blank=True)
def save(self, *args, **kwargs):
if self.pk:
original = MyModel.objects.get(pk=self.pk)
if original.confirmation_status != self.confirmation_status:
self.last_status_change = timezone.now()
return super().save(*args, **kwargs)

How to insert data and update data in One to One Relation in DRF and React Js

I have two models User and Profile which is related by One to One relation. I have registered users who can login and if profile is not created for user, then user can create one profile (using POST) and if profile is created then user can update their profile (using PATCH).
Models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True, related_name='profile')
locality = models.CharField(max_length=70, null=True, blank=True)
city = models.CharField(max_length=70, null=True, blank=True)
address = models.TextField(max_length=300, null=True, blank=True)
pin = models.IntegerField(null=True, blank=True)
state = models.CharField(max_length=70, null=True, blank=True)
profile_image = models.ImageField(upload_to='user_profile_image', blank=True, null=True)
Serializer.py
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model= Profile
fields = ['user', 'locality','city','address','pin','state','profile_image']
Views.py
class UserProfileDataView(APIView):
renderer_classes = [UserRenderer]
permission_classes = [IsAuthenticated]
def get(self, request, format=None):
serializer = ProfileSerializer(request.user.profile, context={'request': request})
return Response(serializer.data, status=status.HTTP_200_OK)
def post(self, request, format=None):
serializer = ProfileSerializer(data= request.data, context={'user': request.user})
serializer.is_valid(raise_exception=True)
serializer.save()
return Response ({ 'msg':'Data Updated Successfully'},status=status.HTTP_201_CREATED
)
def patch(self, request, format=None):
item = Profile.objects.get(user = request.user)
serializer = ProfileSerializer(item ,data = request.data, partial=True, context={'user': request.user.profile})
serializer.is_valid(raise_exception=True)
serializer.save()
return Response({'msg':'Profile Updated Successfull'}, status = status.HTTP_200_OK)
API using Redux Toolkit
editProfile: builder.mutation({
query: (access_token, actualData ) => {
return {
url:'editprofile/',
method:'PATCH',
body:actualData,
headers:{'authorization' : `Bearer ${access_token}`, 'Content-type':'application/json'}
}
}
}),
createProfile: builder.mutation({
query: (access_token, actualData ) => {
return {
url:'createprofile/',
method:'POST',
body:actualData,
headers:{'authorization' : `Bearer ${access_token}`, 'Content-type':'application/json'}
}
}
}),
})
})
When I create profile from django admin for a user and tries to update its data, then I only get {"msg": "Profile Updated Successfull"} in network console but data is not reflected in database. and also when I try to create profile of user from Fronend using React, it gives error msg {"errors": {"user": ["This field is required."]}}
I think you missed setting the user_id field in the request payload. In the ProfileSerializer, you need to change the user field into user_id.
class ProfileSerializer(serializers.ModelSerializer):
class Meta:
model= Profile
fields = ['user_id', 'locality','city','address','pin','state','profile_image']
extra_kwargs = {
'user_id': {'source': 'user'}
}
And in the frontend, you need to set the user_id attribute in the actual_data object.
Or in the backend, you can add that field manually in the post method of the UserProfileDataView class.
class UserProfileDataView(APIView):
...
def post(self, request, format=None):
input_data = request.data
input_data['user_id'] = request.user.id
serializer = ProfileSerializer(data= input_data, context={'user': request.user})
serializer.is_valid(raise_exception=True)
serializer.save()
return Response ({ 'msg':'Data Updated Successfully'},status=status.HTTP_201_CREATED
)

How do i call a primary key from another view in another form in django?

I have a stocks model that relies on GRN (Goods Receiving Note) model primary key in order to store stocks of a certain GRN in the database. I would like to humbly ask for guidance on how i can click a GRN and enter stocks in a form with the open GRN No already selected in this form.
Below are my views:
def grns(request):
grns = GRN.objects.all()
return render (request, 'products/GRNS.html', {'grns' : grns})
def grn(request, pk):
gnrObj = GRN.objects.get(GRN_id = pk)
return render(request, 'products/stocks_in.html', {'grn': gnrObj})
def createGrn(request):
form = GrnForm()
if request.method == 'POST':
form = GrnForm(request.POST)
if form.is_valid():
form.save()
return redirect('grns')
context = {'form': form}
return render (request, 'products/grn_form.html', context)
def stocks(request):
stocks = Stock.objects.all()
return render (request, 'products/stocks_in.html', {'stocks' : stocks})
def stock(request, pk):
stockObj = stock.objects.get(GRN_id = pk)
return render(request, 'products/stocks_in_form.html', {'stock': stockObj})
def createStock(request):
form = StockForm()
if request.method == 'POST':
form = StockForm(request.POST)
if form.is_valid():
form.save()
return redirect('stocks')
context = {'form': form}
return render (request, 'products/stocks_in_form.html', context)
Below are my urls:
#GRNS Urls
path('grns', views.grns, name = "grns"),
path('create-grn/', views.createGrn, name = "create-grn"),
path('grn/<str:pk>/', views.grn, name = "grn"),
#Stocks Urls
path('stocks', views.stocks, name = "stocks"),
path('create-stock/', views.createStock, name = "create-stock"),
path('stock/<str:pk>/', views.stock, name = "stock"),
Below are my forms:
class GrnForm(ModelForm):
class Meta:
model = GRN
fields = ['GRN_no', 'date', 'supplier']
def __init__(self, *args, **kwargs):
super(GrnForm, self).__init__(*args, **kwargs)
self.fields['GRN_no'].widget.attrs.update(
{'class': 'form-control'}
)
self.fields['date'].widget.attrs.update(
{'class': 'form-control', 'type': 'date'}
)
self.fields['supplier'].widget.attrs.update(
{'class': 'form-control'}
)
class StockForm(ModelForm):
class Meta:
model = Stock
fields = ['GRN', 'product', 'warehouse', 'unit_price', 'quantity']
def __init__(self, *args, **kwargs):
super(StockForm, self).__init__(*args, **kwargs)
self.fields['GRN'].widget.attrs.update(
{'class': 'form-control', 'value':'grn.GRN_id'}
)
self.fields['product'].widget.attrs.update(
{'class': 'form-control'}
)
self.fields['warehouse'].widget.attrs.update(
{'class': 'form-control'}
)
self.fields['unit_price'].widget.attrs.update(
{'class': 'form-control'}
)
self.fields['quantity'].widget.attrs.update(
{'class': 'form-control'}
)

Error: Invalid data. Expected a dictionary, but got InMemoryUploadedFile

I am getting the above error when trying to upload multiple pictures from react to django rest api.
This is my django view code:
def post(self, request, *args, **kwargs):
posts_serializer = PostSerializer(data=request.FILES.getlist('image[]'), many=True)
print(posts_serializer)
if posts_serializer.is_valid():
posts_serializer.save()
return Response(posts_serializer.data, status=status.HTTP_201_CREATED)
else:
print('error', posts_serializer.errors)
return Response(posts_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
This is a print from posts_serializer:
PostSerializer(data=[<InMemoryUploadedFile: 1PSM Logo.png (image/png)>, <InMemoryUploadedFile: Microsoft-Azure-Fundamentals.png (image/png)>, <InMemoryUploadedFile: DP-900_ProductImage-1.png (image/png)>], many=True):
id = IntegerField(label='ID', read_only=True)
image = ImageField(max_length=100)
Appreciate any help.
So I finally made it work by using a different way:
def post(self, request, *args, **kwargs):
if request.method == "POST":
allimages = request.FILES.getlist('images')
for oneimage in allimages:
Post.objects.create(images=oneimage)
return Response(status=status.HTTP_201_CREATED)
return Response(status=status.HTTP_400_BAD_REQUEST)
class Post(models.Model):
images = models.FileField(upload_to='post_images', default='')

How to make use of filter using ContentType to check if model instance is already present or not

I am trying to implement like functionality based on this . I want to restrict user to hit like on a event only once. But I am getting the following error. I have added full error details at bottom
Exception Type: AttributeError at /api/event/likes/create/
Exception Value: 'str' object has no attribute '_meta'
models.py
class ThumbsUpManager(models.Manager):
def create_by_model_type(self, model_type, slug, content, user, parent_obj=None):
model_qs = ContentType.objects.filter(model=model_type)
if model_qs.exists():
some_model = model_qs.first().model_class()
obj_qs = some_model.objects.filter(slug=slug)
if obj_qs.exists() and obj_qs.count() == 1:
instance = self.model()
instance.content = content
instance.user = user
instance.content_type = model_qs.first()
instance.object_id = obj_qs.first().id
if parent_obj:
instance.parent = parent_obj
instance.save()
return instance
return None
class Thumbsup(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE)
content = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
approved = models.BooleanField(default=True)
objects = ThumbsUpManager()
class Meta:
ordering = ['-timestamp']
def __str__(self):
return str(self.user.username)
#property
def is_parent(self):
if self.parent is not None:
return False
return True
urls.py
urlpatterns = [
path('create/', ThumbsUpCreateAPIView.as_view(), name='create'),
]
view.py
class ThumbsUpCreateAPIView(CreateAPIView):
queryset = Thumbsup.objects.all()
permission_classes = [IsAuthenticated, ]
def get_serializer_class(self):
model_type = self.request.GET.get("type")
slug = self.request.GET.get("slug")
obj_qs = Thumbsup.objects.all()
print(obj_qs)
parent_id = self.request.GET.get("parent_id", None)
return create_thumbs_up_serializer(
model_type=model_type,
slug=slug,
parent_id=parent_id,
user=self.request.user
)
serializers.py
def create_thumbs_up_serializer(model_type=None, slug=None, parent_id=None, user=None):
class ThumbsUpCreateSerializer(ModelSerializer):
class Meta:
model = Thumbsup
fields = [
'id',
'content',
'timestamp',
]
def __init__(self, *args, **kwargs):
self.model_type = model_type
self.slug = slug
self.parent_obj = None
self.user = user
if parent_id:
parent_qs = Thumbsup.objects.filter(id=parent_id)
if parent_qs.exists() and parent_qs.count() == 1:
self.parent_obj = parent_qs.first()
return super(ThumbsUpCreateSerializer, self).__init__(*args, **kwargs)
def validate(self, data):
model_type = self.model_type
slug = self.slug
model_qs = ContentType.objects.filter(model=model_type)
if not model_qs.exists() or model_qs.count() != 1:
raise ValidationError("This is not a valid content type")
SomeModel = model_qs.first().model_class()
obj_qs = SomeModel.objects.filter(slug=self.slug)
if not obj_qs.exists() or obj_qs.count() != 1:
raise ValidationError("This is not a slug for this content type")
######################### ######################### #########################
How do I need to make query here to check if the user already liked the Event or not?
I tried the following way, but it is not working.
user_act = Thumbsup.objects.filter(user=self.user, content_type=ContentType.objects.get_for_model(model_type))
if user_act.exists():
raise ValidationError("You have already liked the event")
return data
def create(self, validated_data):
content = validated_data.get("content")
if user:
main_user = user
else:
main_user = User.objects.all().first()
model_type = self.model_type
slug = self.slug
parent_obj = self.parent_obj
thumbsup = Thumbsup.objects.create_by_model_type(
model_type, slug, content, main_user,
parent_obj=parent_obj,
)
return thumbsup
return ThumbsUpCreateSerializer
Traceback:
File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\exception.py" in inner
34. response = get_response(request)
File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
115. response = self.process_exception_by_middleware(e, request)
File "E:\GIT\blog\backend\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
113. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "E:\GIT\blog\backend\venv\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
54. return view_func(*args, **kwargs)
File "E:\GIT\blog\backend\venv\lib\site-packages\django\views\generic\base.py" in view
71. return self.dispatch(request, *args, **kwargs)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in dispatch
497. response = self.handle_exception(exc)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in handle_exception
457. self.raise_uncaught_exception(exc)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in raise_uncaught_exception
468. raise exc
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\views.py" in dispatch
494. response = handler(request, *args, **kwargs)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\generics.py" in post
190. return self.create(request, *args, **kwargs)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\mixins.py" in create
18. serializer.is_valid(raise_exception=True)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\serializers.py" in is_valid
235. self._validated_data = self.run_validation(self.initial_data)
File "E:\GIT\blog\backend\venv\lib\site-packages\rest_framework\serializers.py" in run_validation
433. value = self.validate(value)
File "E:\GIT\test-heroku4\thumbsup\api\serializers.py" in validate
124. user_act = Thumbsup.objects.filter(user=self.user, content_type=ContentType.objects.get_for_model(model_type))
File "E:\GIT\blog\backend\venv\lib\site-packages\django\contrib\contenttypes\models.py" in get_for_model
40. opts = self._get_opts(model, for_concrete_model)
File "E:\GIT\blog\backend\venv\lib\site-packages\django\contrib\contenttypes\models.py" in _get_opts
27. model = model._meta.concrete_model
Exception Type: AttributeError at /api/event/likes/create/
Exception Value: 'str' object has no attribute '_meta'
I checked the model instance before saving in model manager like below and it is working fine. I do not know whether this is the correct way to do the task or not (I'm very new to django. Suggestions are most welcome)
def create_by_model_type(self, model_type, slug, content, user, parent_obj=None):
model_qs = ContentType.objects.filter(model=model_type)
if model_qs.exists():
some_model = model_qs.first().model_class()
obj_qs = some_model.objects.filter(slug=slug)
if obj_qs.exists() and obj_qs.count() == 1:
instance = self.model()
instance.content = content
instance.user = user
instance.content_type = model_qs.first()
instance.object_id = obj_qs.first().id
if parent_obj:
instance.parent = parent_obj
#### Here I have checked for existence before saving the instance ####
if Thumbsup.objects.filter(object_id=instance.object_id, user=instance.user).exists():
raise ValidationError({'already_liked': 'You have already liked the item'})
instance.save()
return instance
return None

Resources