File : "Upload a valid image" using Postman in Django Rest Framework - django

I am using Django Rest Framework to upload profile picture and Google Cloud Storage to store my images. I test my API with Postman and i have this result :
Postman result
And here is my Postman headers : Postman headers
This is my code :
class ProfilePictureSerializer(serializers.Serializer):
file = serializers.ImageField()
class UploadProfilePictureAPI(APIView):
permission_classes = (IsAuthenticated,)
parser_classes = [FileUploadParser]
#staticmethod
def post(request):
input_serializer = serializers.ProfilePictureSerializer(
data=request.data
)
input_serializer.is_valid(raise_exception=True)
profile = ProfileService.upload_profile_picture(
request.user,
**input_serializer.validated_data
)
output_serializer = serializers.ProfileSerializer(profile)
return Response(
output_serializer.data,
status=status.HTTP_202_ACCEPTED
)
#staticmethod
def upload_profile_picture(user, file):
user.profile.profile_picture = file
user.profile.save()
return user.profile
path(
'upload/picture',
views.UploadProfilePictureAPI.as_view(),
name='api_upload_profile_picture'
),
I does not understand why I have this response. Could you help me ?

I think the issue here might be that FileUploadParser expects you to just send raw binary data (you can see the binary option in Postman).
In your current example, can you just try to send the binary data like so?
For multipart form you should use the MultiPartParser: https://www.django-rest-framework.org/api-guide/parsers/#multipartparser

Related

Can't Get Image from Django Api To React Native

Hello Friends I Can't Get Image From Django To React Native
Here My Code
Fetch APi
const [add, setStudents] = useState([{}])
async function getAllStudent() {
try {
const add = await axios.get('http://192.168.1.77:19000/api/add/')
method:'GET',
setStudents(add.data)
}
catch (error) {
console.log(error)
}
}
getAllStudent();
FlatList :
<FlatList
data={add}
renderItem={({item})=>
<Image
style={{width:200,height:200, backgroundColor:'green',}}
source={{uri:item.image}}
/>
}
/>
Django Code Is Here
Views
class addpost(viewsets.ViewSet):
def list(self,request):
postadd1 = postadd.objects.all()
postaddserial1 = postaddserial(postadd1,many=True)
return Response(postaddserial1.data)
def create(self,request):
postaddserial1 = postaddserial(data=request.data)
if postaddserial1.is_valid():
postaddserial1.save()
return Response(postaddserial1.data, status=status.HTTP_201_CREATED)
return Response(postaddserial1.errors, status=status.HTTP_400_BAD_REQUEST )
def retrieve(self,request,pk=None):
queryset = postadd.objects.all()
contact = get_object_or_404(queryset,pk=pk)
postaddserial1 = postaddserial(contact)
return Response(postaddserial1.data)
def update(self,request,pk=None):
contact = postadd.objects.get(pk=pk)
postaddserial1 = postaddserial(contact,data=request.data)
if postaddserial1.is_valid():
postaddserial1.save()
return Response(postaddserial1.data,status=status.HTTP_201_CREATED)
return Response(postaddserial1.errors,status=status.HTTP_400_BAD_REQUEST)
def destroy(self, request, pk=None):
postadd1 = postadd.objects.get(pk=pk)
postadd1.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Serializer
class postaddserial(serializers.ModelSerializer):
class Meta:
model = postadd
fields ='__all__'
Model
class postadd(models.Model):
city=models.CharField(max_length=122)
carinfo=models.CharField(max_length=122)
milage=models.CharField(max_length=122)
price=models.CharField(max_length=122)
company=models.CharField(max_length=122)
image = models.ImageField(upload_to ='static/Images', height_field=None, width_field=None, max_length=100,)
engine=models.CharField(max_length=122)
contact=models.CharField(max_length=122)
I make django Api to add product in react native. i show image from post man . but cant get image in react native from api
i am making application where i can add product from django rest framework and show it on react native through api i get all data in react native but cant get image from api. when i use postman i get image from api but when i use api on react native i can't get image
You need to define media settings and absolute url for image or files.
For more helo you can see here
Django serializer Imagefield to get full URL

