I have 2 models. First is House. Second is HouseImage
Therefore I have to submit the image with ForeigneKey
I can upload by using the REST normally, but failed to do unittest.
The reason why I keep doing unittest in here because I have a more specifications waiting for me and I would not do hand-test for sure.
django==1.11.5
djangorestframework==3.6.4
python3.6.2
PostgreSQL 9.6.5 on x86_64-apple-darwin14.5.0, compiled by Apple LLVM version 7.0.0 (clang-700.1.76), 64-bit
Here is my additional source code.
https://gist.github.com/elcolie/a013be9c3b7ab5f0cc130e320b19da4b
import tempfile
from PIL import Image
from django.contrib.auth.models import User
from model_mommy import mommy
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APITestCase, APIClient
from soken_web.apps.houses.models import House
class HouseImageTest(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = mommy.make(User, username='Pan')
self.house = mommy.make(House, location="100.00, 100.00")
def test_post_image(self):
self.client.force_authenticate(user=self.user)
image = Image.new('RGB', (100, 100))
tmp_file = tempfile.NamedTemporaryFile(suffix='.jpg')
image.save(tmp_file)
data = {
'image': tmp_file,
'house': self.house.id,
}
response = self.client.post(reverse('api:house_images-list'), data, format='multipart')
self.assertEqual(status.HTTP_201_CREATED, response.status_code)
Problem:
Server raises appliation/json type to me
Attempts:
1. Replace format=multipart with content_type/multipart. Same error
1. User both format=mulipart and content_type/multipart. It is not permitted by DRF
Solution:
#zaidfazil Thank you very much. You are right. I have to use real-file
import tempfile
from django.conf import settings
from django.contrib.auth.models import User
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from model_mommy import mommy
from rest_framework import status
from rest_framework.reverse import reverse
from rest_framework.test import APITestCase, APIClient
from soken_web.apps.houses.models import House
class HouseImageTest(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = mommy.make(User, username='Pan')
self.house = mommy.make(House, location="100.00, 100.00")
settings.MEDIA_ROOT = tempfile.mkdtemp()
def test_post_image(self):
file = File(open('static/rest_framework/img/grid.png', 'rb'))
uploaded_file = SimpleUploadedFile('new_image.jpg', file.read(), content_type='multipart/form-data')
data = {
'image': uploaded_file,
'houses': self.house.id,
}
self.client.force_authenticate(user=self.user)
response = self.client.post(reverse('api:house_images-list'), data, format='multipart')
response.render()
self.assertEqual(status.HTTP_201_CREATED, response.status_code)
References:
How can I test binary file uploading with django-rest-framework's test client?
http://www.django-rest-framework.org/api-guide/testing/
You may need to convert the file into uploaded file format before posting to the url,
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files import File
class HouseImageTest(APITestCase):
def setUp(self):
self.client = APIClient()
self.user = mommy.make(User, username='Pan')
self.house = mommy.make(House, location="100.00, 100.00")
settings.MEDIA_ROOT = tempfile.mkdtemp()
def test_post_image(self):
image = Image.new('RGB', (100, 100))
tmp_file = tempfile.NamedTemporaryFile(suffix='.jpg')
image.save(tmp_file)
file = File(tmp_file)
uploaded_file = SimpleUploadedFile('new_image.jpg', file.read(), content_type='multipart/form-data')
data = {
'image': uploaded_file,
'houses': self.house.id,
}
self.client.force_authenticate(user=self.user)
response = self.client.post(reverse('api:house_images-list'), data, format='multipart')
response.render()
self.assertEqual(status.HTTP_201_CREATED, response.status_code)
Related
from flask import Flask
from flask import render_template, redirect, request
from flask_restful import Resource, Api
import requests
import pickle
app = Flask(name)
api = Api(app)
class HelloWorld(Resource):
def post(self):
r = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_r = r.json()
temp_k = float(json_object_r['main']['temp'])
temp_c = temp_k - 273.15
tempp_c = int(temp_c)
pickle_in = open("var.pickle", "wb")
tempp_c = pickle.load(pickle_in)
# pressure
p = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_p = p.json()
press_k = float(json_object_p['main']['pressure'])
# wind
# speed
w = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_w = w.json()
wind_k = float(json_object_w['wind']['speed'])
# gust
g = requests.get('https://samples.openweathermap.org/data/2.5/weather?zip=16802,us&appid=157d320b7d029e653c67902f982784ff')
json_object_g = g.json()
gust_g = float(json_object_g['wind']['gust'])
return {tempp_c}
api.add_resource(HelloWorld, '/')
if name == 'main':
app.run(debug=True)
Create a program which sends serialised object first:
import flask
import pickle
object_to_send = {1:2}
#app.route('/endpoint')
def endpoint():
return pickle.dumps(object_to_send).hex()
app.run(port=8080)
Then you can call it from another python program and read that object:
import pickle
import requests
object_hex = requests.get('http://127.0.0.1:8080/endpoint').text
object_received = pickle.loads(bytearray.fromhex(object_hex))
print(object_received)
This is definitely not a best practice - perhaps you should serialise as json, if at all possible, or use some framework for messaging, which should support different serialisation methods, or a message bus, like Kafka.
I have written below custom collector which pulls the data from a rest api and adds page view metrics. Each payload has 5 metrics so I am adding timestamp to it. It successfully publishes it to the http listener but the metrics never expires. How can I add the expiry to these metrics?
#!/usr/bin/env python3
import argparse
import re
import sys
import time
import datetime
import urllib3
import requests
import aniso8601
import pytz
import json
from prometheus_client import start_http_server
from prometheus_client.core import GaugeMetricFamily, REGISTRY
class HttpCollector(object):
def __init__(self):
self.url = "my_endpoint"
self.username = 'my_userid'
self.password = 'my_pass'
self.labels = ['app_name', 'url_host' ]
self.page_views_metrics = GaugeMetricFamily('pageviews', 'Page Views', labels=self.labels)
def collect(self):
headers = {'Accept': '*/*', }
auth = (self.username, self.password)
urllib3.disable_warnings()
result = requests.get(self.url, headers=headers, auth=auth, timeout=60, verify=False)
if not result.ok:
# Log error
print("No results")
return
json_result = result.json()
for record in json_result['records']:
timestamp_epoch = covert_date_to_epoch(record["timestamp'])
label_values = ["testapp", "testhost"]
self.page_views_metrics.add_metric(label_values, record["page_views"], timestamp=timestamp_epoch)
yield self.page_views_metrics
Making the self.page_views_metrics as local variable to collect method solved the problem.
import re
import sys
import time
import datetime
import urllib3
import requests
import aniso8601
import pytz
import json
from prometheus_client import start_http_server
from prometheus_client.core import GaugeMetricFamily, REGISTRY
class HttpCollector(object):
def __init__(self):
self.url = "my_endpoint"
self.username = 'my_userid'
self.password = 'my_pass'
self.labels = ['app_name', 'url_host' ]
def collect(self):
headers = {'Accept': '*/*', }
auth = (self.username, self.password)
urllib3.disable_warnings()
result = requests.get(self.url, headers=headers, auth=auth, timeout=60, verify=False)
if not result.ok:
# Log error
print("No results")
return
json_result = result.json()
page_views_metrics = GaugeMetricFamily('pageviews', 'Page Views', labels=self.labels)
for record in json_result['records']:
timestamp_epoch = covert_date_to_epoch(record["timestamp'])
label_values = ["testapp", "testhost"]
page_views_metrics.add_metric(label_values, record["page_views"], timestamp=timestamp_epoch)
yield page_views_metrics
I am new in Django and even in programming. I want to download an mp3 file from a youtube video and send it as a message (a link to download) to the user. I will download the video and then convert it
Here is what I have tried so far.
views.py
import os
import sys
from .task import *
from datetime import datetime
from .models import Downloader
from .forms import DownloadForm
from django.shortcuts import render
def main_page(request):
if request.method == 'POST':
form = DownloadForm(request.POST)
if form.is_valid():
video_url = form.cleaned_data.get('link')
email = form.cleaned_data.get('email')
try:
convert_load.delay(video_url)
Downloader.objects.create(url=video_url, email=email)
except Exception as e:
exc_type, exc_obj, exc_tb = sys.exc_info()
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
print(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ' Type:{} Filename:{} Line:{}ERROR: {}'.
format(exc_type, fname, exc_tb.tb_lineno, e))
return render(request, 'download_link.html')
else:
form = DownloadForm()
return render(request, 'main_page.html', {'form': form})
def history(request):
return render(request, 'history.html', {'instance': Downloader.objects.all()})
def download_link(request):
link_location = 'media/{}'.format('skjdskdj')
print(link_location, '\n\n\n\n')
return render(request, 'download_link.html', {'link': link_location})
task.py
from __future__ import unicode_literals
import youtube_dl
from celery import task
from django.core.mail import send_mail
import converter
from converter.models import Downloader
from django.utils.timezone import now
#task
def convert_load(video_url):
# Mp3 format options
ydl_opts = {
'format': 'bestaudio/best',
'outtmpl': 'media/%(title)s.mp3',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
},
{'key': 'FFmpegMetadata'}
],
}
with youtube_dl.YoutubeDL(ydl_opts) as yld:
file_data = yld.extract_info(video_url)
name = file_data['title']
email = file_data['email']
mail_sending.delay(email, name)
return name, email
#task
def mail_sending(email, name):
send_mail(
'Download link',
'You can download file from this link: http://127.0.0.1:8000/converter/media/{}'.format(name),
'foto.nurbek#gmail.com',
[email],
fail_silently=False
)
I will be greatful if somebody could provide any leads/solution to my problem?
File Manager
I want uploading any file and i have a file manager service that get the file and saving without extension and files name are UUID and return file information.
my file manager handler :
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
from pyramid_storage.exceptions import FileNotAllowed
import uuid
from pyramid.view import view_config
from pyramid.response import Response
import os
class UploadHandler:
def __init__(self, request):
self.request = request
self.settings = self.request.registry.settings
#view_config(route_name='upload', request_method='POST', renderer='json')
def post(self):
# file
f = self.request.POST.items()
# file name
file_name_main = f[0][1].filename
# content type
content_type = str(f[0][1].type)
if content_type:
extension_main = content_type.split('.')[-1]
# set id for file name
if extension_main:
f[0][1].filename = str(uuid.uuid4())
else:
response = Response(body=json.dumps({'ERROR': 'Your File Not Allowed'}))
response.headers.update({
'Access-Control-Allow-Origin': self.settings['Access-Control-Allow-Origin'],
})
return response
else:
response = Response(body=json.dumps({'ERROR': 'Your File Not Allowed'}))
response.headers.update({
'Access-Control-Allow-Origin': self.settings['Access-Control-Allow-Origin'],
})
return response
try:
# save file
file_name = str(self.request.storage.save(f[0][1]))
except FileNotAllowed:
response = Response(body=json.dumps({'ERROR': 'Your File Not Allowed'}))
response.headers.update({
'Access-Control-Allow-Origin': self.settings['Access-Control-Allow-Origin'],
})
return response
# file name == file id
f_name = file_name
file_path = self.request.storage.base_path + os.sep + f_name
file_size = os.path.getsize(file_path)
response = Response(body=json.dumps(
{'file_id': f_name, 'file_name': file_name_main, 'content_type': content_type, 'size': file_size,
'extension': extension_main}))
response.headers.update({
'Access-Control-Allow-Origin': self.settings['Access-Control-Allow-Origin'],
})
return response
There's a UNIX utility called file that uses "magic" to recognize known file types. file uses a library called libmagic for this purpose.
The python interface to libmagic is called filemagic and you can get it here.
I am using from social_auth.signals import socialauth_registered for new registered user in my project. and I have noticed that when I try to sign-up on facebook to my project. my project did not get the profile pic of my facebook, instead it gets the profile pic of my gravatar.com account.
this is my code :
from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from userena.models import *
from social_auth.signals import pre_update
from social_auth.backends.facebook import FacebookBackend
from social_auth.backends import google
from social_auth.signals import socialauth_registered
import datetime
def new_users_handler(sender, user, response, details, **kwargs):
user.is_new = True
print "hello"
if user.is_new:
print "world"
if "id" in response:
print "police"
from urllib2 import urlopen, HTTPError
from django.template.defaultfilters import slugify
from django.core.files.base import ContentFile
try:
url = None
if sender == FacebookBackend:
url = "http://graph.facebook.com/%s/picture?type=large" \
% response["id"]
elif sender == google.GoogleOAuth2Backend and "picture" in response:
url = response["picture"]
print url
if url:
avatar = urlopen(url)
#profile = UserProfile(user=user)
print "again"
print user
fileName = "media/mugshots/"+ str(user) + ".jpg"
print "okss"
print fileName
try:
profile = Profile.objects.get(user=user)
except:
profile = Profile.objects.create(user=user)
localFile = open(fileName, 'w')
localFile.write(avatar.read())
localFile.close()
profile.mugshot = fileName
print "save=ing profile"
#profile.mugshot.save(slugify(user.username + " social") + '.jpg',
# ContentFile(avatar.read()))
profile.save()
except HTTPError:
pass
return False
socialauth_registered.connect(new_users_handler, sender=None)
but my code did not work on saving the facebook profile pic to `media/mudshots/ dir.
my question is, how can I get the profile pic of a facebook account and save it in media/mudshots/ dir in my django project?
can anyone can help me about my case?
thanks in advance ..
i get it... i use this ..
import datetime
import urllib
import string
import random
import os
avatar = urlopen(url)
try:
profile = Profile.objects.get(user=user)
except:
profile = Profile.objects.create(user=user)
print profile
print "sdfffffffffffffffffffff"
filename_charset = string.ascii_letters + string.digits
filename_length = 10
file_save_dir = 'media/mugshots/'
filename = ''.join(random.choice(filename_charset)
for s in range(filename_length))
urllib.urlretrieve (url, os.path.join(file_save_dir, filename + '.png'))
profile.mugshot = 'mugshots/'+filename + '.png'
profile.save()