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='')
Related
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
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)
I am building a Django+DRF/React app (simple blog app) and i am facing difficulties saving nested images
Model Structure
Model:
Post
Children:
details: ContentType Model ( DRF: save is successfull )
images: ContentType Model ( DRF : save is not successfull )
Process
Send images from <input type="file" multiple />
Process data through FormData
Catch request.data and process it
class PostFormView(generics.RetrieveUpdateDestroyAPIView):
queryset = Post._objects.is_active()
serializer_class = PostModelSerializer
permission_classes = (IsOwnerOr401,)
parser_classes = (parsers.MultiPartParser,parsers.JSONParser,
parsers.FormParser, parsers.FileUploadParser)
lookup_field = 'slug'
lookup_url_kwarg = 'slug'
def get_queryset(self):
return super().get_queryset().annotate(**sharedAnnotations(request=self.request))
def update(self, request, *args, **kwargs):
data = request.data
_images = data.getlist('images')
images = []
for _ in _images:
if isinstance(_, dict):
images.append(images)
continue
images.append({'image': _, 'object_id': self.get_object().pk, 'content_type': self.get_object().get_content_type().pk})
data['images'] = images
print(data)
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer)
if getattr(instance, '_prefetched_objects_cache', None):
instance._prefetched_objects_cache = {}
return Response(serializer.data)
Save images (FAIL):
class MediaModelSerializer(ContentTypeModelSerializer):
# inherits object_id & content_type fields just to avoid writing them over and over alongside (create & update fns)
class Meta:
model = Media
fields='__all__'
class PostModelSerializer(WritableNestedModelSerializer):
is_active = serializers.BooleanField(default=True)
path = serializers.HyperlinkedIdentityField(
view_name="api:post-detail", lookup_field='slug')
images = MediaModelSerializer(many=True)
details = DetailModelSerializer(required=False, many=True)
# annotated fields
is_author = serializers.BooleanField(read_only=True, default=False)
class Meta:
model = Post
fields = '__all__'
read_only_fields = ['is_locked', 'slug', 'user', 'is_author']
def create(self, validated_data):
return super().create(validated_data)
def update(self, instance, validated_data):
return super().update(instance, validated_data)
The print(data) statement from PostFormView.update(self, request, *args, **kwargs) (after manipulation) returns this:
<QueryDict: {'id': ['8'], ..., 'images': [[{'image': <InMemoryUploadedFile: bmw_3.jpeg (image/jpeg)>, 'object_id': 8, 'content_type': 20}, {'image': <InMemoryUploadedFile: bmw_2.jpeg (image/jpeg)>, 'object_id': 8, 'content_type': 20}, {'image': <InMemoryUploadedFile: bmw_1.jpeg (image/jpeg)>, 'object_id': 8, 'content_type': 20}]]}>
Server returns 400_BAD_REQUEST because images were not passed to PostModelSerializer
{"images":["This field is required."]}
i've been facing this issue for 3 days and i can't wrap my head around the root cause.
Thank you for your help.
i have been looking all over the internet but i could not find any anwsers so i had to go this way
I have removed the processing part from PostFormView.update(...) and accessed the images directly in the create & update methods of the ModelSerializer. I'll figure out later on how to handle removing these images
Here's the code:
class PostModelSerializer(WritableNestedModelSerializer):
is_active = serializers.BooleanField(default=True)
path = serializers.HyperlinkedIdentityField(
view_name="api:post-detail", lookup_field='slug')
images = MediaModelSerializer(read_only=True, many=True)
details = DetailModelSerializer(required=False, many=True)
# annotated fields
is_author = serializers.BooleanField(read_only=True, default=False)
class Meta:
model = Post
fields = '__all__'
read_only_fields = ['is_locked', 'slug', 'user', 'is_author']
def create(self, validated_data):
instance = super().create(validated_data)
request = self.context.get('request', None)
if request:
try:
images = request.data.getlist('images')
for image in images:
self.instance.images.create(image=image)
except Exception as e:
pass
return instance
def update(self, instance, validated_data):
instance = super().update(instance, validated_data)
request = self.context.get('request', None)
if request:
try:
images = request.data.getlist('images')
for image in images:
self.instance.images.create(image=image)
except Exception as e:
pass
return instance
If anyone has faced this issue before and managed to resolve it, please post your answer below.
Thank you !
I trying to update a instance model if it exists using serializer, but I got error
any ideas?
views.py
def sensor(request):
if request.method == 'POST':
data = JSONParser().parse(request)
sensor = Sensor.objects.filter(name=data['name'])
if sensor.exists():
serializer = SensorDetailSerializer(instance=sensor, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
else:
return JsonResponse(serializer.errors, status=400)
else:
serializer = SensorDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
else:
return JsonResponse(serializer.errors, status=400)```
AttributeError: 'QuerySet' object has no attribute '_meta'
[12/Apr/2020 13:13:19] "POST /sensor/ HTTP/1.1" 500 87980
You're passing a queryset instead of an actual instance to your serializer (hence the error you're getting AttributeError: 'QuerySet' object has no attribute '_meta').
You could update your code to do something similar to this:
def sensor(request):
if request.method == 'POST':
data = JSONParser().parse(request)
# Fetches the first result of Sensor with name data['name']
sensor = Sensor.objects.filter(name=data['name']).first()
if sensor:
serializer = SensorDetailSerializer(instance=sensor, data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
else:
return JsonResponse(serializer.errors, status=400)
else:
serializer = SensorDetailSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
else:
return JsonResponse(serializer.errors, status=400)
I have this code:
def handler_method():
users = UserModel.query(UsersModel.email == users.get_current_user().email()).fetch()
if len(users) == 0:
user = UsersModel(email = users.get_current_user().email())
user.put()
class MyHandler(webapp2.RequestHandler):
#login_required
def get(self):
.
.
my code
.
.
How can I specify to the #login_required decorator the method "handler_method" as the action to perform once the Login success ?
Looking at the code for the decorator:
def login_required(handler_method):
"""..."""
def check_login(self, *args):
if self.request.method != 'GET':
raise webapp.Error('The check_login decorator can only be used for GET '
'requests')
user = users.get_current_user()
if not user:
self.redirect(users.create_login_url(self.request.uri))
return
else:
handler_method(self, *args)
return check_login
there isn't a way to run additional code if the user is logged in successfully.
You could write a custom version of the decorator that would do what you want:
def custom_login_required(handler_method):
"""..."""
def check_login(self, *args):
if self.request.method != 'GET':
raise webapp.Error('The check_login decorator can only be used for GET '
'requests')
user = users.get_current_user()
if not user:
self.redirect(users.create_login_url(self.request.uri))
return
else:
users = UserModel.query(UsersModel.email == users.get_current_user().email()).fetch()
if len(users) == 0:
user = UsersModel(email = users.get_current_user().email())
user.put()
handler_method(self, *args)
return check_login
You should use the users.get_current_user() to identify whether user is logged-in:
from google.appengine.api import users
class MyHandler(webapp2.RequestHandler):
#login_required
def get(self):
if users.get_current_user():
handler_method()
else:
#user not login, redirect or return 404
pass