Dajngo CSV FIle not download ? When we have a large CSV file download its takes some time?Django 502 bad gateway nginx error Django

How can I download a large CSV file that shows me a 502 bad gateway error?
I get this solution I added in below.
Actually, in this, we use streaming references. In this concept for example we download a movie it's will download in the browser and show status when complete this will give the option to show in a folder same as that CSV file download completely this will show us.
There is one solution for resolving this error to increase nginx time but this is will affect cost so better way to use Django streaming. streaming is like an example when we add a movie for download it's downloading on the browser. This concept is used in Django streaming.
Write View for this in Django.
views.py
from django.http import StreamingHttpResponse
503_ERROR = 'something went wrong.'
DASHBOARD_URL = 'path'
def get_headers():
return ['field1', 'field2', 'field3']
def get_data(item):
return {
'field1': item.field1,
'field2': item.field2,
'field3': item.field3,
}
class CSVBuffer(object):
def write(self, value):
return value
class Streaming_CSV(generic.View):
model = Model_name
def get(self, request, *args, **kwargs):
try:
queryset = self.model.objects.filter(is_draft=False)
response = StreamingHttpResponse(streaming_content=(iter_items(queryset, CSVBuffer())), content_type='text/csv', )
file_name = 'Experience_data_%s' % (str(datetime.datetime.now()))
response['Content-Disposition'] = 'attachment;filename=%s.csv' % (file_name)
except Exception as e:
print(e)
messages.error(request, ERROR_503)
return redirect(DASHBOARD_URL)
return response
urls.py
path('streaming-csv/',views.Streaming_CSV.as_view(),name = 'streaming-csv')
For reference use the below links.
https://docs.djangoproject.com/en/4.0/howto/outputting-csv/#streaming-large-csv-files
GIT.
https://gist.github.com/niuware/ba19bbc0169039e89326e1599dba3a87
GIT
Adding rows manually to StreamingHttpResponse (Django)

Headers content included in file uploaded in django rest framework

