How to solve problem "Must be a valid json" - Django + Vue js - django

I try to create object in Django with vue js + axios but somehowe this not work for me. I try in two ways and always I see in vue dev tools empty data. When I fill the data model in vuedev tools I see "Invalid value "Must be a valid Json"".
First way. I create a view that return jsonresponse.
#login_required
def save_embed(request):
if request.method == "POST":
form = SubmitEmbed(request.POST)
if form.is_valid():
url = form.cleaned_data['url']
r = requests.get('http://iframe.ly/api/oembed?url='+ url + '&api_key=' + IFRAMELYKEY)
data = r.json()
serializer = EmbedSerializer(data=data, context={'request': request})
if serializer.is_valid():
embed = serializer.save()
return JsonResponse(serializer.data, status=201, content_type="application/json", safe=False)
return JsonResponse(serializer.errors, status=400)
else:
form = SubmitEmbed()
return render(request, 'embed/embedadd.html', {'form': form})
Template:
<script>
new Vue({
el: '#app',
delimiters: ['!!', '!!'],
data () {
return {
url: "http://example.com"
}
},
methods: {
formSubmit(e) {
e.preventDefault();
let currentObj = this;
this.axios.post('http://wege.local:8000/recipes/recipe/embed/add/', {
url: this.url,
})
.then(function (response) {
currentObj.output = response.data;
})
.catch(function (error) {
currentObj.output = error;
});
}
}
});
</script>
Form:
<div id="app">
!! url.title !!
<form method="post" class="margin-bottom-25" #submit="formSubmit">
{% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-success-gradiant">Dodaj link</button>
</form>
</div>
In the url field has been added v-model "url".
as you can see in the screenshot below, when I fill in the url field, nothing happend
Second way is to create endpoint with rest framework in Django and then create templateview with code:
<div id="app">
<form method="post" class="margin-bottom-25" #submit="formSubmit">
{% csrf_token %}
<div class="form-group">
<label for="formGroupExampleInput">Adres przepisu*</label>
<input type="url" class="form-control" id="formGroupExampleInput" placeholder="Url" v-model="embed.url">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Tytuł</label>
<input class="form-control" id="formGroupExampleInput2" placeholder="Title" v-model="embed.title">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Description</label>
<input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Description" v-model="embed.description">
</div>
<div class="form-group">
<label for="formGroupExampleInput2">Thumbnail_url</label>
<input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Tthumbnail_url" v-model="embed.thumbnail_url">
</div>
<button type="submit" class="btn btn-success-gradiant">Dodaj link</button>
</form>
!! embed.title !!
!! embed.url !!
</div>
Vue js:
<script>
new Vue({
el: '#app',
delimiters: ['!!', '!!'],
data () {
return {
embed:{
url: 'http://example.com',
title: '',
description: '',
thumbnail_url: '',
}
}
},
methods: {
formSubmit(e) {
e.preventDefault();
let currentObj = this;
this.axios.post('http://wege.local:8000/recipes/embeds/', this.embed)
.then(function (response) {
currentObj.output = response.data;
})
.catch(function (error) {
currentObj.output = error;
});
}
}
});
</script>
In the second case the same problem, in vue tools the fields are still empty after completing the form.

I think your response is okay.
When/where do you define or gloabally bind axios to this? You keep trying this.axios, which does not exist. More on Vue instance properties here.
Unless I'm missing where you bind this.axios...
You need to import axios from "axios"; and do axios.post(...)
To see if your request is going out, try looking at the network tab in dev tools and see the requests that go out with the data! I see you're using firefox, check out the docs here

Related

got problem in the ajax form submission code

<form action="" method="post" class="f-color" id="email-form">
{% csrf_token %}
<label>Name</label>
<input type="text">
<label>From</label>
<input type="email">
<label>Message</label>
<button type="submit">Sent</button>
</form>
<div class="mt-5" id="spin" style="display: none;">
<div class="loader"></div>
</div>
<div id="msg"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).on("submit", "#email-form", function(event){
event.preventDefault();
$('#spin').show();
$.ajax({
url: "{% url 'contact' %}",
type: "POST",
data: $("#email-form").serialize(),
success: function(data){
$("#spin").hide();
if(data.status == "success"){
$("#msg").html("<p class='alert alert-success'>we will get back to you as soon as possible</p>" );
$("#email-form").reset();
}
}
})
})
})
</script>
using this code I can submit the form successfully, but after the form submission the message(msg) not showing, the 'if condition statement' is perfectly working (for the testing I gave the alert, the alert was worked)
another problem is form reset, for this I'm using
$("#email-form").reset();
but the form dose't reset
how can I solve these problems
try
$('#email-form')[0].reset();
https://stackoverflow.com/a/3786702/8640027
I got a solution for the resetting form after the ajax form submission
$("#email-form").trigger("reset");

Django - POST method not working for those forms created within a FOR loop in template

