How to parse request.body for multipart file in django - django

I have used below code to post data to url
public void updateLogo(String clientKey, MultipartFile file) {
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("file", file.getResource());
Settings prevData = repo.findFirstByClientKey(clientKey);
WebClient webClient = WebClient.builder().baseUrl("http://localhost/")
.defaultHeader(HttpHeaders.AUTHORIZATION, String.format("Token %s", userToken)).build();
Mono<SettingsLogo> resObj = webClient.post().uri("api/upload-logo")
.contentType(MediaType.MULTIPART_FORM_DATA).body(BodyInserters.fromMultipartData(builder.build()))
.retrieve().bodyToMono(SettingsLogo.class)
.onErrorResume(WebClientResponseException.class, ex -> {
logger.error("Exception", ex);
return Mono.empty();
});
}
On Django post function
class UpdateJiraAppLogo(APIView):
def post(self, request, *args, **kwargs):
print('POST', request.POST)
print('BODY', request.body)
print('FILES', request.FILES)
logo = request.body
now = timezone.now()
logo_name = "logo_" + str(now.strftime('%d_%m_%Y') + "_" + now.strftime('%H%M%S')) + ".png"
try:
with open("media/logos/" + logo_name, "wb+") as f:
f.write(logo)
f.close()
except Exception as e:
print(e)
Following is printed
POST <QueryDict: {}>
BODY b'--3oqd3VUazPhxbazUKCTiNsp2MeoS9RgQqbQLnj7X\r\nContent-Disposition: form-data; name="file"; filename="clock.png"\r\nContent-Type: image/png\r\nContent-Length: 1959\r\n\r\n\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00x\x00\x00\x00x\x08\x03\x00\x00\x00\x0e\xba\xc6\xe0\x00\x00\x00\x04gAMA\x00\x00\xb1\x8f\x0b\xfca\x05\x00\x00\x00 cHRM\x00\x00z&\x00\x00\x80\x84\x00\x00\xfa\x00\x00\x00\x80\xe8\x00\x00u0\x00\x00\xea`\x00\x00:\x98\x00\x00\x17p\x9c\xbaQ<\x00\x00\x01\xefPLTE\x00\x00\x00\xe399\xde11\xde33\xdc33\xdd44\xdd33\xdd33\xdd33\xdd33\xdd33\xde44\xdf##\xff\x00\x00\xdb55\xdc33\xdd33\xdd33\xdd33\xdd44\xde44\xdb11\xde77\xdc22\xde44\xdd33\xdd22\xde22\xdc..\xdb$$\xde22\xdd33\xdd33\xdd33\xdd22\xdc44\xe633\xdf33\xdc33\xdd33\xde44\xdd55\xdd33\xdd33\xdd33\xdd55\xdc33\xde33\xdc44\xdd33\xdb11\xe399\xde33\xdd33\xdc22\xdb11\xdd33\xdd33\xff\x00\x00\xde11\xdd22\xdd33\xdd33\xdd33\xdd33\xde44\xbf##\xdd44\xd5++\xdc55\xdd33\xdb77\xe022\xdd33\xdc33\xdd33\xde44\xdd33\xdd44\xdd33\xdd33\xdc44\xdd33\xdd33\xdd33\xde33\xdd33\xcc33\\x00\x00\x00%tEXtdate:create\x002019-06-02T16:58:33+00:00.c\xfc\x1c\x00\x00\x00%tEXtdate:modify\x002019-06-02T16:58:33+00:00_>D\xa0\x00\x00\x00\x00IEND\xaeB`\x82\r\n--3oqd3VUazPhxbazUKCTiNsp2MeoS9RgQqbQLnj7X--\r\n'
FILES <MultiValueDict: {}>
the file is saved but it is corrupted. How to save file when file is received in request.body rather than FILES or POST?

Related

Django UnitTesting: 'AnonymousUser' object has no attribute

