I have an existing views.py file in my django app something like this:
from django.shortcuts import render
def segment_image(request):
if request.method == 'POST':
form = segment_form()
else:
if form.is_valid():
info = request.POST['info_name']
output = script_function(info)
return render(request, 'your_app/your_template.html', {
'output': output,
})
return render(request, 'your_app/your_template.html', {
'form': form,
})
def script_function(info):
'''here goes my main logic'''
x=y=w=h=102
return x,y,w,h
which used to interact with a django template and a django form.But, now i am in the process of shifting everything to a angular frontend app so i replaced the form with a angular $http post.
index.html
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-4" ng-repeat="image in images track by image.pk">
<h3>
Image {{ image.pk }}
<button class="btn btn-warning" ng-click="deleteImage(image)">Delete</button>
<button class="btn btn-primary" ng-click="segmentImage(image)">Segment</button>
</h3>
<a href="{{ image.image }}">
<img class="img-responsive" ng-src="{{ image.image }}">
</a>
</div>
app.js
...
$scope.segmentImage = function(image)
{
$http({method:'POST', url:'127.0.0.1:8000/image/segment_image/', data:{'image': image}})
.then(function successCallback(response)
{
console.log('success')
},function errorCallback(response)
{
console.log('failed')
console.log(response.config)
console.log(response.statusText)
}
)};
...
Now what changes do i need to make to my views.py so that it can recieve the image from angularapp and pass it to my script_function, and render the return values(x,y,w,h) back to index.html
Related
I have a page where I load 2 files. After a click to the load button, this page reload to display a major part of the data, allowing the user to modified it. After a click to lunch button, I want to launch the process and I want to send to another page the path of results files to allow the user to download it.
My problem is after clicking on lunch button and send data to the other page. I have 2 versions :
The first one, send data to the result page, but I do not find a way to take back in the view the data modified by the user, the ajax seems to be ignored because of the type "summit" for the button launch :
<body>
<section class="bg-light py-5 border-bottom">
<div class="container px-5 my-5 px-5">
<div>
<h1 class="display-5 fw-bolder mb-2"> Convert to Dose </h1>
<br>
</div>
<form id="formCTD" action="{% url 'json:convertToDose' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
##here some fields to modified one of them following
<div class="row gx-5 justify-content-center">
<div class="col-lg-4 col-xl-4">
{% if factors %}
<input name="img_path" readonly
class="form-control" {{ pathAnalyseForm.img_path }}>
{% else %}
<input id="btn-submit-form-jsonfile"
class="btn btn-lg" {{ formImgFile.imgFile }}>
{% endif %}
</div>
</div>
<div class="text-center">
<div class="d-grid">
{% if factors %}
<button class="btn btn-primary btn-lg" id="launchButton" type="submit">
Launch
</button>
{% else %}
<button class="btn btn-primary btn-lg" id="submitButton" type="submit">
Load
</button>
{% endif %}
/div>
</div>
</form>
</div>
</section>
</body>
And the js block :
<script type="text/javascript">
$(document).ready(function () {
$("#launchButton").on('submit', function(e) {
e.preventDefault();
var form = $("#formCTD").get(0) //recup en html
// Est-ce que le formulaire est valide ?
console.log("valid? ")
if (form.checkValidity()) {
console.log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ")
nam = $("input[name='img_path']").val()
json = $("input[name='json_path']").val()
console.log(nam)
data = {"img_path" : nam,
"json_path": json}
console.log("bef ajax")
$.ajax({
url: "/filmchromique/convertToDose/",
type: "POST",
data: data,
beforeSend: function (xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
success: function (response) {
console.log("ok")
},
error: function(xhr, status, error) {
alert(xhr.responseText);
}
})
console.log("after ajax")
}
});
});
</script>
And the view :
def launchCtd(request):
if request.method == 'POST':
#2 after click load
if bool(request.FILES.get('calibrationFile', False)) == True and bool(request.FILES.get('imgFile', False)) == True :
#do some test ok
context = {
'factors': True,
'factorsCalib': factorsCalib,
'formCtd': formCtd,
'formJsonFile': formJsonFile,
'formImgFile': formImgFile,
'pathAnalyseForm': pathAnalyseForm,
'doseRect': doseRect,
'ctrlRect': ctrlRect,
}
return render(request, 'convertToDose.html', context)
after click lunch
else:
if request.is_ajax:
print ("here")#check
img_path = request.POST.get("img_path")
doseRectStr = request.POST.getlist('form[]')
json_pactrlRectth = request.POST.get("json_path")
method = request.POST.get("analyse_type")
if method == 'rb':
#init var
if method == 'multi':
#init var
img_out_path, json_pactrlRectth = functionTOLaunch()
context = {
'filename': img_out_path,
'protocol_file': json_pactrlRectth,
}
return render(request, 'result.html', context)
#1 load init
else:
formCtd = CtdForm()
formJsonFile = JsonFileForm()
formImgFile = ImgFileForm()
context = {
'factors': False,
'formCtd': formCtd,
'formJsonFile': formJsonFile,
'formImgFile' : formImgFile,
}
return render(request, 'convertToDose.html', context)
and the result page is a basic TemplateView.
In this first case, console.log in the ajax are not printed, I do not understand why and I supposed the function is not called (and so the ajax part)
in the second version, views are identical but I modified this on the html :
<button class="btn btn-primary btn-lg" id="launchButton" type="button">
Launch</button>
and this in the js part :
$("#launchButton").on('click', function(e) {....}
Data are sended to the view, I can read it but when I do the render to display the result page with out process data, nothing append... I supposed I have to implement something in the succes ajax part, but I do not understand what I have to do. I supposed I have to implement a new ajax request, to send the new context to the result page but how I take back the context sended by the render in the success ajax ... I'am totaly new and lost on this tech
Thanks for reading :)
So I am creating and working around forms in my web app. I have a profile page for all users (displaying their first name, last name, email, etc). I am trying to add an 'edit' button to it and once they click on it, they are taken to the update form page where they type in the new details and click on the update button and once they do so, they are taken back to their profile page but with the new details they have entered this time (a simple edit button)
my forms.py class for the update form is:
class Updateform(FlaskForm):
email = StringField("Email", validators=[DataRequired(), Email()])
fname = StringField("First Name", validators=[DataRequired(), Length(min=2, max=20)])
lname = StringField("Last Name", validators=[DataRequired(), Length(min=2, max=20)])
phoneno = StringField("Phone Number", validators=[DataRequired()])
submit = SubmitField("Update account")
my route to the html is:
#auth.route("/updateform", methods=["GET", "POST"])
def updateform():
form = Updateform()
if(form.validate_on_submit()):
user: User = User.select().where(User.email == form.email.data).first()
user.email = form.email.data
user.fname = form.fname.data
user.lname = form.lname.data
user.phoneno = form.phoneno
user.save()
flash('Your account has been updated', 'success')
return redirect (url_for("user.profile"))
return render_template("user/formupdate.html", form=form)
and here is the template for the update form((formupdate.html)):
{% extends "admin-layout.html" %}
{% block content %}
<div>
{% from "_formhelpers.html" import render_field %}
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="font-weight-bold text-primary">UpdateForm</h6>
</div>
<div class="card-body">
<div class="row">
<div class="col-sm-6 col-md-8">
<div>
{{ form.hidden_tag()}}
{{ render_field(form.fname, class="form-control")}}
{{ render_field(form.lname, class="form-control")}}
{{ render_field(form.email, class="form-control")}}
{{ render_field(form.phoneno, class="form-control")}}
Update form
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
My problem is that when I click on the update button after entering new details, nothing changes - the page goes back to the profile page as it is supposed to, but the details are still the same and none of the new details are visible anywhere.
What am I doing wrong and how do I fix it?
Check your implementation of user.save() for a call to commit the update to the database. Here is one of my routes for comparison, watch out for db.session.commit():
from flask import render_template, flash, redirect, url_for
from flask_login import login_required
from app import db
from app.artists import bp
from app.artists.forms import ArtistForm
from app.main.forms import EmptyForm
from app.models import Artist
#bp.route('/', methods=['GET', 'POST'])
#login_required
def overview():
create_form = ArtistForm()
delete_form = EmptyForm()
if create_form.validate_on_submit():
artist = Artist(name=create_form.name.data)
artist.save()
db.session.add(artist)
db.session.commit() # <-- persist data in database
flash(f'Created artist {create_form.name.data}.')
return redirect(url_for('artists.overview'))
return render_template('artists/overview.html', artists=Artist.query.all(), create_form=create_form, delete_form=delete_form)
I am trying to use file pond with my Django but after the images are preview and it displays them as green and I see the POST request, after clicking submit n my form when I print request.files it returns an empty list.
This is my Django view:
#login_required
def post_create(request):
data = dict()
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
post = form.save(False)
post.author = request.user
post.save()
if request.FILES is not None:
images = request.FILES.getlist('filepond')
print(images)
for i in images:
image_instance = Images.objects.create(image=i,post=post)
image_instance.save()
data['form_is_valid'] = True
data['post'] = render_to_string('home/posts/new_post.html',{'post':post},request=request)
else:
data['form_is_valid'] = False
else:
form = PostForm
context = {
'form':form,
}
data['html_form'] = render_to_string('home/posts/post_create.html',context,request=request)
return JsonResponse(data)
Andd this is my html with script:
<form method="POST" data-url="{% url 'home:post-create' %}" class="post-create-form" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-header text-center">
<h5 class="modal-title col-12 text-center">Create a Post
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</h5>
</div>
<div class="modal-body" style="height:400px;overflow-y: auto; margin:0;">
{{ form|crispy }}
<div class="pt-3" style="margin-bottom: -100px !important;">
<input type="file" class="filepond" accept="image/*">
</div>
</div>
<div class="modal-footer col-12" style="margin-top: -20px;">
<button type="submit" class="btn btn-primary" style="border-radius: 20px; width: 100%;">Post</button>
</div>
</form>
<script>
$.fn.filepond.registerPlugin(
FilePondPluginImagePreview,
FilePondPluginImageCrop,
FilePondPluginImageEdit,
FilePondPluginImageEdit,
FilePondPluginFileValidateType,
);
$(function () {
var csrf_token="{{ csrf_token }}";
$('.filepond').filepond({
allowMultiple: true,
className: "d-flex",
maxFiles: 4,
allowFileTypeValidation: true,
acceptedFileType:['image/png', 'image/jpeg'],
dropOnPage: true,
server: {
process: {
headers: {"X-CSRFToken":csrf_token,},
url: '/home/post/create/',
method: 'POST',
},
revert: {
headers: {
"X-CSRFToken":csrf_token,
},
url: '/home/post/create/',
method: 'DELETE',
},
fetch: null,
load: null,
},
labelIdle: '<span class="filepond--label-action">Add Photos</span>',
imagePreviewHeight: 250,
});
})
</script>
What is causing this issue as I can see the files being uploaded and I set the server URL to which handles the POST request how am I suppose to fix this? I have already tried renaming input field but nothing is being returned in Django when I print the files.
The files are already uploaded. You won't receive another files list, you'll receive an array of file ids (the id's returned by this endpoint '/home/post/create/).
You can then move files from the temp directory, where the process end point should put files, to a more final location.
I have an existing django web api with angular frontend, using which i can upload images and display them to the user.Now i want to extend this.On clicking the button "segment"(see image) it should pass the corresponding image to my python script on the backend, which does some processing on the image.
I have my python script in the views.py file of the main app,which is some thing like this:
from django.shortcuts import render
def segment_image(request):
if request.method == 'GET':
form = segment_form()
else:
if form.is_valid():
info = request.POST['info_name']
output = script_function(info)
''' Here i am calling script_function,passing the POST data info to it'''
return render(request, 'your_app/your_template.html', {
'output': output,
})
return render(request, 'your_app/your_template.html', {
'form': form,
})
'''here info is our image in some format'''
def script_function(info):
...
'''here goes my mian logic to process the image.'''
...
return x,y,w,h
I have never worked with images as inputs in angular,i dont know how to route the image using angularjs to my view.Now how can i implement this segmentImage() function in app.js file so that the function would call the corresponding view by passing this image as a POST argument.
Below is my index.html file.
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<!-- Include Angular and several angular libraries -->
<script src="node_modules/angular/angular.min.js"></script>
<script src="node_modules/angular-resource/angular-resource.min.js"></script>
<!-- Include our app -->
<script src="js/app.js"></script>
<!-- Include our own controllers, factories, directives, etc... -->
<script src="js/filesModelDirective.js"></script>
<script src="js/images.rest.js"></script>
<!-- Include Bootstrap CSS -->
<link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css">
</head>
<body>
<!-- Main Division -->
<div class="container-fluid">
<div ng-app="imageuploadFrontendApp" ng-controller="MainCtrl">
<!-- Panel for Uploading a new Image -->
<div class="panel panel-default">
<div class="panel-body">
<form class="form" name="form" ng-submit="uploadImage()">
<label for="inputFile">Select Image:</label>
<input id="inputFile" type="file" files-model="newImage.image">
<br />
<button class="btn btn-default" type="submit">
Upload
</button>
<br />
</form>
</div>
</div>
<div ng-if="images.length == 0">
There are no images available yet.
</div>
<div class="row">
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-4" ng-repeat="image in images track by image.pk">
<h3>
Image {{ image.pk }}
<button class="btn btn-warning" ng-click="deleteImage(image)">Delete</button>
<button class="btn btn-primary" ng-click="segmentImage(image)">Segment</button>
</h3>
<a href="{{ image.image }}">
<img class="img-responsive" ng-src="{{ image.image }}">
</a>
</div>
</div>
</div>
</div>
</body>
</html>
Below is my app.js file:
// create a module called imageuploadFrontendApp, which relies on ngResource
var myApp = angular.module('imageuploadFrontendApp', ['ngResource']);
// Configure ngResource to always use trailing slashes (required for django)
myApp.config(function($resourceProvider) {
$resourceProvider.defaults.stripTrailingSlashes = false;
});
// Main Controller
myApp.controller('MainCtrl', function($scope, Images)
{
console.log('In main Control');
$scope.images = Images.query();
$scope.newImage = {};
$scope.uploadImage = function()
{
// call REST API endpoint
Images.save($scope.newImage).$promise.then(
function(response) {
// the response is a valid image, put it at the front of the images array
$scope.images.unshift(response);
},
function(rejection) {
console.log('Failed to upload image');
console.log(rejection);
}
);
};
$scope.deleteImage = function(image)
{
image.$delete(
function(response)
{
// success delete
console.log('Deleted it');
// update $scope.images
$scope.images = Images.query();
},
function(rejection)
{
console.log('Failed to delete image');
console.log(rejection);
}
);
};
});
You can try some thing like this
Define a url for your view function
urls.py
url(r'^image/script_function/$', script_function, name="script_function")
Write the view for the url script_function
views.py
def script_function(info):
...
'''here goes my mian logic to process the image.'''
...
return x,y,w,h
app.js
$scope.segmentImage = function(image){
$http({method:'POST', url:'https://127.0.0.1/image/script_function/', data:{'image': image}}).
then(function successCallback(response) {
console.log('Image Posted successfully')
},function errorCallback(response) {
console.log('Image Post failed')
}
});
};
Pass the image to the sever via post and process your image.
Is it possible to include the following in my django html file?
<!-- Hit template -->
<script type="text/template" id="hit-template">
<div class="hit media">
<a class="pull-left" href="{{ url }}">
<img class="media-object" src="{{ image }}" alt="{{ name }}">
</a>
<div class="media-body">
<h3 class="hit_price pull-right text-right text-danger">
${{ salePrice }}
</h3>
<h4 class="hit_name">{{{ _highlightResult.name.value }}}</h4>
<p>
{{{ _highlightResult.shortDescription.value }}}
</p>
<ul class="hit_tags list-inline">
{{#_highlightResult.manufacturer}}<li>{{{ _highlightResult.manufacturer.value }}}</li>{{/_highlightResult.manufacturer}}
{{#_highlightResult.category}}<li>{{{ _highlightResult.category.value }}}</li>{{/_highlightResult.category}}
{{#type}}<li>{{{ type }}}</li>{{/type}}
</ul>
</div>
</div>
</script>
When I currently include that I get a django error, as django templating engine seems to be trying to parse it first.
If you're running django >= 1.5, try the verbatim template tag.
[edit]
on earlier versions of django, you should be able to replicate the template tag functionality yourself with the following:
"""
From https://gist.github.com/1313862
"""
from django import template
register = template.Library()
class VerbatimNode(template.Node):
def __init__(self, text):
self.text = text
def render(self, context):
return self.text
#register.tag
def verbatim(parser, token):
text = []
while 1:
token = parser.tokens.pop(0)
if token.contents == 'endverbatim':
break
if token.token_type == template.TOKEN_VAR:
text.append('{{')
elif token.token_type == template.TOKEN_BLOCK:
text.append('{%')
text.append(token.contents)
if token.token_type == template.TOKEN_VAR:
text.append('}}')
elif token.token_type == template.TOKEN_BLOCK:
text.append('%}')
return VerbatimNode(''.join(text))