Reputation: 23
Please tell me where the problem is: I need to process a JSON request, what should I access and what should I return? and this is the essence of the problem, because the answer comes to me on the server, that there is a problem with the token.
contact.html:
<form class="feedback__form" id="contact_form" role="form" action="{% url 'contact' %}" method="post">
{% csrf_token %}
<div class="feedback__inv-msg feedback__response-msg">
<span> ERROR</span>
</div>
<div class="feedback__form-wrapper">
<ul class="feedback__field-list">
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR NAME</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_name }}
</div>
</li>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR MAIL</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_email }}
</div>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR PHONE</span></div>
<div class="feedback__field-inp">
{{ contact_form.contact_phone }}
</div>
<li class="feedback__field-item">
<div class="feedback__field-title txt txt_font_mp_regular txt_size_18"><span>YOUR PROBLEM</span></div>
<div class="feedback__field-inp">
{{ contact_form.content }}
</div>
</li>
<div class="feedback__controls">
<button class="btn btn_compact feedback__sender" type="submit">SEND</button>
</div>
<div class="feedback__response">
<div class="feedback__positive feedback__response-msg"><span>YOUR MESSAGE WAS SENT</span></div>
<div class="feedback__negative feedback__response-msg"><span>YOUR MESSAGE WASNT SENT</span></div>
</div>
</form>
<script type="text/javascript">
class Form {
constructor(){
this.element = document.querySelector(`.feedback`)
this.init()
this.isValid = false
this.values = {}
}
addClassesToImps(){
for(let elem of this.element.querySelectorAll(`input`))
elem.classList.add(`inp`)
this.element.querySelector(`input[type="hidden"]`).classList.remove(`inp`)
}
getStructure(){
this.addClassesToImps()
this.form = this.element.querySelector(`.feedback__form`)
this.inps = this.element.querySelectorAll(`.inp`)
this.reqInps = this.element.querySelectorAll(`.inp[required]`)
this.sender = this.element.querySelector(`.feedback__sender`)
}
handleValidityCheck(elem){
if(!elem.checkValidity()){
elem.classList.add(`inp_invalid`)
this.isValid = false
} else {
elem.classList.remove(`inp_invalid`)
elem.classList.add(`inp_valid`)
}
}
handleSenderClick(e){
e.preventDefault()
this.isValid = true
for(let elem of this.reqInps){
this.handleValidityCheck(elem)
}
if(this.isValid){
this.element.classList.remove(`feedback_inv`)
this.values.name = this.element.querySelector(`.inp[name="contact_name"]`).value
this.values.mail = this.element.querySelector(`.inp[name="contact_email"]`).value
this.values.phone = this.element.querySelector(`.inp[name="contact_phone"]`).value
this.values.text = this.element.querySelector(`.inp[name="content"]`).value
async function postData(url = '', data = {}) {
const response = await fetch(url, {
method: 'POST', // *GET, POST, PUT, DELETE, etc.
mode: 'cors', // no-cors, *cors, same-origin
cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
credentials: 'same-origin', // include, *same-origin, omit
headers: {
'Content-Type': 'application/json'
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow', // manual, *follow, error
referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
body: JSON.stringify(data) // body data type must match "Content-Type" header
});
return response.json(); // parses JSON response into native JavaScript objects
}
postData(``, this.values)
.then(data => {
console.log(data); // JSON data parsed by `response.json()` call
});
} else {
this.element.classList.add(`feedback_inv`)
return false
}
}
init(){
this.getStructure()
console.log(this)
this.sender.addEventListener(`click`, this.handleSenderClick.bind(this))
for(let elem of this.inps){
elem.addEventListener(`focusout`, this.handleValidityCheck.bind(this, elem))
}
}
}
let feedback = new Form()
</script>
forms.py:
class ContactForm(forms.Form):
contact_name = forms.CharField(required=True)
contact_email = forms.EmailField(required=True)
contact_phone = forms.CharField(required=False)
content = forms.CharField(
required=True,
widget=forms.Textarea(attrs={'id': 'my_field', 'class': 'feedback__textarea inp'})
)
# the new bit we're adding
def __init__(self, *args, **kwargs):
super(ContactForm, self).__init__(*args, **kwargs)
self.fields['contact_name'].label = "Name:"
self.fields['contact_email'].label = "Mail:"
self.fields['contact_phone'].label = "Phone"
self.fields['content'].label = "Your problem"
views.py:
def contact(request):
form_class = ContactForm
if request.method == 'POST':
form = form_class(data=request.POST)
if form.is_valid():
contact_name = request.POST.get(
'contact_name'
, '')
contact_phone = request.POST.get(
'contact_phone'
, '')
contact_email = request.POST.get(
'contact_email'
, '')
form_content = request.POST.get('content', '')
# Email the profile with the
# contact information
template = get_template('contact_template.txt')
context = {
'contact_name': contact_name,
'contact_email': contact_email,
'contact_phone': contact_phone,
'form_content': form_content,
}
content = template.render(context)
email = EmailMessage(
"New message from form",
content,
'', ['[email protected]'],
headers = {'Reply-To': contact_email }
)
email.send()
return HttpResponse('')
in urls.py:
...
path('contact/', views.contact, name='contact'),
...
in server console:
Forbidden (CSRF token missing or incorrect.)
"POST / HTTP/1.1" 403
in browser console:
SyntaxError: JSON.parse: unexpected character at line 2 column 1 of the JSON data
Please do not recommend options using jQuery, its presence is excluded in this project
Upvotes: 0
Views: 63
Reputation: 607
In your script take the csrf token value using the below line
var token = jQuery("[name=csrfmiddlewaretoken]").val();
and when you sending data to server use one more parameter
headers: {'X-CSRFToken': token}
It will resolve your csrf error and make sure in form you have defined {% csrf_token %}.
Upvotes: 1