I have the following code:
class CampaignModelTests(TestCase):
# https://docs.djangoproject.com/en/4.1/topics/testing/advanced/
def setUp(self):
# create some test campaigns
shop = Shop.objects.create(name='Test Shop')
self.factory = RequestFactory()
self.user = User.objects.create(shop_username='testuser', shop=shop)
self.merchant = User.objects.create(username='merchant', password='merchant123', is_merchant=True, shop=shop)
self.campaign = Campaign.objects.create(name='Test Campaign', shop=shop)
def test_campaign_creation(self):
request = self.factory.get(reverse('create-campaign'), {
'name': 'Test Campaign -1',
'shop': Shop(name='Test Shop').sid
})
request.user = self.merchant
print('request.user: ', request.user.is_merchant)
response = CampaignCreate.as_view()(request)
self.assertEqual(response.status_code, 200)
And I am getting the following error:
return request.user.is_merchant or request.user.is_superuser
AttributeError: 'AnonymousUser' object has no attribute 'is_merchant'
I have tried using self.client as well but still the same error.
self.client.force_login(self.merchant)
# send a request to the view
response = self.client.post(reverse('create-campaign'), {
'name': 'Test Campaign -1',
'shop': Shop(name='Test Shop').sid
})
self.assertEqual(response.status_code, 200)

Django CBV : Download PDF document from media

