first of all i'm sorry because of my duplicated question but actually the other didn't work for me at all.
my problem is that I have 2 views which the first one is returning a Httpresponse to the 2nd, and what I want is to convert this Httpresponse to dictionary in the 2nd view and have access to it's elements.
here is the code :
1st view:
def base_tag_upload(request, tag):
error = False
upload_msg = "success"
user = request.user
response_data = {"error": error, "upload_msg": upload_msg, "file_id": None, "file_version": None}
if request.method == 'POST':
form = UploadForm(request.POST or None, request.FILES or None, tag=tag, user=user)
if form.is_valid():
cd = form.cleaned_data
uploaded_file = cd['file']
collection_name = cd['new_name'] or uploaded_file.name.split('.')[0].strip()
response_data.update(
{"uf_name": uploaded_file.name, "uf_size": uploaded_file.size, "uf_colname": collection_name})
set_primary = True # first file in collection
# Finding/Creating Related FileCollection
collection = FileCollection.objects.create(name=collection_name)
is_major = cd['version_type'] == 'mj'
file_obj = collection.upload_file(uploaded_file, set_primary, Major_version=is_major)
file_obj.author = user
collection.tags.add(tag)
collection.get_tag_permissions(tag, False)
file_obj.get_collection_permissions(collection, False)
set_user_ownership(collection, tag, user)
set_user_ownership(file_obj, tag, user)
collection.save()
file_obj.collection = collection
file_obj.save()
response_data.update({'file_id':file_obj.id, 'file_version': file_obj.version})
ActionLog.log(action=Action.objects.get(name="create"), target=file_obj,
user=user, request=request, details=None, extra_details=None)
redirect_url = reverse('file_history', kwargs={'collection_id': collection.id})
response_data.update({'redirect': redirect_url})
return HttpResponse(json.dumps([response_data]))
and the 2nd one :
def tag_upload(request, tag_id):
try:
tag = Tag.objects.get(id=tag_id)
except Tag.DoesNotExist:
return HttpResponse(simplejson.dumps([{'error': 'value_error', 'upload_msg': "no such folder"}]))
k = base_tag_upload(request, tag)
k.response.decode('utf-8')
print k
return base_tag_upload(request, tag)
but I got this error when I wanted to decode the Httpresponse as shown above :
AttributeError: 'HttpResponse' object has no attribute 'response'
I have 2 views which the first one is returning a Httpresponse to the 2nd
Then you didn't structured your code properly - a view has no business calling another view not messing with the response.
If you need to share some common code between two views, then extract this code in a distinct function (that would in this case return a plain dict) and call this function from both your views.
It's k.content.decode('utf-8').
Related
I am trying to get my view to redirect to another page after clicking a button that triggers the POST request. I cannot seem to figure out why the redirect doesn't work or why it doesn't even seem to try to redirect.
Here is my view:
def cart1(request):
if request.user.is_authenticated:
#POST
if request.method == "POST":
#JSON Data
data = request.body
new_data = ast.literal_eval(data.decode('utf-8'))
customer = request.user
user_order = Order(user=customer)
user_order.save()
x = 0
while x < len(new_data.keys()):
obj_title = new_data[x]["title"]
obj_price = new_data[x]["price"]
obj_quantity = new_data[x]["quantity"]
obj_extra = new_data[x]["extra"]
total = round(float(obj_price.replace("$", "")))
m = OrderItem(order=user_order, title=obj_title, price=total, quantity=obj_quantity, extra=obj_extra)
m.save()
x += 1
return redirect('checkout-page')
return render(request, 'cart.html')
Any help would be appreciated, thank you
redirect(…) [Django-doc] produces a HttpRedirectResponse, you need to return it, so:
return redirect('checkout-page')
redirect(…) itself thus does not stop the code flow to redirect return a HTTP redirect response, it constructs such response, and your view should then return that response.
you need to be sure the URL name =checkout-page is in the current app otherwise you need to make it redirect('app:checkout-page')
However,I suggest to use from django.http import HttpResponseRedirect
I want to pass some arguments to my HTML form from flask when using redirect(url_for('Some End-Point')) instead of render_template(). I have already visited both of these questions
redirect while passing arguments
How can I pass arguments into redirect(url_for()) of Flask?
but neither of them had the answer I am looking for. After some surfing I do find out that I have to use session for this but the problem is I don't know actually how to use that either. When I use this:
return redirect(url_for('register', neg_resp="Username Already Taken"))
the problem was, my output message do generate but came with URL instead and thus my jinja template doesn't receive it. Link from 120.0.0.1:5000/register/ changed to 120.0.0.1:5000/register/?=Username Already Taken
And when I do this:
return redirect(url_for('register'), neg_resp="Username Already Taken")
An error gets generated, TypeError: redirect() got an unexpected keyword argument 'neg_resp'
Here's my Python Code
# Setting Up Route for Register Page
#app.route('/register/', methods=['GET', 'POST'])
def register():
# Fetching Form Data
user = {
"name": request.form.get('name'),
"email": request.form.get('email'),
"username": request.form.get('username'),
"password": request.form.get('password'),
"tasks":[]
}
# Inserting data to Database and Redirecting to Login Page after Successful Registration
if user['name'] != None:
user['password'] = pbkdf2_sha256.encrypt(user['password'])
if mongo.db.appname.find_one({"username": user["username"]}):
return redirect(url_for('register'), neg_resp="Username Already Taken")
else:
mongo.db.appname.insert(user)
return redirect(url_for('login', pos_resp="Registered Successfully"))
return render_template('register.html')
Error
TypeError: redirect() got an unexpected keyword argument 'neg_resp'
This won't work:
return redirect(url_for('register'), neg_resp="Username Already Taken")
because it passes neg_resp as a parameter of redirect instead of url_for.
Here's a basic example of how to pass parameters between routes and to a template:
#app.route('/first/')
def first():
return redirect(url_for('second', passed_value='string value'))
#app.route('/second/')
def second():
passed_value = request.args.get('passed_value')
return render_template('index.html', val_name=passed_value)
So here's what I tried, I made a global dictionary and keep updating it wherever needed, now whenever I want to access some values I directly access it from my dictionary and render it using jinja templating. Apart from this method there are other ways as well like storing data in flask.session also one can use flask.flash() to render messages and access them using messages.get() function in their jinja template, but the problem with it is, it only provides a limited amount of size, if you pass an object or string of beyond that size, the browser simply ignores it and your messages will not be displayed because the message passed is in the form of browser-cookies. So, storing them in my global dictionary works for me:
Here's a small snippet of my final code which similarizes the code I have posted as question:
# Globals
info = {
'logged_in' : False,
'user' : {},
'tasks' : [],
'status' : {
'value' : '',
'positive' : True
}
}
def reset():
'''
function to reset the values of info object
'''
global info
info['logged_in'] = False
info['user'] = {}
info['tasks'] = []
info['status'] = {
'value' : '',
'positive' : True
}
# Setting Up Route for Register Page
#app.route('/register/', methods=['GET', 'POST'])
def register():
'''
function to register an account into the server and database
'''
global info
# Fetching Form Data
user = {
"name": request.form.get('name'),
"email": request.form.get('email'),
"username": request.form.get('username'),
"password": request.form.get('password'),
"tasks":[]
}
# Inserting data to Database and Redirecting to Login Page after Successful Registration
if user['name'] != None:
user['password'] = pbkdf2_sha256.encrypt(user['password'])
if mongo.db.appname.find_one({"username": user["username"]}):
info['status']['value'] = 'Username Already Taken'
info['status']['positive'] = False
return redirect(url_for('register'))
else:
mongo.db.appname.insert(user)
info['status']['value'] = 'Registered Successfully'
info['status']['positive'] = True
return redirect(url_for('login'))
status_val = info['status']['value']
positive_status = info['status']['positive']
reset()
return render_template('register.html', value = status_val, positive = positive_status)
I am trying to get User as foreignkey in a model but getting error.
When I try:
qr.claimed = True
user = get_object_or_404(User,id=request.user.id)
qr.branch = user
qr.save();
OUTPUT:
AttributeError: 'str' object has no attribute 'user'
When I try to POST:
qr.claimed = True
get_user = request.POST.get('branch')
user = User.objects.get(id=get_user)
qr.branch = user
qr.save();
OUTPUT:
AttributeError: 'str' object has no attribute 'POST'
When I define user in another python file and try to fetch from there:
qr.claimed = True
get_user = pythonfile.user
user = User.objects.get(id=get_user)
qr.branch = user
qr.save();
OUTPUT:
TypeError: Field 'id' expected a number but got <function user at 0x0E777E38>.
request.user -> AttributeError: 'str' object has no attribute 'user'
request.POST -> AttributeError: 'str' object has no attribute 'POST'
Any error with request or missing any package to install/import?
UPDATE:
#csrf_exempt
def decodeAjax(request):
if request.POST:
decodedData = barCode.decode(request.POST['imgBase64'])
if decodedData:
json_data = json.dumps(decodedData)
print(json_data)
return JsonResponse(json_data,safe=False)
return JsonResponse({"code" : 'NO BarCode Found'})
def decode(request):
# Find barcodes and QR codes
imgstr = re.search(r'base64,(.*)', request).group(1) #url
image_bytes = io.BytesIO(base64.b64decode(imgstr))
im = Image.open(image_bytes)
arr = np.array(im)[:, :, 0]
decodedObjects = pyzbar.decode(arr)
#print(decodedObjects)
# return decodedObjects.Decoded
# Print results
data = []
for obj in decodedObjects:
qrs = Scanner.objects.all()
for qr in qrs:
if obj.data.decode('utf-8') in qr.ID:
dt = 'Successfully Claimed!'
btn = 'Claim Another'
img = 'tick.gif'
if qr.claimed == True:
dt = 'Already Claimed at %s'%(localtime(qr.scanned_at))
img = 'cross.png'
else:
qr.claimed = True
qr.save();
break
else:
dt = 'Invalid QR Code'
btn = 'Try Another'
img = 'cross.png'
data.append({
"code":obj.data.decode('utf-8') ,
#"type": obj.type,
"dt": dt,
"btn":btn,
"img":img
})
return data
You check the method with:
#csrf_exempt
def decodeAjax(request):
if request.method == 'POST':
decodedData = barCode.decode(request.POST['imgBase64'])
# …
The item you pass to decode is not a HttpRequest object, but the image in base64 encoding. You thus might want to rename this to:
def decode(base64img):
imgstr = re.search(r'base64,(.*)', base64img).group(1)
# …
If you need the request somewhere, you will need to pass request, not request.POST['imgBase64'].
furthermore I would really advise not to make methods with a CSRF exeption. You can send the CSRF token as specified in the AJAX section of the documentation.
With Flask-Admin and Flask how can I submit a form\view based on ModelView from code?
I'm trying to create a separate view\form that would allow user to add multiple entries with one form. Specifically allowing to upload multiple images with common prefix name and common parameters. I'd like to do it by submitting a single-image upload form from code, because it does some additional processing like resizing images and I'd like to let Flask-Admin handle connecting database entries and files.
Here's the form I'd like to submit from code:
class ImageView(ModelView):
def _list_thumbnail(view, context, model, name):
if not model.path:
return ''
return Markup('<img src="%s">' % url_for('media',
filename=form.thumbgen_filename(model.path)))
column_labels = dict(show_in_header="Show In Header?",
path="Image")
form_create_rules = ("name",
"tags",
rules.Text(
"Use this image as header. If more than one image is selected header image will be random each time the page is loaded."),
"show_in_header",
"path")
form_excluded_columns = ("timestamp")
column_formatters = {
'path': _list_thumbnail
}
thumbnail_size = config("media", "thumbnail_size")
form_extra_fields = {
'path': BroImageUploadField('Image',
base_path=IMAGES_FOLDER,
thumbnail_size=(thumbnail_size, thumbnail_size, True),
endpoint="media",
url_relative_path='media',
relative_path=None)
}
def is_accessible(self):
return current_user.is_authenticated
def inaccessible_callback(self, name, **kwargs):
# redirect to login page if user doesn't have access
return redirect(url_for('login', next=request.url))
And here I'm creating a form and I'm just not sure that .process() is the function to submit it? Is there one at all?
lass MultipleImagesUploadView(BaseView):
#expose("/", methods=["GET", "POST"])
def index(self):
if request.method == "POST":
a_form = MultipleImagesForm(request.form)
base_name = a_form.base_name.data
tags = a_form.tags.data
show_in_header = a_form.show_in_header.data
print (request.files.getlist(a_form.images.name))
uploaded_files = request.files.getlist(a_form.images.name)
for i, uf in enumerate(uploaded_files):
try:
name, ext = os.path.splitext(uf.filename)
if ext not in IMAGE_EXTENSIONS:
flash("Image file {} was skipped as it's extension is not supported ({}).".format(uf.filename, ext), category="warning")
continue
image_contents = uf.stream.read()
image_form = ImageView()
image_form.name.data = "{}_{}".format(base_name, i)
image_form.tags.data = tags
image_form.show_in_header.data = show_in_header
image_form.path.data = image_contents
image_form.process()
except Exception as e:
flash ("Unhandled exception: {}".format(e), category="warning")
flash("Images were added to the gallery.", category='success')
a_form = MultipleImagesForm()
print("############", a_form)
return self.render('/admin/multiple_images_upload.html', form=a_form)
I can't figure out a way to submit a form from code, been trying to find the answer in docs and google for hours now with no luck.
Found the issue. In my case I was missing the enctype="multipart/form-data". Without that files part was sent as empty.
Also changed to using from flask_wtf import FlaskForm and enabling it as {{ form.files(class="form-control", multiple="") }} in the template.
Files can then be accessed with uploaded_files = request.files.getlist("files") on POST request, it will hold array of file-objects.
I hope this helps someone. If any additional formatting is required I will add or expand the answer.
I have a page called 'Read Later' where the users read later posts are stored. I have the Read Later on the nav bar. Now, when the user has no read later posts and clicks on Read Later, the user is redirected back to the original page. I have a function based def for Read Later.
views.py :
def show_readlater(request, *args):
global redirect
global redirect_lock
global return_address
if not(redirect_lock):
redirect = None
else:
redirect_lock = False
if not(request.user.is_authenticated()):
raise PermissionDenied
else:
user_instance = User.objects.get(username = request.user.username)
userprofile_instance = UserProfile.objects.get(user = user_instance)
readlater_objects = ReadLaterList.objects.all()
readlater_list = []
count = 0
for x in readlater_objects:
if x.username == request.user.username:
readlater_post = Post.objects.get(slug = x.slug)
readlater_list.append(readlater_post)
count = count + 1
if count == 0 :
redirect = "no_readlater"
redirect_lock = True
return HttpResponseRedirect(return_address) # The user is redirect back to the original page
post_title = "Read Later"
template = "posts/show_posts.html"
dictionary = {
"total_posts" : readlater_list,
"title" : post_title,
"count" : count,
"redirect" : redirect,
}
return render(request, template, dictionary)
Here, redirect is to display a message that no Read Later posts are there, in the original page.
The issue is that, when the redirect happens, Django says page not found, but upon refresh the page is loaded.
What is happening ?
first of all change this
global redirect
global redirect_lock
global return_address
to
request.session['redirect']= redirect
for all global variables
and use redirect instead HttpResponseRedirect
Make sure the url specified in the global variable "return_address" is correct and specified in your app/urls.py.