I'm having an issue in my django api file upload.
When I upload file using FileUploadParser everything goes well
but the file upload contains the header of the request stuff like Content-Disposition
when i try to open the uploaded file it is broken. I searched for a while for some solution but no chance. Decided to use MultiPartparser but this way nothing is included in the request.data dict. How can I go around this ? Can somebody show me a code or a way to successfully upload file or image to my api without having them broken ? Thanks for any hint.
Here's the code I have so far
class EstablishmentMediaUploadView(views.APIView):
permission_classes = (IsAuthenticated,)
authentication_class = JSONWebTokenAuthentication
parser_classes = (FileUploadParser,)
serializer_class = MediaSerializer
name = 'establishment-media-file-upload'
def put(self, request, **kwargs):
print(request.data)
if 'file' not in request.data:
raise ParseError("Empty media file for establishment")
establishmentid = kwargs.get('establishmentid')
if establishmentid is None:
return Response({"error": "You didn't specify the establishmentid"}, status=400)
mediaFile = request.data.get('file')
media = Media.objects.create(mediatitle=mediaFile.name)
establishment = Establishment.objects.get(id=establishmentid)
media.establishmentlogo.save(mediaFile.name, mediaFile, save=False)
media.establishment = establishment
media.save()
return Response({"message": "Logo added for this establishment"}, status=200)
I first test it by uploading from Insomnia api test client and Vscode thunder client extension. For both the headers are included.
Then I did the test in my angular frontend. Here's the code of the service method in charge of the upload :
setEstablishmentLogo(establishment: Establishment, media: Media): Observable<Object> {
let formdata = new FormData();
formdata.set("establishmentlogo", media.establishmentlogo);
var url = `${endpoints.establishment_media_upload_uri_base}/${establishment.id}`;
console.log(url)
return this.http.put(url, formdata, {
headers: {
"Accept": "*/*",
"Content-Disposition": `attachment; filename=${media.establishmentlogo.name}`,
'Authorization': `Bearer ${token}`
}
});
}
Got the same behavior. Perhaps I'm getting something wrong in all this. But can't figure it out.
Well i use flutter framework and i upload images from mobile to django and guess what, it updates image field without doing anything from my end. Just make sure where ever you are uploading this image from do it accordingly to http library in that framework.
So just to avoid this headache to another folk. Here is what I found finally.
I was using FileUploadParser in my uploadview. But the point is that when using the 'FileUploadParser' the request.data dict
is populated with the uploaded content. The uploaded content in that case, when it comes from clients like Postman
or Insomnia or Thunder Client of vscode, it contains the single file you uploaded (We assume that you select the option binary request
in those clients) and that way, nothing wrong happens, the files are safe. But when you upload files from the browser, let's say from angular and the parser_class in the view is set to FileUploadParser
then you will successfully upload the file but it would be broken because the whole request (file + headers and browser boundaries stuffs) is parsed as a single file
by FileUploadParser(It's indeed it's job) and thus you end up with broken files on your server or backend. So the way to go around that is to set parser_classes to MultipartParser and FormParser optionally
That way your uploaded files are fine. And much, you don't need to specify Content-Disposition: attachment; filename='some file name' in your request header. Bear in mind that when you use FileUploadParser, your file is in request.data['file'] and when it is MultiPartParser (and FormParser) the file is in request.FILES['file'].
With all this said, the working version of the upload view I posted in my question looks like below :
class EstablishmentMediaUploadView(views.APIView):
permission_classes = (IsAuthenticated,)
authentication_class = JSONWebTokenAuthentication
parser_classes = (MultiPartParser, FormParser,)
name = 'mtp-establishment-media-file-upload'
def post(self, request, *args, **kwargs):
if 'file' not in request.FILES:
return Response({"message": "Please provide a file"}, status=status.HTTP_400_BAD_REQUEST)
establishmentid = kwargs.get('establishmentid')
if establishmentid is None:
return Response({"error": "You didn't specify the establishmentid"}, status=status.HTTP_400_BAD_REQUEST)
mediaFile = request.FILES['file']
media = Media.objects.create(mediatitle=mediaFile.name)
media.establishmentlogo.save(mediaFile.name, mediaFile, save=True)
try:
establishment = Establishment.objects.get(id=establishmentid)
except Establishment.DoesNotExist:
return Response({"error": "Establishment does not exist"}, status=status.HTTP_404_NOT_FOUND)
media.establishment = establishment
media.save()
return Response({"message": "Logo added for this establishment"}, status=status.HTTP_201_CREATED)

How to force download an image on click with django and aws s3

I have this view, which takes a user_id and image_id. When the user cliks the link, check if there is an image. If there is, then I would like the file to force download automatically.
template:
<a class="downloadBtn" :href="website + '/download-image/'+ user_id+'/'+ image_id +'/'">Download</a>
Before I was developing it in my local machine, and this code was working.
#api_view(['GET'])
#permission_classes([AllowAny])
def download_image(request, user_id=None, image_id=None):
try:
ui = UserImage.objects.get(user=user_id, image=image_id)
content_type = mimetypes.guess_type(ui.image.url)
wrapper = FileWrapper(open(str(ui.image.file)))
response = HttpResponse(wrapper, content_type=content_type)
response['Content-Disposition'] = 'attachment; filename="image.jpeg'
return response
except UserImage.DoesNotExist:
...
But now I am using aws s3 for my static and media files. I am using django-storages and boto3. How can I force download the image in the browser?
#api_view(['GET'])
#permission_classes([AllowAny])
def download_image(request, user_id=None, image_id=None):
try:
ui = UserImage.objects.get(user=user_id, image=image_id)
url = ui.image.url
...
... FORCE DOWNLOAD THE IMAGE
...
except UserImage.DoesNotExist:
...
... ERROR, NO IMAGE AVAILABLE
...
You can just return a HttpResponse with the image itself.
return HttpResponse(instance.image, content_type="image/jpeg")
This will return the image's byte stream. The Content-type header is to show the images in platforms like Postman.