I would like to download pdf file in my view but I don't overcome to display browser window which let to download my file.
The downloadPDF function seems to work well but nothing appears on my browser.
This is my class :
class TokenDownloadView(TemplateView):
template_name = 'app/token.html'
def get_context_data(self, **kwargs):
now = timezone.now()
context = super().get_context_data(**kwargs)
context['token'] = self.kwargs['token']
token = context['token']
download = Download.objects.get(token__iexact=token)
upload_doc = Document.objects.get(id=download.pub_id).upload
if download and download.expiration_date > now:
print("token valide jusqu'à : " + str(download.expiration_date))
print("il est actuellement : " + str(now))
print(' ==> Token existe et valide <==')
messages.success(self.request, 'Vous allez télécharger le document')
self.downloadPDF(upload_doc)
if download and download.expiration_date < now:
print("token valide jusqu'à : " + str(download.expiration_date))
print("il est actuellement : " + str(now))
print('==> Token existe mais a expiré <==')
messages.error(self.request, 'Document non téléchargé : la session a expiré')
return context
def downloadPDF(self, upload_doc):
from django.core.files.storage import FileSystemStorage
from django.http import HttpResponse, HttpResponseNotFound
fs = FileSystemStorage()
filename = upload_doc
if fs.exists(filename):
with fs.open(filename) as pdf:
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="mypdf.pdf"'
return response
else:
return HttpResponseNotFound('The requested pdf was not found in our server.')
I miss something in my class which could let to download my pdf ?
EDIT :
I edited my class in order to convert get_context_data() to get() method. It seems to work but I would like to get your mind :
class TokenDownloadView(TemplateView):
template_name = 'app/token.html'
def get(self, request, *args, **kwargs):
now = timezone.now()
context = super().get(request, *args, **kwargs)
token = self.kwargs['token']
download = Download.objects.get(token__iexact=token)
document_title = Document.objects.get(id=download.pub_id).title
upload_doc = Document.objects.get(id=download.pub_id).upload
if download and download.expiration_date > now:
print("Token is valid until : " + str(download.expiration_date))
print("Now : " + str(now))
print(' ==> Token exists and valid <==')
messages.success(self.request, 'You are going to download document(s)')
resp = self.downloadPDF(upload_doc, document_title)
if download and download.expiration_date < now:
print("Token is valid until : " + str(download.expiration_date))
print("Now : " + str(now))
print('==> Token exists but has expired <==')
messages.error(self.request, 'Session of 10 minutes has expired - Please download document(s) one more time')
return render(request, self.template_name)
return resp
def downloadPDF(self, upload_doc, document_title):
fs = FileSystemStorage()
filename = upload_doc
if fs.exists(filename):
with fs.open(filename) as pdf:
response = HttpResponse(pdf, content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' % document_title
return response
else:
return HttpResponseNotFound('The requested pdf was not found in our server.')
You call the downloadPDF but you ignore its return value. You would need to return the result of calling that method. However, this will not work because you cannot return a response from get_context_data; that method, as the name implies, must return a dictionary context and not a response.
You need to move this code into the get method.

download a file after rendering a template in django

I am trying to download a csv file and rendering a template at the same time after redirecting from a view but it only downloads the file ,doesn't render the template.
I think it can be handled by middleware but finding an easier solution to it.
class ProductUploadView(FormView):
template_name ='upload.html'
form_class = csvform
success_url = 'response/'
failed_rows = []
def post(self,request,*args,**kwargs):
form = self.form_class(request.POST,request.FILES)
file = request.FILES['csvfile']
csvfile = csv.reader(utf_8_encoder(file), dialect='excel', delimiter=',')
csvfile.next()
for row in csvfile:
if row[1] in ['PRES','GEN','GEN'] and row[2] in ['CAPS','TAB','SYP','GEL','SUSP','INJ']:
try:
p, created = Product.objects.get_or_create(brand_name=row[0], category=row[1], defaults={'form': row[2], 'mrp': row[3], 'ptr': row[4]})
except ValidationError:
self.failed_rows.append(row)
pass
else:
self.failed_rows.append(row)
return HttpResponseRedirect(self.success_url)
class UploadedView(ProductUploadView):
template_name = 'response.html'
rows = ProductUploadView.failed_rows
def download_view(self,request):
response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
writer = csv.writer(response)
writer.writerows(self.rows)
return response
def get(self,request):
response = TemplateResponse(request,self.template_name,{'num':len(self.rows),'failed_rows':self.rows})
response.add_post_render_callback(download_view)
return response

Save request.POST to database

in view.py:
#require_POST
#csrf_exempt
def ipn(request):
transactions_logger = logging.getLogger("django")
processor = Ipn(request.POST, logger=transactions_logger)
verification_success = processor.verify_ipn()
encoding = request.POST.get('ok_charset', None)
data = QueryDict(request.body, encoding=encoding)
if verification_success:
form = OkpayIpnForm(data)
if form.is_valid():
print("ALL FINE!!")
form.save()
return HttpResponse("")
In forms.py:
class OkpayIpnForm(forms.ModelForm):
class Meta:
model = OkpayIpn
exclude = []
Code for IPN Checkprocessor = Ipn(request.POST, logger=transactions_logger:
class Ipn(object):
OKPAY_VERIFICATION_URL = 'https://checkout.okpay.com/ipn-verify'
OKPAY_IPN_INVALID = b'INVALID'
OKPAY_IPN_VERIFIED = b'VERIFIED'
OKPAY_IPN_TEST = b'TEST'
OKPAY_STATUS_COMPLETED = 'completed'
__verification_result = False
def __init__(self, request_data, logger):
if 'ok_verify' in request_data:
raise Exception("ok_verify must not be present in initial request data for {}".format(
self.__class__.__name__
))
self._request_data = request_data
self.logger = logger
return
def verify_ipn(self):
self.__verification_result = False
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
}
verify_request_payload = {
'ok_verify': 'true',
}
verify_request_payload.update(self._request_data)
resp = requests.post(self.OKPAY_VERIFICATION_URL, data=verify_request_payload, headers=headers)
if resp.content == self.OKPAY_IPN_VERIFIED or resp.content == self.OKPAY_IPN_TEST:
self.__verification_result = True
# if resp.content == self.OKPAY_IPN_VERIFIED: # anyway disable test on production.
# self.__verification_result = True
return self.__verification_result
All is ok, I revice IPN and validate it, then I try to validate form and save it to Database.
But form doesn't pass validation and doesn't save to database.
Thank You for help
Problem was that 1 CharField of Model for saving IPN has maxlength=20, but recieved 40 symbols.
Thx jape he advised to add in form validation else statement and print form.errors
the error of of form validation was :
<li>ok_item_1_type<ul class="errorlist"><li>Ensure this value has at most 20 characters (it has 40).</li></ul></li>

django twilio for number phone confirmation returns exception in send function

I got an exception when i create a sms to send
here is my functions
def send_sms(to_number, body):
account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
twilio_number = '+15005550006'
client = TwilioRestClient(account_sid, auth_token)
try :
client.messages.create(to=to_number,
from_=twilio_number,
body=body)
except Exception as e:
print e.message
def generate_code():
return str(random.randrange(100000, 999999))
def send_confirmation_code(request,to_number):
verification_code = generate_code()
send_sms(to_number, verification_code)
request.session['verification_code'] = verification_code
return verification_code