How to insert data to the database using Django and AJAX? - ajax

I have a simple webpage that allows the user to enter data using form.
I am using Django with Ajax in order to enter the new records into the database.
The problem is that once the user choose the webpage the system display the below error:
MultiValueDictKeyError at /addperson/ 'na'
Request Method: GET
Request URL: http://127.0.0.1:8000/addperson/
Django Version: 2.1.3
Exception Type: MultiValueDictKeyError
Exception Value: 'na'
Exception Location: C:\Users\LT GM\AppData\Local\Programs\Python\Python37\lib\site-packages\django\utils\datastructures.py in getitem, line 79
Python Executable: C:\Users\LT GM\AppData\Local\Programs\Python\Python37\python.exe
Python Version: 3.7.1
Python Path: ['C:\Users\LT ' 'GM\Downloads\Django-Related-DropDowns-master\Django-Related-DropDowns-master', 'C:\Users\LT GM\AppData\Local\Programs\Python\Python37\python37.zip', 'C:\Users\LT GM\AppData\Local\Programs\Python\Python37\DLLs', 'C:\Users\LT GM\AppData\Local\Programs\Python\Python37\lib', 'C:\Users\LT GM\AppData\Local\Programs\Python\Python37', 'C:\Users\LT ' 'GM\AppData\Local\Programs\Python\Python37\lib\site-packages']
Server time: Mon, 4 Mar 2019 07:10:33 +0000
models.py
class Person(models.Model):
boolChoice = (
("Male","M"),("Female","F")
)
name = models.CharField(max_length=50)
date = models.DateTimeField()
description = models.TextField()
gender = models.BooleanField(choices= boolChoice)
def __str__(self):
return str(self.name)
urls.py
from django.urls import path, include
from django.contrib import admin
from map import views as mapviews
admin.autodiscover()
urlpatterns = [
path('admin/', admin.site.urls),
path('', mapviews.index),
path('addperson/',mapviews.addperson),
]
addperson.html
{% extends 'base.html' %} {% block content %}
<div class="hero__content">
<form method="POST" class="form-style-9">
{% csrf_token %} {{ form.as_p }}
<ul>
<script
type="text/javascript"
src="http://code.jquery.com/jquery-latest.min.js"
></script>
<li>
{#
<input
type="number"
name="field1"
class="field-style field-split align-right"
placeholder="اﻟﺴﻨﺔ"
id="year"
/>
#} {#
<input
type="date"
name="field2"
class="field-style field-split align-left"
placeholder="اﻟﺘﺎﺭﻳﺦ"
id="date"
/>
#}
<h2>Add Member</h2>
</li>
<li>
<input
type="text"
name="name"
class="field-style field-split align-right"
placeholder="enter ur name "
id="name"
/>
</li>
<li>
<input
type="text"
name="date"
class="field-style field-full align-none"
placeholder=" your birthdate"
id="birthdate"
/>
</li>
<li>
<input type="radio" name="gender" id="male" value="male" /> Male<br />
<input type="radio" name="gender" id="female" value="female" />
Female<br />
</li>
<li>
<textarea
name="description"
class="field-style"
placeholder="introduce yourself "
id="description"
></textarea>
</li>
<li>
<input
type="submit"
class="field-style field-full align-none"
id="save"
value="ADD"
/>
<script type="text/javascript">
$(function() {
$("#save").on("click", function(e) {
e.preventDefault();
name = $("#name").val();
birthdate = $("#birthdate").val();
description = $("#description").val();
radioValue = $("input[name = 'gender']:checked").val();
alert("radioValue =", radioValue);
$.ajax({
url: "/create/te2chira",
method: "POST",
data: {
na: name,
bi: birthdate,
de: description,
ra: radioValue
},
headers: {
"X-CSRFToken": "{{csrf_token}}"
}
})
.done(function(msg) {
document.location = "/home.html";
alert("ﻟﻘﺪ ﺗﻢّ ﺣﻔﻆ اﻟﻤﻌﻠﻮﻣﺎﺕ");
})
.fail(function(err) {
alert("ﻟﻢ ﻳﺘﻢ اﻟﺤﻔﻆ");
});
});
});
</script>
</li>
</ul>
</form>
</div>
{% endblock %}
views.py
def addperson(request):
name = request.POST['na']
birthdate = request.POST['bi']
description=request.POST['de']
radiovalue=request.POST['ra']
person=Person.objects.create(
name=name,date=birthdate,description=description,
gender=radiovalue
)
person.save()
return render(request,'./home.html')

Note that your URL pattern ends in a slash, but the URL your using in the Ajax call doesn't.
What's happening is that Django is automatically redirecting you from
/addperson to /addperson/. But a redirect is always a GET, so all your data is lost and therequest. POST lookups fail.
The solution is simply to use /addperson/ in the Ajax call, although you probably want to make the view more robust in any case.

Fetch data using get method
def addperson(request):
data = request.POST
name = data.get('na', '')
birthdate = data.get('bi', '')
description= data.get('de', '')
radiovalue= data.get('ra', '')
person=Person.objects.create(
name=name,date=birthdate,description=description,
gender=radiovalue
)
person.save()
return render(request,'./home.html')

Related

Ajax function keeps messing up after inserting 24-25 records into the db

I have a multi select checkbox with 30-80 inputs, I wrote an Ajax code for this form, once checkbox is selected it sends records to the database.
Problem occurs after selecting 25th or 26th record, error is saying that value is duplicated, but every input's value is unique. and mentioned value in the error log is for the 1st selected checkbox.
What I want to achieve is, once a checkbox is clicked it should save it in the db, once the checkbox is unchecked, record should be removed from the database.
HTML:
<input type="checkbox" onClick="toggle(this)" /> Toggle All<br/>
#foreach ($counties as $county)
<li>
<input class="checkIt" type="checkbox" id="cnty_id" name="cnty_id"
value="{{ $county->id }}" #foreach($jct_fr_cnty as $jct) #if($jct->cnty_id == $county->id) checked #endif #endforeach>
{{ $county->county }}
</li>
#endforeach
Ajax:
$('.checkIt').bind('click', function() {
if($(this).is(":checked")) {
console.log("Checked");
$.ajax({
type: "POST",
url: '{{ url('company/assignment/interstate/cntys') }}',
data: $("#cntyselectform").serialize()
}).done(function( result ) {
console.log(result);
});
} else {
console.log("Unchecked");
$.ajax({
type: "DELETE",
url: '{{ url('company/assignment/interstate/cntysrem') }}',
data: $("#cntyselectform").serialize()
})
}
});
Controller
public function postcntyinterstate(Request $request)
{
jct_fr_cnty::create([
'cmp_id' => $request->cmp_id,
'cnty_id' => $request->cnty_id,
'svc_id' => $request->svc_id
]);
return response()->json(['success'=>'Data is successfully added']);
}
this is a code for toggle all button, which checks all the checkboxes and sends values to the db without any issue.
function toggle(source) {
checkboxes = document.getElementsByName('cnty_id');
for (var i = 0, n = checkboxes.length; i < n; i++) {
checkboxes[i].checked = source.checked;
console.log("Checked");
$.ajax({
type: "POST",
url: '{{ url('company/assignment/interstate/cntys') }}',
data: $("#cntyselectform").serialize()
}).done(function(result) {
console.log(result);
});
}
}
form code:
<form id="cntyselectform" method="POST"
action="{{ route('company.cntyinterstate', ['company' => $company->id]) }}">
#csrf
<div class="col-lg-12 mb-3 mt-3 mb-sm-0">
<h3>Please select counties</h3>
<div name="cntSelect[]" id="cntSelect">
<ul>
<input type="checkbox" onClick="toggle(this)" /> Toggle All<br />
#foreach ($counties as $county)
<li>
<input class="checkIt" type="checkbox" id="cnty_id" name="cnty_id"
value="{{ $county->id }}"
#foreach ($jct_fr_cnty as $jct) #if ($jct->cnty_id == $county->id) checked #endif #endforeach>
{{ $county->county }}
</li>
#endforeach
</ul>
</div>
<input type="hidden" value="{{ $company->id }}" name="cmp_id" id="cmp_id">
<input type="hidden" value="1" name="svc_id" id="svc_id">
{{-- <button id="cntyselect-button" type="submit" class="btn btn-primary">Submit</button> --}}
</div>
</form>
Database:
I understand the logic of. BUT it looks a little patchy. Let's fix it:
You absolutely should not have duplicate IDs. It may work, but it is semantically incorrect and you should not do it. (The id you specified in the loop in your code will be repeated in the document.) AND Get rid of unnecessary loops.
<input type="checkbox" onClick="toggle(this)" /> Toggle All<br/>
#php
$jct_fr_cnty_array = array_column($jct_fr_cnty->toArray(), 'cnty_id');
#endphp
#foreach ($counties as $county)
<li>
<input class="checkIt" type="checkbox" name="cnty_id"
value="{{ $county->id }}" #checked(in_array($county->id, $jct_fr_cnty_array))>
{{ $county->county }}
</li>
#endforeach
A few elements that could not be marked and triggered incorrectly due to repeated ids in the document and their values may have caused this error.
If you perform your deletion operation properly and if you provide correct checking/unchecking conditions in the relevant checkboxes, I think the error will be corrected when you apply this.

Unable to validate form with single field, with ajax post

I've been unable to find a solution to my problem from searching. So I'd like to ask what might be wrong with my code. I'm trying to validate a form from forms.ModelForm but in my views function it won't pass the form.is_valid(). printing form.errors gives me:
<li>title<ul class="errorlist"><li>This field is required.</li></ul>
Model:
class Paper(models.Model):
title = models.CharField(max_length=100, help_text='Hello World!')
forms.FormModel
class eventCreateForm(forms.ModelForm):
class Meta:
Model = Paper
fields = ['title']
widgets = {
'title': forms.TextInput(attrs={'class' :'form-control', 'placeholder' : 'Place title'}),
}
Views
def create_paper(request):
context = {}
if request.method == 'POST':
form = paperCreateForm(request.POST or None, request.FILES or None)
if form.is_valid():
form_data = form.cleaned_data
t1 = form_data['title']
print(t1)
else:
context['create_paper_form'] = form
form_template = "user/paper-event-template.html"
return HttpResponse(render_to_string(form_template, {'context' : context}))
The form dosen't get validated, and in the else clause it'll pass the error when trying to retrieve it from the cleaned_data
I did try and print the form, and it shows:
<tr><th><label for="id_title">Title:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input class="form-control" id="id_title" maxlength="100" name="title" placeholder="Place Title" type="text" required /></td></tr>
But it dosen't contain any value, which I guess it should: I use a jax method for sending the forms data:
ajax
$('#create_paper_form_id').submit(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "{% url 'Eapp:create_paper' %}",
data: {
csrfmiddlewaretoken : '{{ csrf_token }}',
form_data : $('#create_paper_form_id').serializeArray(),
},
success: function (data) {
console.log(data);
$('.create-paper').html(data);
},
error: function() {
console.log('err');
}
});
});
html
<div class="create-paper">
<div class="container-fluid">
<form class="form" id="create_paper_form_id" novalidate="novalidate" action="{% url 'Eapp:create_event' %}" method="POST">
{% for field in create_paper_form %}
<div class="form-group">
<div class="col-xs-12">
{{ field.label_tag }}
</div>
<div class="col-xs-12">
{{ field }}
</div>
<div class="col-xs-6">
{{ field.help_text }}
</div>
<div class="col-xs-6">
{{ field.errors }}
</div>
</div>
{% endfor %}
<div class="form-group">
<div class="col-xs-6 col-sm-6 col-md-2 col-lg-2">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</div>
</form>
</div>
</div>
That's expected behaviour, the cleaned_data is only available on a valid form when there's actually cleaned data available.
The form.data is still available though, you can use that.
To quote the manual:
A Form instance has an is_valid() method, which runs validation
routines for all its fields. When this method is called, if all fields
contain valid data, it will:
return True
place the form’s data in its cleaned_data attribute.
[edit] As #fazil-zaid mentioned, you need to include model in your Meta class for it to function as a modelform.