Upload zip files to Google App Engine using Django

In a nutshell, we are trying to implement the following example from Google using Django:
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
class MainHandler(webapp2.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
self.response.out.write('<html><body>')
self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit"
name="submit" value="Submit"> </form></body></html>""")
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
blob_info = upload_files[0]
self.redirect('/serve/%s' % blob_info.key())
Our app is written in Django 1.x. We use urls.py, views.py and models.py to define our url scheme, views and data models respectively.
In our database, we need to keep track of the data file (or at least, a reference to where the file exists on disk). Currently, our data model is as follows:
class FileData(models.Model):
token = models.CharField(max_length=10)
file = models.FileField(upload_to=get_upload_file_name, null=True, default=None, blank=True)
The field 'token' contains a token that client apps will use to request the file for download. The field 'file' is intended to contain the data. However, if we need to make it a reference to a blob location, it won't be a problem. We just don't know what to do at this point. What is the right solution?
Our urls pattern is as follows:
urlpatterns = patterns('',
url(r'^upload/', 'views.upload', name='upload'),
url(r'^/serve/([^/]+)?', 'views.servehandler', name='servehandler'),
)
Our form is as follows.
class DataUploadForm(forms.Form):
"""
FileData form
"""
token = forms.CharField(max_length=10)
file = forms.FileField()
class Meta:
model = FileData
fields = ['token', 'file', ]
def __init__(self, *args, **kwargs):
super(DataUploadForm, self).__init__(*args, **kwargs)
self.helper = FormHelper()
self.helper.form_tag = False
self.helper.layout = Layout(
'token',
'file',
ButtonHolder(
Submit('submit', 'Submit', css_class='btn btn-success btn-block'),
),
)
Our view is as follows.
def upload(request):
args = {}
args.update(csrf(request))
if request.method == 'POST':
print "In /upload"
form = DataUploadForm(request.POST, request.FILES)
if form.is_valid():
file_data = FileData()
file_data.token = request.POST.get('token')
file_data.file = request.FILES.get('file')
print "===========> Uploading:" + file_data.token
file_data.save()
return render(request, 'upload_success.html', args)
form = DataUploadForm()
args['form'] = form
return render(request, 'upload.html', args)
When we execute, we get:
Exception Value:
[Errno 30] Read-only file system: u
What are we doing wrong? How can we improve our code? How do we get Google App Engine to save our file, perhaps in the blobstore, and give us the reference to where the file exists for use in downloading it later?
Please be complete. Describe changes needed for urls.py, models.Model, views.py and yaml files (if necessary). Address how to upload large files (i.e., files greater than 40 MB each).
Please don't send us any more links. We have searched and seen a lot of postings-- none of which answers this question. If you can, please post a code snippets that answer the question -- not links.
The reason you have this Read-only file system error is that the default models.FileField save uploaded file to the MEDIA_ROOT folder and it's read-only for Google Appengine apps.
You have to use a third party FileField to save the uploaded files to services like Google Cloud Storage or Amazon S3.
I did a quick search and found:
https://github.com/viadanna/django-gcsengine
https://django-storages.readthedocs.org
And for the upload file size limit issue, Google Appengine has a size limit for request which is 32M. To support larger files, you have to make the user upload their files directly to BlobStore or Google Cloud Storage and build a callback handler to link the uploaded file with your model.
Check these links:
https://cloud.google.com/appengine/docs/python/blobstore/
Upload images/video to google cloud storage using Google App Engine