form.html
<form>
{% csrf_token %}
<table>
<tr>
<td>
<label for="name">NAME: </label>
<input type="text" data-bind="value: $data.name" name="name" class="form-control" id="name" placeholder="name of product">
</td>
</tr>
<tr>
<td>
<label for="price">PRICE </label>
<input type="text" name="price" data-bind="value:$data.price" class="form-control" id="price" placeholder="price">
</td>
</tr>
<tr>
<td>
<label for="description">DESCRIPTION: </label>
<textarea cols="10" rows="5" name="description" data-bind="value:$data.description" class="form-control" id="description" placeholder="product description"></textarea>
</td>
</tr>
<tr>
<td>
<label for="image">IMAGE: </label>
<input type="file" class="form-control-file" id="image" name="image" required>
</td>
</tr>
<tr><td><button type="button" id="submit" data-bind="click : save" class="btn btn-success">Submit</button></td></tr>
</table>
</form></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min.js"></script>
<!-- <script type="application/javascript" src="static/js/knockout-file-bind.js"></script> -->
<script>
function getCookie(name) {
let cookieValue = null;
if (document.cookie && document.cookie !== '') {
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i++) {
const cookie = cookies[i].trim();
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
const csrftoken = getCookie('csrftoken');
</script>
<script>
var ViewModel = function () {
var self = this;
self.save = function () {
var formdata = new FormData();
formdata.append('image', $('#image').get(0).files[0]);
formdata.append('name', ko.observable(""));
formdata.append('price', ko.observable(""));
formdata.append('description', ko.observable(""));
console.log(formdata)
$.ajax({
type: 'POST',
url: "{% url 'addProduct' %}",
data: formdata,
headers: {'X-CSRFToken': csrftoken},
processData: false,
contentType: false,
success: function (){
alert('The post has been created!')
},
error: function () {
alert("fail");
}
});
};
};
ko.applyBindings(new ViewModel())
</script>
</body>
</html>
views.py
def productform(request):
return render(request, 'app/product_form.html')
class ProductCreateView(CreateView):
model = Product
fields = ['name', 'price', 'description', 'image']
success_url=reverse_lazy('create-form')
def addProduct(request):
if request.method == "POST":
product=Product()
product.name = request.POST['name']
product.description = request.POST['description']
product.price = request.POST['price']
if len(request.FILES) != 0:
if len(product.image) > 0:
os.remove(product.image.path)
product.image = request.FILES['image']
product.save()
return render(request, 'app/product_form.html')
else:
return render(request, 'app/product_form.html')
# def get_success_url(self):
# return reverse('successlist')
def detail_view(request, id):
context ={}
context["data"] = Product.objects.get(id = id)
return render(request, "detail_view.html", context)
Image is not saving in database django I don't know what is the issue but image file name is displaying in console.log in ajax. Issue is image is not saving to database
When i try to print(request.FILES) it shows multidict is empty
I have given html code views code please check
Please help me to solve this
Thanks in advance
in your form.html try adding
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
# the rest of your code
</form>
If you're using a formdata object in an $.ajax request you must set the data field to that formdata object.
Also all the fields must be in it, append all to fields into it when you're making the ajax request not before.
self.save = function () {
var formdata = new FormData();
formdata.append('image', $('#image').get(0).files[0]);
formdata.append('name', ko.observable(""));
formdata.append('price', ko.observable(""));
formdata.append('description', ko.observable(""));
$.ajax({
type: 'POST',
url: "{% url 'addProduct' %}",
data: formdata,
headers: {'X-CSRFToken': csrftoken},
processData: false,
contentType: false,
success: function (){
alert('The post has been created!')
},
error: function () {
alert("fail");
}
});
};
Related
I wanted to pass a file along with other text data from react to django and so I used the FormData() class and axios to post the request to DRF. The React code :
import React, { useEffect, useState } from "react";
import "../styling/AptitudeTest.css";
import Timer from "../components/Timer";
import { useNavigate, useLocation } from "react-router-dom";
import axios from "axios";
function AptitudeTest() {
const navigate = useNavigate();
const [lkdn, setLkdn] = useState("");
const [selectedFile, setSelectedFile] = useState();
const location = useLocation();
const [qs, setQs] = useState([]);
const onFileChange = (event) => {
setSelectedFile(event.target.files[0]);
};
useEffect(() => {
const data = async () =>
await axios
.get(`http://127.0.0.1:8000/comp/test/${location.state.id}`)
.then((res) => {
setQs(res.data.jsonData);
})
.catch((e) => console.log(e));
data();
}, []);
function submitHandler(e) {
e.preventDefault();
let c = 0,
total = 0;
var checkboxes = document.querySelectorAll("input[type=radio]:checked");
for (var i = 0; i < checkboxes.length; i++) {
c = c + parseInt(checkboxes[i].value);
total = total + 2;
}
let formData1 = new FormData();
formData1.append("Content-Type","multipart/form-data")
formData1.append(
"cid",
JSON.parse(localStorage.getItem("uData"))["cand_email"]
);
formData1.append("testid", location.state.id);
formData1.append("linkedin", "asasdads");
formData1.append("score", Math.ceil((c * 100) / total));
formData1.append("cv", selectedFile);
formData1.append("compid", location.state.compid);
axios
.post("http://localhost:8000/cand/response/",formData1)
.then((res) => {
navigate("/records2");
})
.catch((err) => {
console.log(err);
});
}
return (
<div className="container">
<h4 className="tit">J.P Stan and Co. - Data Analyst</h4>
<Timer hours="0" minutes="60" />
<form onSubmit={submitHandler}>
{qs.map((q) => {
return (
<div className="c card">
<div className="ch card-header">{q.question}</div>
<div className="card-body">
<input
type="radio"
id={"option1"}
name={q.question}
value={q.option1.marks}
/>
<label htmlFor={q.question}> {q.option1.title} </label>
</div>
<div className="card-body">
<input
type="radio"
id={"option2"}
name={q.question}
value={q.option2.marks}
/>
<label htmlFor={q.question}> {q.option2.title} </label>
</div>
<div className="card-body">
<input
type="radio"
id={"option3"}
name={q.question}
value={q.option3.marks}
/>
<label htmlFor={q.question}> {q.option3.title} </label>
</div>
<div className="card-body">
<input
type="radio"
id={"option4"}
name={q.question}
value={q.option4.marks}
/>
<label htmlFor={q.question}> {q.option4.title} </label>
</div>
</div>
);
})}
<div className="card">
<div className="card-header">Upload your CV.</div>
<div className="card-body">
<input name="cv" type="file" onChange={onFileChange} />
</div>
</div>
<div className="card">
<div className="card-header">Add your Linkedin.</div>
<div className="card-body">
<input
type="text"
name="op"
className="form-control"
id="op"
placeholder="https://www.linkedin.com/in/bhoomika-valani-695b22199/"
/>
</div>
</div>
<input
onClick={submitHandler}
type="submit"
value="Submit"
className="btn btn-primary btn-lg btn-block"
/>
</form>
</div>
);
}
export default AptitudeTest;
The request being sent is an XMLHTTPRequest which I cannot figure out how to parse it. The django code:
class ResponseAction(APIView):
parser_classes = [FormParser, MultiPartParser]
#csrf_exempt
def get(self, request, *args, **kwargs):
resp_objs = Response1.objects.filter(**request.data)
list0 = []
for resp_obj in resp_objs:
dict1 = model_to_dict(resp_obj)
candname = Candidate.objects.get(cand_email = resp_obj.cid)
dict1['cand_name'] = candname
list0.append(dict1)
return JsonResponse(list0,safe=False)
#csrf_exempt
def post(self, request, *args, **kwargs):
serializer1 = ResponseSerializer(data = request.data)
if serializer1.is_valid():
resp_obj = Response1.objects.filter(cid=request.data['cid'],testid=request.data['testid'])
if not resp_obj.exists():
serializer1.save()
print("stored")
else:
print(serializer1.errors)
return Response(serializer1.data)
When I tried printing the request.data the output is such
<QueryDict: {'------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name': ['"Content-Type"\r\n\r\nmultipart/form-data\r\n------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name="cid"\r\n\r\nb#gmail.com\r\n------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name="testid"\r\n\r\n1\r\n------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name="linkedin"\r\n\r\nasasdads\r\n------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name="score"\r\n\r\n0\r\n------WebKitFormBoundarywCHXwKecZPVgYxxN\r\nContent-Disposition: form-data; name="cv"; filename="zs.docx"\r\nContent-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document\r\n\r\nPK\x03\x04\x14\x00\x06\x00\x08\x00\x00\x00!\x002\x91oWf\x01\x00\x00¥\x05\x00\x00\x13\x00\x08\x02[Content_Types].xml ¢\x04\x02(\xa0\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00.....
.. represents more xml data. Can anyone help me or suggest me an alternative method to sent files and text from react to DRF. Thanks in advance
I have an user profile where he can crop his image, and so after cropping, and printing data in view nothing is passed to view
Form
<form method="post" action="change_photo/" id="avatar_changing_form">
{% csrf_token %}
<label for="upload_image">
{% if item.image%}
<img src="{{item.image.url}}" alt="" style="max-height:300px">
{%else%}
<img src="{%static 'avatar_sample.png' %}" id="uploaded_image"
class="img-responsive img-circle" />
{%endif%}
<div class="overlay">
<div class="text">Click to Change Profile Image</div>
</div>
<!-- <input type="file" name="image" class="image" id="upload_image" style="display:none" /> -->
{{imageForm.image}}
</label>
</form>
JS & Ajax
$(document).ready(function(){
const imageForm = document.getElementById('avatar_changing_form')
const confirmBtn = document.getElementById('crop')
const input = document.getElementById('upload_image')
const csrf = document.getElementsByName('csrfmiddlewaretoken')
var $modal = $('#modal');
var image = document.getElementById('sample_image');
var cropper;
$('#upload_image').change(function (event) {
var files = event.target.files;
var done = function (url) {
image.src = url;
$modal.modal('show');
};
if (files && files.length > 0) {
reader = new FileReader();
reader.onload = function (event) {
done(reader.result);
};
reader.readAsDataURL(files[0]);
}
});
$modal.on('shown.bs.modal', function () {
cropper = new Cropper(image, {
aspectRatio: 1,
viewMode: 3,
preview: '.preview'
});
}).on('hidden.bs.modal', function () {
cropper.destroy();
cropper = null;
});
$('#crop').click(function () {
cropper.getCroppedCanvas().toBlob((blob) => {
console.log('confirmed')
const fd = new FormData();
fd.append('csrfmiddlewaretoken', csrf[0].value)
fd.append('file', blob, 'my-image.png');
$.ajax({
type: 'POST',
url: imageForm.action,
enctype: 'multipart/form-data',
data: fd,
success: function (response) {
console.log('success', response)
$modal.modal('hide');
$('#uploaded_image').attr('src', fd);
},
error: function (error) {
console.log('error', error)
},
cache: false,
contentType: false,
processData: false,
})
});
});
})
View
def change_photo(request):
if request.user.is_authenticated and Guide.objects.filter(user = request.user).exists():
item = Guide.objects.get(user=request.user)
if request.method == "POST":
Photoform = ChangeImageForm(request.POST or None, request.FILES or None, instance = item)
if Photoform.is_valid():
print(Photoform.cleaned_data['image'])
Photoform.save()
return HttpResponseRedirect('/profile/')
form
class ChangeImageForm(ModelForm):
class Meta:
model = Guide
fields = ['image']
def __init__(self, *args, **kwargs):
super(ChangeImageForm, self).__init__(*args, **kwargs)
self.fields['image'].widget = FileInput(attrs={
'name':'image',
'class':'image',
'id':'upload_image',
'style':'display:none'
})
When i print image field from cleaned data in terminal displays "none", and when i load image through admin everything working good, can pls someone tell me where the problem is?
I build the comment system and when I click like in the first comment the like appears successfully but when I come to the next comment It returns the JSON response page {"a_c_like": true} instead of like appear and the like count in the span also didn't work (count). I build my comment system on the MPTTModel
my view
def add_like_to_comment(request, id):
comment = Comment.objects.get(id=id)
data = {}
if request.method == 'POST':
account = request.user
if comment.likes.filter(id=account.id).exists():
comment.likes.remove(account)
a_c_like = False
else:
comment.likes.add(account)
a_c_like = True
data["a_c_like"] = a_c_like
print(data)
return JsonResponse(data)
my urls
path('comment/like/<int:id>/like', add_like_to_comment, name='add_like_to_comment'),
the html template
<form method="POST" action="{% url 'video:add_like_to_comment' node.id %}" id="comment-like-form">
{% csrf_token %}
<button style="color: #aaaaaa;" class="remove-default-btn p-0 border-0 " type="submit" style="border: none; color: #aaaaaa;" >
<svg width="1.5em" height="1.5em" xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-heart" viewBox="0 0 16 16" >
<path d="M8 2.748l-.717-.737C5.6.281 2.514.878 1.4 3.053c-.523 1.023-.641 2.5.314 4.385.92 1.815 2.834 3.989 6.286 6.357 3.452-2.368 5.365-4.542 6.286-6.357.955-1.886.838-3.362.314-4.385C13.486.878 10.4.28 8.717 2.01L8 2.748zM8 15C-7.333 4.868 3.279-3.04 7.824 1.143c.06.055.119.112.176.171a3.12 3.12 0 0 1 .176-.17C12.72-3.042 23.333 4.867 8 15z"/>
<span class="ml-1" >{{ node.likes.all.count }}</span></svg>
</button>
</form>
Ajax file which handles the like comments
$("#comment-like-form").submit(function(e){
e.preventDefault();
var form = $(this);
let url = form.attr("action");
$.ajax({
type: "POST",
url: url,
data: form.serialize(),
dataType: "json",
success: function(response) {
var btn = form.find("button[type='submit']");
if (response.a_c_like) {
btn.css("color", "red");
} else {
btn.css("color", "#aaaaaa");
}
btn.find("span").text(response.count)
}
})
})
you are using "response.count" but you didn't pass the count value.
add data["count"] = comment.likes.count() in your views.py
example:
def add_like_to_comment(request, id):
comment = Comment.objects.get(id=id)
data = {}
if request.method == 'POST':
account = request.user
if comment.likes.filter(id=account.id).exists():
comment.likes.remove(account)
a_c_like = False
else:
comment.likes.add(account)
a_c_like = True
data["a_c_like"] = a_c_like
data["count"] = comment.likes.count()
print(data)
return JsonResponse(data)
I found difficult to change the color of the like button when the button hit and increase by +1 (in likes) in Django using ajax
my html template
<form method="POST" action="{% url 'video:like' video.pk %}" id="my-like-form">
{% csrf_token %}
<input type="hidden" class="likin" name="next" value="{{ request.path }}">
<button class="remove-default-btn" type="submit" id="openPopup" class="like-btn{{ request.path }}" style="border: none; ">
<i class="fa fa-thumbs-up" aria-hidden="true"><span>{{ video.likes.all.count }}</span></i>
Like
</button>
JavaScript
$("#my-like-form").submit(function(e){
e.preventDefault(); // Prevent form submission
let form = $(this);
let url = form.attr("action");
let res
const likes = $(`.like-btn{{ request.path }}`).text();// this code stopping the function of like button from work
const trimCount = parseInt(likes)
$.ajax({
type: "POST",
url: url,
data: form.serialize(),
dataType: "json",
success: function(response) {
selector = document.getElementsByName(response.next);
if(response.liked==true){
$(selector).css("color","blue");
res = trimCount - 1
} else if(response.liked==false){
$(selector).css("color","black");
res = trimCount + 1
}
}
})
})
Instead of using jinja code inside jquery code you can simple use $(this).find("button[class*=like-btn] span") this will give you span tag which have your total likes count then using .text() add new count to span tag.
Demo Code :
//suppose this return from server
var response = {
"liked": true
}
$("#my-like-form").submit(function(e) {
e.preventDefault();
let form = $(this);
let url = form.attr("action");
let res
//get like button and then find span to get total value
const likes = $(this).find("button[class*=like-btn] span").text();
const trimCount = parseInt(likes)
console.log(trimCount)
var selector = $(this).find("button[class*=like-btn]") //to select that button
/* $.ajax({
type: "POST",
url: url,
data: form.serialize(),
dataType: "json",
success: function(response) {
*/
if (response.liked == true) {
$(selector).css("color", "blue");
res = trimCount + 1
} else if (response.liked == false) {
$(selector).css("color", "black");
res = trimCount - 1
}
$(selector).find("span").text(res) //add that value inside span
/*}
})*/
})
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.2/css/all.min.css" integrity="sha512-HK5fgLBL+xu6dm/Ii3z4xhlSUyZgTT9tuc/hSrtw6uzJOvgRr2a9jyxxT1ely+B+xFAmJKVSTbpM/CuL7qxO8w==" crossorigin="anonymous" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form method="POST" action="{% url 'video:like' video.pk %}" id="my-like-form">
{% csrf_token %}
<input type="hidden" class="likin" name="next" value="{{ request.path }}">
<!--you have two clas attribute merge that in one here `1` is just for demo replace that with like-btn{{ request.path }} -->
<button class="remove-default-btn like-btn1" type="submit" id="openPopup" style="border: none; ">
<i class="fa fa-thumbs-up" aria-hidden="true"><span>23</span></i>
Like
</button>
</form>
I am using django with VueJS. The data is updating properly in my database.
I need to accomplish two things:
Post the correct content to the field image_file.
Get the downloaded image file pasted onto the servers folder which is media/shop/images
My attempted code is as below:
models.py
...
image_file = models.ImageField(upload_to='shop/images/', blank=True, null=True)
urls.py
...
urlpatterns += [
url(r'^Post-Items-Axios$', myviews.Post_Items_Axios, name='Post-Items-Axios'),
]
views.py
#api_view(['GET', 'POST', 'PUT', 'DELETE'])
def Post_Items_Axios(request):
if request.method == 'POST':
data_itemfullhd = request.data['Item Name']
data_image_file = request.data['Item Image File']
td_items, created = Md_Items.objects.get_or_create(
itemfullhd = data_itemfullhd)
td_items.imagefl = data_imagefl
td_items.image_file = data_image_file
td_items.save()
data = { 'data_itemfullhd': data_itemfullhd }
return Response(data)
bm_home.html
<template id="product-edit">
<div>
<h2>Product details</h2>
<form method="post" enctype="multipart/form-data">{% csrf_token %}
<div class="form-group">
<label for="edit-name">Item Name</label>
<input class="form-control" id="edit-name" v-model="product.itemfullhd" required/>
</div>
<!-- Upload single Image files -->
<div class="form-group">
<label for="edit-imagefile">Image</label>
<input type="file" id="edit-imagefile" #change="onFileChanged" required/>
</div>
<button type="submit" class="btn btn-primary" #click.prevent="updateProduct">Save</button>
<a class="btn btn-dark"><router-link to="/product-list">Cancel</router-link></a>
</form>
</div>
</template>
Vue template
var ProductEdit = Vue.extend({
template: '#product-edit',
data: function () {
return {
product: findProduct(this.$route.params.product_id),
selectedImage: null,
};
},
methods: {
onFileChanged (event) {
this.selectedImage = event.target.files[0]
this.product.image_file = this.selectedImage.name
},
updateProduct: function () {
let product = this.product;
products[findProductKey(product.id)] = {
id: product.id,
itemfullhd: product.itemfullhd,
image_file: product.image_file,
};
const data = {
"Item Name": product.itemfullhd,
"Item Image File": product.image_file,
}
// const formData = new FormData()
// formData.append('image_file', this.selectedImage, this.selectedImage.name)
// axios.post('/biggmount_home/Post-Items-Axios', formData, data)
axios.post('/biggmount_home/Post-Items-Axios', data)
router.push('/product-list');
},
}
});
The changes below have given me the result that I was looking to achieve:
Vue template
var ProductEdit = Vue.extend({
template: '#product-edit',
data: function () {
return {
product: findProduct(this.$route.params.product_id),
selectedImage: null,
};
},
methods: {
onFileChanged (event) {
this.selectedImage = event.target.files[0]
},
updateProduct: function () {
let product = this.product;
const formData = new FormData()
formData.append('Item Image', this.selectedImage, this.selectedImage.name)
formData.append('Item Name', product.itemfullhd)
axios.post('/biggmount_home/Post-Items-Axios', formData)
router.push('/product-list');
},
}
});
views.py
#api_view(['GET', 'POST', 'PUT', 'DELETE'])
def Post_Items_Axios(request):
if request.method == 'POST':
data_itemfullhd = request.data['Item Name']
td_items, created = Md_Items.objects.get_or_create(
itemfullhd = request.data['Item Name'],
)
td_items.image_file = request.data['Item Image']
td_items.save()
return HttpResponse('Success!')