how to update 2 text fields on click of a search button in the same form by fetching data from Grails Controller using AJAX in Grails 2.1.0

I have a controller(SearchController) which fetches data on clicking a search button (inside myview.gsp) i want to populate 2 text fields present in the same myview.gsp with the data i have in my controller (SearchController) .I know i need to do ajax calling because i want to populate only 2 fields and dont want to reload the page which contains other valuable information . How can i achieve it please guide me
here is my Controller
def searchItem() {
def itemFound = MyService.searchP20Code(params["item"])
def resultMap = [:]
if (itemFound!=null)
{
resultMap.put("CODE",itemFound[1])
resultMap.put("DESC",itemFound[2])
}
println "Result:"+resultMap
session.setAttribute("searchResult", resultMap)
render(view: myview" )
}
myview.gsp
myview.gsp
<div class="leftPanel filter-label">
<a href="#" class="tt"> <g:message
code="Normal.label.Code" />
</a>
</div>
<div class="rightPanel filter-field-wrapper">
<input type="text"
name="Code" maxlength="30"
value=""
id="i_code" />
</div>
</div>
<div class="formLables">
<div class="leftPanel filter-label">
<a href="#" class="tt"> <g:message
code="Normal.label.Description" />
</a>
</div>
<div class="rightPanel filter-field-wrapper">
<input type="text"
name="Desc" maxlength="30"
onkeyup="fieldMaxlength('material_code')" value=""
id="i_description" />
</div>
</div>
<g:actionSubmit
value="${message(code:'Normal.button.search', default: 'Search Code')}"
action="searchItem" />
please help my how can i update only these two text fields in myview.gsp onclicking search button using ajax .I am using grails 2.1.0
Here you can find a detailed example with Grails build-in Ajax support.
You can also use JQuery (example here)
EDIT:
Your controller needs to look like this:
import grails.converters.JSON
class ExampleController {
....
def searchItem() {
def itemFound = MyService.searchP20Code(params["item"])
def resultMap = [:]
if (itemFound!=null) {
resultMap.put("CODE",itemFound[1])
resultMap.put("DESC",itemFound[2])
}
println "Result:"+resultMap
//session.setAttribute("searchResult", resultMap)
render(resultMap as JSON )
}
}
and your gsp
<head>
...
<g:javascript plugin="jquery" library="jquery" src="jquery/jquery-{WRITE_YOUR_VERSION_HERE}.js"/>
<script>
function callAjax(e){
e.preventDefault();
$.ajax({
url: "example/search",
type:"post",
dataType: 'json',
success: function(data) {
console.log(data);
$("input[name='Code']").val(data.CODE);
$("input[name='Desc']").val(data.DESC);
}
});
}
</script>
...
</head>
<body>
....
<input type="submit" value="Call Ajax Function" onclick="callAjax()">
....
</body>

Kendo UI - Datasource. pass parameters to server using mvvm

I'm having trouble using the datasource the right way.
My Goal: create external widget for filtering kendo grid (server side filter).
I managed to make it work, but it's kind of a workaround and I am looking for the corrent approach
The filterGrid function do all the work but it doesn't look right,
I want the parametermap function to do all the work but I can't figure it out.
Please advise.
this is how my view model looks like (I omitted the less important parts):
var viewModel = kendo.observable({
selectedInterface: null,
selectedStatus: null,
toHilanDate: new Date(),
updateDate: new Date(),
employeeId: null,
factoryId: null,
eventId:null,
employees: new kendo.data.DataSource({
transport: {
parameterMap: function (data, type) {
return { criteria: data };//for the mvc controller
},
read: {
url: "tohilan/Employees",
type: "post",
data: {}
}
}
}),
filterGrid: function () {
var data = {
SelectedInterface: this.selectedInterface ? this.selectedInterface.Id:null,
SelectedStatus: this.selectedStatus? this.selectedStatus.Key:null,
ToHilanDate: kendo.toString(kendo.parseDate(this.toHilanDate), "d"),
UpdateDate: kendo.toString(kendo.parseDate(this.updateDate), "d"),
EmployeeId: this.get("employeeId"),
FactoryId: this.get("factoryId"),
EventId: this.eventId,
};
//set new data into datasource
$('#employeeGrid').data('kendoGrid').dataSource.transport.options.read.data = data;
//refresh grid
$('#employeeGrid').data('kendoGrid').dataSource.read();
$('#employeeGrid').data('kendoGrid').refresh();
}
});
kendo.bind($("#employees-view"), viewModel);
My markup looks like this: (again, only the important part)
<ul>
<li>
<label for="employeeId">מספר עובד:</label>
<input type="number" id="employeeId" data-role="maskedtextbox" data-bind="value:employeeId"/>
</li>
<li>
<label for="eventId">מספר אירוע:</label>
<input type="number" id="eventId" data-role="maskedtextbox" data-bind="value:eventId"/>
</li>
<li>
<label for="factoryId">מספר מפעל:</label>
<input type="number" id="factoryId" data-role="maskedtextbox" data-bind="value:factoryId"/>
</li>
<li>
<label for="toHilanDate">תאריך העברה לחילן:</label>
<input type="date" id="toHilanDate" data-role="datepicker" data-bind="value:toHilanDate" />
</li>
<li>
<label for="updateDate">תאריך עדכון:</label>
<input type="date" id="updateDate" data-role="datepicker" data-bind="value:updateDate" />
</li>
<li>
<label for="event-status">סטטוס אירוע:</label>
<select id="event-status" data-role="dropdownlist" data-bind="value: selectedStatus, source: statusList" data-text-field="Value" data-value-field="Key" data-option-label=" "></select>
</li>
<li>
<label for="interface">ממשק:</label>
<select id="interface" data-role="dropdownlist" data-bind="value: selectedInterface, source: interfaceList" data-text-field="Description" data-value-field="Id" data-option-label=" "></select>
</li>
<li>
<button type="submit" data-role="button" data-bind="events: {click:filterGrid}">סנן</button>
</li>
</ul>
I guess I found an answer, maybe I had a typo or something.
I created the data object in the parametermap function instead of the filterGrid function. I just replaced "this" with viewModel. I still think that there is even better way to deal with it but at the moment it serve me just right.

ajax post no update in django template

I want to post some text in django with ajax,and save the input data,show the data in same page and no refresh,like twitter.
my js:
$('#SumbitButton').click(function(){
var data_1 = $('#data_1').val()
var data_2 = $('#data_2').val()
var data_3 = $('#data_3').val()
var data_4 = $('#data_4').val()
var user = $('#AuthorName').text()
var authorprotrait = $('#UserProprait').html()
if(data_1.length>0){
$.ajax({
type: 'POST',
url: '/post/',
data:{'data_1':data_1,'data_2':data_2,'data_3':data_3,'data_4':data_4},
async: false,
error: function(msg){alert('Fail')},
success: function(msg){
$('#TopicWrap').prepend("<div class='topic-all even'><div class='topic-left'><div class='topic-author'><div class='topic-author-protrait'>"+authorprotrait+"</div><div class='topic-author-nickname'>"+authorname+"</div></div></div><div class='topic-right'><div class='topic-meta'><span class='topic-datetime'></span></div><div class='topic-content-wrap'><div class='topic-content'>"+msg+"</div></div></div><div class='clearfix'></div></div>");
$('#data_1').val('');
$('#data_2').val('');
$('#data_3').val('');
$('#data_4').val('');
}
});
} else {
alert('The data_1's length error !'+data_1.length);
}
});
and the html:
<div id="TopicTextarea">
<div>
data1:<input tabindex="4" id="data_1" type="text" name="data1" value="" maxlength="6" placeholder=""/></br>
data2:<input tabindex="4" id="data_2" type="text" name="data2" value="" maxlength="8" placeholder=""/></br>
data3:<input tabindex="4" id="data_3" type="text" name="data3" value="" maxlength="10" placeholder=""/></br>
data4:<input tabindex="4" id="data_4" type="text" name="data4" value="" maxlength="10" placeholder=""/>
<div id="TopicFormControl">
<button type="button" id="SumbitButton" class="button orange">sumbit</button>
</div>
</div>
   <div class="clearfix"></div>
</div>
<div id="TopicWrap">
{% include 'topics.html'%}
</div>
and the views:
#login_required
def post(request):
assert(request.method=='POST' and request.is_ajax()==True)
data_1 = smart_unicode(request.POST['data_1'])
data_2 = smart_unicode(request.POST['data_2'])
data_3 = smart_unicode(request.POST['data_3'])
data_4 = smart_unicode(request.POST['data_4'])
data_obj = DataPool(user=request.user,data_1=data_1,data_2=data_2,data_3=data_3, data_4=data_4)
data_obj.save()
content = '"+data_3+"  "+data_4+" "+data_1+"("+data_2+")'
response = HttpResponse(cgi.escape(content))
return response
when I input the data and click the sumbit button,it can save the data ,but it can't show the data.what's wrong in my code?
thanks.
First, use something like Poster to test that your view is returning what you expect. Only then should you start building the AJAX part.
As for what's wrong... it's a bit difficult to say since you just write that it "can't show the data" instead of saying what it's actually doing. I suspect it has to do with this line in your view:
content = '"+data_3+"  "+data_4+" "+data_1+"("+data_2+")'
It's not really clear to me what you think this would do, but what it actually does is:
>>> '"+data_3+"  "+data_4+" "+data_1+"("+data_2+")'
'"+data_3+" \xe3\x80\x80"+data_4+"\xe3\x80\x80"+data_1+"("+data_2+")'
That is to say that it produces a string containing the substrings "data_3" (etc..) It does not include the submitted data.

Resources