I'm using a for loop in a template to create multiple forms with method="post" that work with Ajax. But only the form for the first element of items_list works fine, the rest do not work at all showing error 405 0 Method Not Allowed. I think they all should work the same way. And just wondering if this issue was caused by a for loop or something else.
cart_items.html:
<script>
$(document).ready(function () {
$("#remove").click(function (event) {
event.preventDefault();
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {bookID: $('#idInput').val()},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% for book in items_list %}
<div class="items">
<p id="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
{% csrf_token %}
<input id="idInput" value="{{ book.book.id }}" >
<button id="remove" type="submit"> Remove</button>
</form>
</div>
{% endfor %}
The code in the function body below is just for testing. Once the first form works, I guess the problem was not caused by the function view.
cart/views.py:
#csrf_exempt
def remove_books(request):
cart = Cart.objects.get(user=request.user)
if request.method == 'POST':
passed_id = request.POST['bookID']
secured_id = int(passed_id)
response_data = {
'quantity': secured_id
}
return JsonResponse(response_data)
<script>
$(document).ready(function () {
$(".remove").click(function (event) {
// event.preventDefault(); // don't think it should be required with button type=button
var book_id = $(this).parent().find('.idInput').val(); // find correct input box.
var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // get csrf token in variable.
// there are multiple ways to get csrf token, I personally like this ^^, see https://docs.djangoproject.com/en/2.1/ref/csrf/#ajax for more
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {
bookID: book_id,
csrfmiddlewaretoken: csrf // add csrf token to post data
},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% csrf_token %} <!-- It will render a hidden input field with csrf token in it. Keep it outside for loop but in html. No need to render exactly same element multiple times. -->
{% for book in items_list %}
<div class="items">
<p class="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
<input class="idInput" value="{{ book.book.id }}" > <!-- use class not id -->
<button class="remove" type="button"> Remove</button> <!-- you can use button type=button to avoid form submit and hence avoid event.preventDefault(); in js -->
</form>
</div>
{% endfor %}

Does Making an AJAX call make a DJANGO form Invalid?

I make an ajax call to my server using the change event on a select widget. Does this cause the Django Form to be invalid? Here is an example of the code.
JAVASCRIPT
<form class="form-horizontal" action="{% url 'accountSelections' %}" method="post">
{% csrf_token %}
<div class="form-group">
<div class="row">
<div class="col-md-4">
{{ account_selection_form|crispy }}
<input class="btn btn-primary" id="button" type="Submit" value="Next >>">
</div>
<div class="col-md-4">
</div>
<div class="col-md-4">
<div id="grid"></div>
</div>
</div>
</div>
</form>`
$( document ).ready(function() {
$("#id_excludeClassification").SumoSelect();
var token = $('input[name="csrfmiddlewaretoken"]').prop('value');
$( "#id_acctFilterName" ).change(function() {
var data = "";
$.ajax({
type:"GET",
url : "../filter",
data : "id="+$(this).val(),
csrfmiddlewaretoken: token,
success : function(response) {
$("#grid").kendoGrid({
data: response,
height: 550,
groupable: true,
sortable: true,
columns: [
{
field: "acctCd",
title: "Code"
}, {
field: "shortName",
title: "Account Name"
}]
});
var grid = $("#grid").data("kendoGrid");
dataSource = new kendo.data.DataSource({
data: response
});
grid.dataSource = dataSource;
dataSource.read();
grid.refresh();
data = response;
return response;
},
error: function() {
alert('Error occured');
}
});
});
});
Does a form submit after cause this to make the form invalid?
My understanding is that you can submit multiple times with the same CSRF token, so it shouldn't be a problem.
you put your csrfmiddlewaretoken variable out data object that you send to your server then it can't work.
Here is what you have to do :
data : {
id : $(this).val(),
csrfmiddlewaretoken: token,
}

updating template with response in Ember after create/update action

I am working on a simple CRUD app using ember js. I have a template with a input form which sends data to the server and server responds with success response.
input form data: "user": {"id": 1, "name": "John"};
server response: {"message":"Created successfully", "nextId": 2}.
I want to display the success message on the same template(one with the input form). Because template refers to the user model and user model does not have a message attribute. How can it be done? Please help.
Here is my code:
var Manager = Ember.Application.create();
Manager.Router.map(function() {
this.resource('users');
this.resource('user', {path: '/users/:user_id'});
this.resource('home', {path: '/'});
});
Manager.UserRoute = Ember.Route.extend({
model: function(params) {
return jQuery.getJSON("http://localhost:8085/users/"+ params.user_id);
},
actions :{
insert : function(){
var user = this.modelFor("User");
$.ajax({
url: "http://localhost:8085/Users",
data: JSON.stringify(user),
type: "POST",
contentType: "application/json",
})
.done(function(data){
//set data.message to display on UI
})
}
}
});
and my template looks like this:
<script type="text/x-handlebars" data-template-name="user">
<form class="form-horizontal" role="form" {{action "insert" on="submit"}}>
<div class="form-group">
<label for="userId" class="control-label col-xs-2">User Id</label>
<div class="col-xs-4 input-group">
{{input type="number" value=_id class="form-control" id="userId" placeholder="Identity"}}
</div>
</div>
<div class="form-group">
<label for="name" class="control-label col-xs-2">Name</label>
<div class="col-xs-4 input-group">
{{input type="text" value=name class="form-control" id="name" placeholder="Name"}}
</div>
</div>
{{#if message}}
<div class="alert alert-success input-group" role="alert">{{message}}</div>
{{/if}}
<div class="form-group button-center">
<button type="submit" class="btn btn-default">Submit</button>
</div>
</form>
</script>
Set the message property on your controller to the response that comes back.
actions :{
insert : function(){
var user = this.modelFor("User");
var self = this;
$.ajax({
url: "http://localhost:8085/Users",
data: JSON.stringify(user),
type: "POST",
contentType: "application/json",
})
.done(function(data){
//set data.message to display on UI
self.controllerFor('user').set('message', data.message);
})
}
}

Having trouble submitting my form using Dojo

I am using Django 1.5 and Dojo 1.8. I am trying to get Dojo to submit a form back to a Django view when I click a button.
Here is my Django view:
def report(request, report_id, report_url=None, template='report_parameters.html'):
if request.method == 'POST':
form = ReportParametersForm(request.POST)
if form.is_valid():
report_params = form.save()
html = "Success!"
return HttpResponse(html)
else:
form = ReportParametersForm()
return render(request,template, {
'form': form,
'report_url': report_url,
'report_id': report_id,
})
Here is the html page:
<div id="report_body">
<form data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<p><button id="submit_parameters" dojoType="dijit.form.Button" type="submit">Submit</button></p>
</form>
</div>
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
e.preventDefault();
require(["dojo/dom", "dojo/request", "dojo/dom-form"], function(dom, request, domForm){
on(dom.byId("submit_parameters"), "click", function() {
console.log("Dojo Post");
request.xhr("/report_parameters/report_id/report_url/", {
method: "post",
handleAs: "json",
data: domForm.toJson("parameters_form"),
}).then(
function(response){
alert(response);
dom.byId("report_body").innerHTML = "Report!";
},
function(error){
dom.byId("report_body").innerHTML = "<div class=\"error\">"+error+"<div>";
}
);
});
});
</script>
When I click the Submit button, I want to send a POST request to the url passing the data I have in my form. However, right now when I click Submit, the page reloads with a url looking something like this: /?csrfmiddlewaretoken=Y9gaNMFRWZNXMbJ2L3Ev7A5iKPGTuWeF&param_1=0&param2=0/report_parameters/report_id/report_url/.
I don't see the Dojo Post that should be appearing in my console.
How do I get my form to submit?
This fiddle seems to do what you want.
The major differences seem to be:
The <form> is actually a <div>. The Dojo documentation for Form links to reasons why this is done for IE.
All the related event script is inside the form <div>.
Remove the on(dom.byId("submit_parameters")... code, as there's already a declarative submit event handler.
HTML code:
<div id="report_body"></div>
<div data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form" encType="multipart/form-data" action="" method="">
<input name="dummy" value="dummy">
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
console.log("submit");
e.preventDefault();
require(["dojo/dom", "dojo/request/xhr", "dojo/dom-form"], function(dom, xhr, domForm) {
console.log("Dojo Post");
var url = "/report_parameters/report_id/report_url/";
var data = domForm.toJson("parameters_form");
// overwrite url and data for jsfiddle
url = "/echo/json/";
data = {
json: data
};
xhr(url, {
method: "post",
handleAs: "json",
data: data,
}).then(function(response) {
alert(JSON.stringify(response, null, 2));
dom.byId("report_body").innerHTML = "Report!";
}, function(error) {
dom.byId("report_body").innerHTML = "<div class=\"error\">" + error + "<div>";
});
});
</script>
<button data-dojo-type="dijit/form/Button" id="submit_button" type="submit" name="submitButton" value="Submit">Submit</button>
</div>
JS code:
require(["dojo/parser", "dijit/registry", "dijit/form/Form", "dijit/form/Button", "dijit/form/ValidationTextBox", "dijit/form/DateTextBox", "dojo/domReady!"], function (parser, registry) {
parser.parse().then(function () {
console.log("parsed");
console.log(registry.byId("parameters_form"));
console.log(registry.byId("submit_button"));
});
});
I had to modify the above slightly. This is what eventually worked for me:
<div id="report_body"></div>
<form data-dojo-type="dijit/form/Form" id="parameters_form" data-dojo-id="parameters_form" encType="multipart/form-data" action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<script type="dojo/on" data-dojo-event="submit" data-dojo-args="e">
e.preventDefault();
require(["dojo/dom", "dojo/request/xhr", "dojo/dom-form"], function(dom, xhr, domForm){
var url = "/report_parameters/report_id/report_url/"
var data = domForm.toObject("parameters_form")
xhr(url, {
method: "post",
data: data,
}).then(
function(response){
alert(response);
dom.byId("report_body").innerHTML = "Report!";
},
function(error){
dom.byId("report_body").innerHTML = error;
}
);
});
</script>
<p><button id="submit_parameters" dojoType="dijit/form/Button" type="submit" name="submitButton" value="Submit">Submit</button></p>
</form>
Using either the <div> or <form> tags to wrap the whole thing worked for me.