I am trying to auto-populate one field of a Django form based on the query response of an entry into another field. I would like to do so before the form is submitted, displaying the autopopulated value in the field and maintain the user's ability to edit.
(Example, I type 'a handful of bananas' into the name field, when that field blurs it queries the api and fills the carbs field with the # of carbs a handful of bananas has)
Right now I have the ajax function to query:
$('#recipe-query').on('blur', function(event){
event.preventDefault();
console.log("blur")
query_macros();
});
function query_macros(){
var dataStr = "APIKEYREDACTED"
var ingredParam = encodeURI($('#recipe-query').val())
dataStr = dataStr + ingredParam
if($('#recipe-query').val() && $('#should-query').val()){
$.ajax({
url: "https://api.edamam.com/api/nutrition-data",
data: dataStr,
type: "GET",
dataType: "json",
success : function(json){
console.log(json);
console.log(json.totalNutrients.CHOCDF.quantity)
$('#carbs-query').value = json.totalNutrients.CHOCDF.quantity;
},
error : function(xhr, errmsg, err){
console.log(xhr.status + ": " + xhr.responseText);
}
});
}
}
this is the form
class NutritionForm(forms.ModelForm):
class Meta:
model = Nutrition
fields = ('food_name', 'autofill_macros', 'grams_of_fat',
'grams_of_protein', 'grams_of_carbs', 'date')
widgets = {
'food_name': forms.TextInput(attrs={
'id': 'recipe-query'
}),
'autofill_macros': forms.CheckboxInput(attrs={
'id': 'should-query'
}),
'grams_of_fat': forms.TextInput(attrs={
'id': 'fat-query'
}),
'grams_of_protein': forms.TextInput(attrs={
'id': 'protein-query'
}),
'grams_of_carbs': forms.TextInput(attrs={
'id': 'carbs-query'
})
}
and model
class Nutrition(models.Model):
food_name = models.CharField(max_length=50)
autofill_macros = models.BooleanField()
grams_of_protein = models.PositiveSmallIntegerField()
grams_of_carbs = models.PositiveSmallIntegerField()
grams_of_fat = models.PositiveSmallIntegerField()
calories = models.PositiveSmallIntegerField()
date = models.DateField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
but the #carbs-query field is not updated. How do I use the result of the API call to populate the other field while maintaining its editability (all before form submit).
It seems like js code have some issues. you can try below method of jQuery to set value:
$('#carbs-query').val(json.totalNutrients.CHOCDF.quantity);
Full code:
function query_macros(){
var dataStr = "APIKEYREDACTED"
var ingredParam = encodeURI($('#recipe-query').val())
dataStr = dataStr + ingredParam
if($('#recipe-query').val() && $('#should-query').val()){
$.ajax({
url: "https://api.edamam.com/api/nutrition-data",
data: dataStr,
type: "GET",
dataType: "json",
success : function(json){
console.log(json);
console.log(json.totalNutrients.CHOCDF.quantity)
$('#carbs-query').val(json.totalNutrients.CHOCDF.quantity);
},
error : function(xhr, errmsg, err){
console.log(xhr.status + ": " + xhr.responseText);
}
});
}
}
Related
I am trying to use Nuxt 3 as a server to pass through API requests. I would like to make FormData requests to a Django DRF API through my Nuxt server to POST data and images.
basically, the usecase is filling a simple form with data and images and send the formdata to a django backend. Here are more details.
In pages.vue:
const taskData = reactive({
title: '',
city: '',
description: '',
category: route.params.cat_slug,
subCat: '',
image_1: [],
image_2: [],
image_3: []
})
const submitTaskForm = async () => {
let formData = new FormData()
formData.append('title', taskData.title)
formData.append('city', taskData.city)
formData.append('description', taskData.description)
formData.append('category', taskData.category)
formData.append('subCat', taskData.subCat)
taskData.image_1.forEach((fileItem) => {
formData.append('image_1', fileItem.file)
})
taskData.image_2.forEach((fileItem) => {
formData.append('image_2', fileItem.file)
})
taskData.image_3.forEach((fileItem) => {
formData.append('image_3', fileItem.file)
})
const data = await useFetch('/api/tasks/add/', {
method: 'POST',
body: formData
})
return data
}
in /server/api/add.post.ts
export default defineEventHandler(async (event) => {
const body = await readBody(event)
const access = getCookie(event, 'access') || null
try {
const data = await $fetch(process.env.API_BASE_URL + "/api/tasks/add/", {
method: "POST",
body: body,
headers: {
Authorization: "Bearer " + access,
},
})
return data
} catch (error) {
console.log(error);
return error
}
})
now the backend part with the view handling the form:
class TasksCreate(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = TasksSerializer
parser_classes = [MultiPartParser, FormParser]
def post(self, request):
data = self.request.data
title = data['title']
city = data['city']
description = data['description']
category_slug = data['category']
subCat = data['subCat']
image_1 = request.FILES.get('image_1', "")
image_2 = request.FILES.get('image_2', "")
image_3 = request.FILES.get('image_3', "")
try:
if not Subcategories.objects.filter(slug=subCat, category__slug=category_slug).exists():
return Response(
{'error': 'The subcategory does not correspond to the category.', },
status=status.HTTP_400_BAD_REQUEST
)
task = Task.objects.create(
title=title,
city=city,
description=description,
slug='%s-%s' % (slugify(title), randint(1000, 10000)),
category=get_object_or_404(Category, slug=category_slug),
sub_category = get_object_or_404(Subcategories, slug=subCat),
created_by=request.user,
image_1=image_1,
image_2=image_2,
image_3=image_3,
)
task.save()
return Response(
{'task': 'Task created successfully', },
status=status.HTTP_201_CREATED
)
except Exception as e:
print(e)
return Response(
{'error': 'Something went wrong when creating the task'},
status=status.HTTP_500_INTERNAL_SERVER_ERROR
)
the error: Unsupported Media Type: /api/tasks/add/
I have tried with readBody readRawBody readMultipartFormData and also adding "Content-Type": "multipart/form-data" to headers.
Also, hitting directly the view with Postman work perfectly so my guess it's nuxt 3 not sending correctly the form.
I'm trying to validate a field while typing based on another question (How to validate django form field while it is typing?).
The js doesn't cal validation view
form
{{ form.num }}
<p id="validate_number" class="help is-danger is-hidden ">nome já utilizado</p>
js
<script>
$('#id_num').on('input', function () {
var id_number = $(this).val();
$.ajax({
url: '{% url 'validate-num' %}',
data: {
'num': id_number
},
dataType: 'json',
success: function (data) {
if (data.is_taken) {
$("#validate_number").show();
document.getElementById('id_num').style.borderColor = "red";
document.getElementById("submit_change").disabled = true;
}
else {
$("#validate_number").hide();
document.getElementById('id_num').style.borderColor = "#e7e7e7";
document.getElementById("submit_change").disabled = false;
}
}
});
});
</script>
url.py
urlpatterns = [
# ...
path('validatenum/', validate_inventory_number, name='validate-num'),
# ...
]
view
def validate_inventory_number(request):
number = request.GET.get('num', None)
data = {
'is_taken': InventoryNumber.objects.filter(num=number).exists()
}
return JsonResponse(data)
I created a checkbox in each row of the table. After selecting multiple check boxes, click the Add Teacher button to add the currently logged in user name (request.user.first_name) to the 'teacher' field of the checked row. I succeeded in getting the id to the page with the table using ajax, but it keeps failing to add the field value of obejct(teacher field) at once. view.py needs to be edited, does anyone know how to fix it?
[urls.py]
path('/study/add_teacher/', views.add_teacher, name='add_teacher'),
path('/study/student/', views.student), ----> page with table
[views.py]
def add_teacher(request):
if request.method == 'POST':
ids = request.POST.getlist('chkArray')
for id in ids:
student = Student.objects.get(pk=id)
student.teacher = request.user.first_name
student.save()
return HttpResponseRedirect(f'/study/student/') ----> page with table
[stduent.js]
$(function () {
('button.addteacher').on('click',function () {
$checkbox = $('.Checked');
var chkArray = [];
var updateTeacher = confirm("업데이트하시겠습니까?");
chkArray = $.map($checkbox, function(el){
if(el.checked) { return el.id };
});
var csrftoken = $('[name="csrfmiddlewaretoken"]').val();
$.ajax({
type:'post',
url: '/study/add_teacher/',
headers: {"X-CSRFTOKEN": "{{ csrf_token }}"},
data:{
"chkArray" : chkArray.toString(),
"csrfmiddlewaretoken": "{{ csrf_token }}",
},
success:function(data){
console.log(chkArray);
},
error : function(xhr,errmsg,err) {
console.log(xhr.status + ": " + xhr.responseText);
}
});
});
});
When i send data from ajax to view in Django I am getting none in data. What seems to be the problem. Here is mycode. Where as if i remove processData: false, contentType: false, then data is printed successfully but on file it gives error.
Ajax code
<script>
function submit_data()
{
var type = $('#type').val();
var subtype = $('#subtype').val();
var name = $('#name').val();
var price = $('#price').val();
var weight = $('#weight').val();
var details = $('#details').val();
var picture1 = $('#image1')[0].files[0];
var picture2 = $('#image2')[0].files[0];
var picture3 = $('#image3')[0].files[0];
var vedio_url = $('#vedio_link').val();
alert(picture1)
$.ajax({
url: '/add_record/',
type: 'POST',
headers: { "X-CSRFToken": '{{csrf_token}}' },
processData: false,
contentType: false,
data: {
type,
subtype,
name,
price,
weight,
details,
picture1,
picture2,
picture3,
vedio_url,
},
success: function (response) {
alert("datauploaded successfully!")
},
error: function(){
alert('error')
}
});
}
</script>
View code
def add_record(request):
print("Yes i am here")
type = request.POST.get('type')
subtype = request.POST.get('subtype')
name = request.POST.get('name')
price = request.POST.get('price')
weight = request.POST.get('weight')
details = request.POST.get('details')
picture1 = request.FILES.get('picture1')
picture2 = request.FILES.get('picture2')
picture3 = request.FILES.get('picture3')
vedi_url = request.POST.get('vedio_url')
print (picture1)
print(type)
print(request.POST)
return JsonResponse({'message':'success'},status=200)
Error:
Yes i am here
None
None
<QueryDict: {}>
its returning none, Why is that?
Ajax without files:
Your JS data element should be a dictionary, also remove processData and contentType parameters.
<!doctype html>
<html lang="en">
<head>
</head>
<body>
<input type="text" id="name"/>
<button type="button" id="send" onclick="submit_data()">Send<button/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.js" integrity="sha512-n/4gHW3atM3QqRcbCn6ewmpxcLAHGaDjpEBu4xZd47N0W2oQ+6q7oc3PXstrJYXcbNU1OHdQ1T7pAP+gi5Yu8g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
function submit_data()
{
var name = $('#name').val();
$.ajax({
url: '/add_record/',
type: 'POST',
headers: { "X-CSRFToken": '{{csrf_token}}' },
data: {
'name': name,
},
success: function (response) {
alert(response.data)
},
error: function(){
alert('error')
}
});
}
</script>
</body>
</html>
views:
from django.shortcuts import render
from django.http import JsonResponse
def form_record(request):
return render(request, "mytemplate.html", {})
def add_record(request):
print("Yes i am here")
name = request.POST.get('name')
print(f"Post: {request.POST}")
return JsonResponse({'data': name},status=200)
Ajax with files:
Because you are sending binary data you should to use FormData:
function submit_data()
{
var name = $('#name').val();
var formData = new FormData() // changes here
formData.append('name', name) // and here
$.ajax({
url: '/add_record/',
type: 'POST',
headers: { "X-CSRFToken": '{{csrf_token}}' },
contentType: false, // and here
enctype: 'multipart/form-data', // and here
processData: false, // and here
cache: false,
data: formData, // <-- carefully here
success: function (response) {
alert(response.data)
},
error: function(){
alert('error')
}
});
}
Result:
you can do with a lot of entries please because I have a more complex problem.
in my case I have 6 entries when I enter an entry I have an output in the form of a table and at the end I have to make a final request which will take into account the rows that I have selected.
Excuse my English.
my js :
function submit_data(){
list_fournisseurs = selectcheck();
list_entrepot = selectcheck1();
var numdoc = $('#numdoc').val();
var reference = $('#reference').val();
var reference_doc = $('#reference_doc').val();
var date_debut = $('#date_debut').val();
var date_fin = $('#date_fin').val();
var format_fournisseur = new FormData();
var format_entrepot = new FormData();
var format_numdoc = new FormData();
var format_reference = new FormData();
var format_reference_doc = new FormData();
var format_date_debut = new FormData();
var format_date_fin = new FormData();
const format = [
format_fournisseur.append('list_fournisseurs', list_fournisseurs),
format_entrepot.append('list_entrepot', list_entrepot),
format_numdoc .append('numdoc', numdoc),
format_reference.append('reference', reference),
format_reference_doc.append('reference_doc', reference_doc),
format_date_debut.append('date_debut', date_debut),
format_date_fin.append('date_fin', date_fin),
]
$.ajax({
type : 'POST',
url : 'fournisseur_ajax',
data : {
'csrfmiddlewaretoken': csrf,
'format' : format,
},
//processData: false,
success : (res) =>{
console.log('res.data',res.data)
},
error : (err) =>{
console.log(err)
},
})
}
my view
if request.method == "POST" :
check_list_fournisseurs = request.POST.getlist("format_fournisseur[]")
print("########## voici la liste ###########",check_list_fournisseurs)
check_list_entrepot = request.POST.getlist("format_entrepot[]")
print("########## voici la liste ###########",check_list_entrepot)
print("numdoc ",num_doc)
print("item_ref",item_ref)
print("item_doc",item_doc)
print("date_depart", date_debut)
print("date_fin",date_fin)
context ={'check_list_entrepot':check_list_entrepot,"check_list_fournisseurs":check_list_fournisseurs, 'num_doc':num_doc, 'item_ref':item_ref, 'item_doc':item_doc, 'date_debut':date_debut, 'date_fin':date_fin}
return render(request,"final.html",context)
I am trying to collect books in a shelf object. However when i try to add a book, the page does nothing and i get this error in my console "Uncaught (in promise) TypeError: Cannot read property 'push' of undefined". Need help with this.
main.js
function sendRequest(url,method,data) {
var r = axios({
method: method,
url: url,
data: data,
xsrfCookieName: 'csrftoken',
xsrfHeaderName: 'X-CSRFToken',
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
})
return r
}
var app = new Vue({
el : '#app',
data: {
book: '',
books: [
{title: 'one'},
{title: 'two'}
]
},
created(){
var vm = this;
var r = sendRequest('','get')
.then(function(response){
vm.books = response.data.books;
})
},
methods: {
createBook(){
var vm = this;
var formData = new FormData();
formData.append('title', this.book);
sendRequest('','post',formData)
.then(function (response) {
vm.books.push(response.data.book); //PROBLEM HERE
vm.book = '';
})
}
}
})
views.py
def add_book(request, shelf_id):
context = {}
if request.POST:
shelf = get_object_or_404(Shelf, pk=shelf_id)
book_form = BookCreation(request.POST)
temp = book_form.save(commit=False)
temp.shelf = shelf
temp.save()
if book_form.is_valid():
books = book_form.save()
return JsonResponse({'book': model_to_dict(books)},status=200)
return render(request, 'shelf/addBook.html')
url.py
path('<int:shelf_id>/create_book', add_book, name='addbook'),
Apparently the issue was with me using if request.POST instead of request.method =='POST' in my backend.
def add_book(request, shelf_id):
context = {}
if request.method == 'POST': //THIS IS WORKING CODE
shelf = get_object_or_404(Shelf, pk=shelf_id)
book_form = BookCreation(request.POST)
temp = book_form.save(commit=False)
temp.shelf = shelf
temp.save()
if book_form.is_valid():
books = book_form.save()
return JsonResponse({'book': model_to_dict(books)},status=200)
return render(request, 'shelf/addBook.html')