Ajax succesfull call show div with form data - python

views.py
def index(request):
""""""""""""""
registerform = UserRegisterForm(request.POST)
createprofileform = UserCreateProfileForm(request.POST)
if registerform.is_valid() and createprofileform.is_valid():
result = registerform.save(commit=False)
result.set_password(request.POST['password']) #set member password
result.username = username
result.save()
member.user_id = user.id
member.member_id = result.id
member.save() #new member registration
member_profile = UserProfile.objects.get(user=result.id)
createprofileform = UserCreateProfileForm(request.POST, instance=member_profile)
createprofileform.save() #create member profile
createprofileform = UserCreateProfileForm()
member_save_msg = 'New member has been added.'
""""""""""""
return render(request,'index.html',{ 'registerform': registerform,'createprofile': createprofileform,})
index.html
{% block main-content %}
<table width="98%" border="0" style="margin-left:0.7%;" cellpadding="0" cellspacing="0" id="rounded_table">
<tr >
<td width="50%">Main Account Holder</td><td width="50%">Authorised Reporters</td>
</tr>
<tr id="main_account">
<td width="50%">All data related to main account holder comes here</td>
</tr>
<tr id="authorised_reporter">
<td width="100%" colspan="2">
<div id="authorisedreporter" {% if not registerform.errors %}style="display:none"{% endif %}>
<form method="post" action="." id="reporter-form">{% csrf_token %}
<table width="100%">
<tr>
<td style="width:100px;">First name:</td><td>{{registerform.first_name}}</td>
</tr>
<tr>
<td>Last name:</td><td>{{registerform.last_name}} </td>
</tr>
""""""other form fields""""""""
<tr>
<td colspan=2""><p align="right"><button type="submit" title="Save" >Save <img src="{{ STATIC_URL }}images/button-icon-ir-fwd.png" width="12" height="17" alt="" /></button></p>
</td>
</tr>
</table></form>
</table>
{%endblock%}
The above views.py and index.html is for saving the new user entry.
My html template is divided into 2 section,Main Account Holder tab and Authorised Reporters tab.Main Account Holder tab is for saving profile info and Authorised Reporters tab is for creating new user.on page load Main Account Holder tab will be active and user tab will be hidden.If user tab is selected,Main Account Holder tab will be hidden.Once the user is saved,the user details are displayed below, in below format.
{% for list in member_list %}
<tr class="ir-shade">
<td style="width:120px;"><span><input type="submit" name="delete" value="{{list.0.id}}" class="delete_reporter" /></span><button> id="{{ list.0.id }}" class="openDiv">{{list.0.first_name|title}} {{list.0.last_name}}</button></td>
<td style="width:410px;"> {{list.0.email}} {{list.1.phone_daytime}} {{list.1.phone_mobile}}</td>
</tr>
{% endfor %}
What i actually want is Onclicking the <button> id="{{ list.0.id }}" class="openDiv">{{list.0.first_name|title}} {{list.0.last_name}}</button> saved user data should shown in same field in editable mode.i am passing the user id in button.On click the button,the data related to user id should shown in editable mode.
js:
$('.openDiv').click(function () {
var id = $(this).attr('id');
var csrf_token = $("#csrf_token").val();
$.ajax({
data:{
csrfmiddlewaretoken: ('{{csrf_token}}'),
id:id,
},
type:'POST',
url: '/setting/save-reporter/',
success: function(data) {
$('#authorisedreporter').html(data);
}
});
});
The below views.py and html are written for showing the saved form instance.Now i can show the saved form instance and i am loading the instance into authorisedreporter div(please check in js and index.html).In this time if i kit save,it is creating new record,it is calling the views.py related to index method.I want to update and not save the record.
save_reporter.html
<form method="post" action="." id="{{ id }}">
{% csrf_token %}
<table width="100%">
<tr>
<td style="width:100px;">First name:</td><td>{{form.first_name}}</td>
</tr>
<tr>
<td>Last name:</td><td>{{form.last_name}}</td>
</tr>
<tr>
<td>Daytime phone:</td><td>{{profile.phone_daytime}}</td>
</tr>
<tr>
<td>Mobile phone:</td><td>{{profile.phone_mobile}}</td>
</tr>
<tr>
<td>Email:</td><td>{{form.email}}</td>
</tr>
<tr>
<td>Password</td><td>{{form.password}}</td>
</tr>
<tr>
<td colspan=2"<p align="right">{% include "buttons/save.html" %}</p></td>
</tr></table></form>
views.py
def save_reporter(request):
user = request.user
id = request.POST.get('id')
user = User.objects.get(pk =id)
userprofile = UserProfile.objects.get(user=user.id)
form = ReporterRegisterForm(instance=user)
profileform = ProfilecontactForm(instance=userprofile)
return render(request, 'setting/save_reporter.html',
{'form': form,
'id':id,
'profile':profileform
})
I had explained my current issue i am facing,please have help me in doing this.Thanks

Let me analyze your JS code a bit, since I can see several errors/mistakes there:
$('.openDiv').click(function (e) {
e.preventDefault();
// where is following data taken from? At the point you click the .openDiv link, the form doesn't have any data yet so all of them will be empty string ''
var csrf_token = $("#csrf_token").val();
var id = $(this).closest('td').attr('id');
var firstname = $("#"+id).find('#id_first_name').val();
var lastname = $("#"+id).find('#id_last_name').val();
var phonedaytime = $("#"+id).find('#id_phone_daytime').val();
var phonemobile = $("#"+id).find('#id_phone_mobile').val();
var email = $("#"+id).find('#id_email').val();
// do you use AJAX to get the form or use it to save the form?
$.ajax({
data: $(this).serialize(), // this is wrong, $(this) is the link object, not a form
type:'POST',
url: '/setting/save-reporter/',
success: function(data) {
$('#authorisedreporter').html(data);
$('#authorisedreporter').show();
}
});
});
Ok as far as I understand, after clicking the link, you are using AJAX to send request to Django view to fetch back the correct instantiated form. So you should:
First, simplify your JS code:
$('.openDiv').click(function (e) {
e.preventDefault();
var this_id = $(this).closest('td').attr('id'); // get the user ID, since that's all you need
console.log(this_id); // making sure that you get the right ID
$.ajax({
data: { id: this_id },
type: 'POST',
url: '/setting/fetch-reporter-form/',
success: function(data) {
$('#authorisedreporter').html(data);
$('#authorisedreporter').show();
}
});
});
Next, split your old view to several views to focus on what it needs to do (note: you can leave your index view as it is now):
def fetch_reporter_form(request):
''' Change your save_reporter view name to this view '''
registerform = UserRegisterForm()
if request.method == 'POST':
id = request.POST.get('id', None)
if id:
user = get_object_or_404(pk=user.id)
userprofile = UserProfile.objects.get(user=user)
registerform = UserRegisterForm(request.POST, instance=user)
return render(request, 'setting/register_form.html', {
'user_id': id
'registerform':registerform
})
else:
return HttpResponse('Request does not contain any ID')
else:
return HttpResponse('Request is not POST')
def update_reporter(request):
''' This function is for update the reporter '''
registerform = UserRegisterForm()
if request.method == 'POST':
id = request.POST.get('id', None)
if id:
user = get_object_or_404(pk=user.id)
userprofile = UserProfile.objects.get(user=user)
registerform = UserRegisterForm(request.POST, instance=user)
if registerform.is_valid():
result = registerform.save(commit=False)
# saving code here ...
return HttpResponse('Success')
else:
return HttpResponse('Request does not contain any ID')
else:
return HttpResponse('Request is not POST')
You can see here there are 2 functions: 1 for fetching the right form from AJAX, the other for saving the data via normal form submit. Of course you should make the urls.py accordingly, something like:
urlpatterns = patterns('',
# ... your code ...
url(r'^setting/fetch-reporter-form/$', 'yourapp.views.fetch_reporter_form'),
url(r'^setting/update-reporter/$', 'yourapp.views.update_reporter'),
)
You might also notice that you should make a new template setting/register_form.html that include your registration form HTML only (note: you need a hidden id field that was returned by fetch_reporter_form view above to identify the form):
<form method="post" action="/setting/update-reporter" id="reporter-form">
{% csrf_token %}
<input type="hidden" name="id" value="{{ user_id }}" />
<!-- your code here -->
</form>
So the flow is:
You go to index view. There is several forms to save new reporter, etc. as normal.
You click on the .openDiv button. It will send the AJAX request above to fetch_reporter_form to get the correct form. (Your code is working fine at this point)
You click Save button on that form, it will submit the updated data (via POST) to update_report view and update the reporter.
I'm just trying to give you the basic idea. The rest is quite straightforward so I guess you can continue easily. Hope it helps!

Let me resume what you are doing:
$.ajax({
data:{
/* ... */
},
type:'POST',
url: '/report/save_reporter/',
success: function() {
return true;
}
});
Here you setup an Ajax asynchronous query to post data to the server. When the query reaches the server, if it doesn't crash, the success: callback is called and javascript does nothing (return true;).
$('#authorisedreporter').show();
Here, you show an HTML node before the asynchronous Ajax query ends (succeeds or fails). To show the element after the Ajax query is done, put this code inside the success: or error: callback.
Finally, if you count your (, ), { and } you will see than $('#authorisedreporter').show(); is outside of the click callback. Therefore, if it is out of the document ready callback, it will have no effect.
So the right Javascript code should be (I think):
$('.openDiv').click(function (e) {
e.preventDefault();
var id = $(this).attr('id');
var firstname = $("#"+id).find('#id_first_name').val();
var phonemobile = $("#"+id).find('id_phone_mobile').val();
$.ajax({
data:{
csrfmiddlewaretoken: csrf_token,
edit_reporter:true,
id:id,
first_name:firstname,
phone_mobile:phonemobile,
},
type:'POST',
url: '/report/save_reporter/',
success: function() {
$('#authorisedreporter').show();
}
});
});
EDIT:
About your view.py, you save a UserProfile but do not return anything to the client browser. Nothing.
def save_reporter(request):
user=User.objects.get(user=user) # you should use django.shortcuts.get_object_or_404
userprofile = Userprofile.objects.get(user=user) # same comment
if request.method == 'POST':
registerform = UserRegisterForm(request.POST,instance=user)
createprofileform = UserCreateProfileForm(request.POST,instance=userprofile)
# you create 2 forms above, but don't use them. Is it normal ?!
# you should do loops "if registerform .valid(): ... else: ..." and use it. Same for the 2nd form
if 'edit_reporter' in request.POST:
first_name=request.POST.get('first_name') # can be None
phone_mobile = request.POST.get('phone_mobile') # can be None
user = User.objects.get(pk=user)
user.first_name = first_name
user.save() # put it inside a try/except statment
userprofile = UserProfile.objects.get(pk=user) # use get_or_404
userprofile.phone_mobile = phone_mobile
userprofile.save() # put it inside a try/except statment
return HttpResponse() # this returns an empty html page, do you want to return the form here ?

Check if there is any error message returned from the server:
$.ajax({
// ...
error: function(err) {
console.log(err);
}
});
Edit:
You don't pass the user id when you submit the form. Try doing something like:
<form ...>
<!-- //.. -->
{{ form.id.as_hidden }}
</form>

Related

how to remember the selected radio button option in diango

I asked this question previously and didn't get any help/solution. So I'm asking again.
I'm trying to make sure that even if the user refresh the page or goes back and comes back to that page, the radio button is still the same as what the user selects.
N.B: the value of the radio button is saved in sessions
<div class="col-md-1 ps-md-1">
<input class="align-middle h-100" type="radio" name="deliveryOption" id="{{option.id}}"
value="{{option.id}}">
</div>
Ajax
$('input[type=radio][name=deliveryOption]').on('change', function(e) {
e.preventDefault();
$.ajax({
type: "POST",
url: '{% url "checkout:cart_update_delivery" %}',
data: {
deliveryoption: $(this).val(),
csrfmiddlewaretoken: "{{csrf_token}}",
action: "post",
},
success: function (json) {
document.getElementById("total").innerHTML = json.total;
document.getElementById("delivery_price").innerHTML = json.delivery_price;
},
error: function (xhr, errmsg, err) {},
});
});
my view
def cart_update_delivery(request):
cart = Cart(request)
if request.POST.get("action") == "post":
delivery_option = int(request.POST.get("deliveryoption"))
delivery_type = DeliveryOptions.objects.get(id=delivery_option)
updated_total_price = cart.cart_update_delivery(delivery_type.delivery_price)
session = request.session
if "purchase" not in request.session:
session["purchase"] = {
"delivery_id": delivery_type.id,
}
else:
session["purchase"]["delivery_id"] = delivery_type.id
session.modified = True
response = JsonResponse({"total": updated_total_price, "delivery_price": delivery_type.delivery_price})
return response
when I added a django templating if statement, it kinda work but the radio button is always remember on the last radio button when refreshed.
{% for option in deliveryoptions %}
<input class="align-middle h-100" type="radio" {% if deliveryoption == %} checked=1 {% elif delivery_option == 2 %} checked="checked"{% endif %} autocomplete='on' name="deliveryOption" id="{{option.id}}"
value="{{option.id}}">
</div>
</div>
</div>
{% endfor %}
</div>

Django ListView: filter history based on chosen user

I've got a History ListView in which I'd like to let my Users filter the Historyitems based on which User they picked in the ModelChoiceFields I'm providing them
My History View looks like this:
class HistoryItems(ListView):
model = HistoryItem
template_name = 'history/history_table.html'
context_object_name = 'history_items'
def get_context_data(self, **kwargs):
user_id = kwargs.get('user_id')
query = {}
if user_id:
user = get_object_or_404(User, pk=user_id)
query['changed_by'] = user
else:
user = None
history_items = HistoryItem.objects.filter(**query).select_related('changed_by',
'content_type')
return {
'filter_history_form': HistoryFilterForm(user_id=user_id),
'history_items': history_items,
}
It returns me the correct History items in a big table (see html below). And then I've got this form:
class HistoryFilterForm(forms.Form):
normal_user = forms.ModelChoiceField(User.objects.filter(special=None), label="Normal Users", empty_label="All normal users")
special_user = forms.ModelChoiceField(User.objects.exclude(special=None), label="Special User", empty_label="All special users")
def __init__(self, *args, **kwargs):
user_id = kwargs.pop('user_id')
super(HistoryFilterForm, self).__init__(*args, **kwargs)
self.fields['normal_user'].initial = user_id
self.fields['special_user'].initial = user_id
self.helper = FormHelper()
self.helper.label_class = 'sr-only'
self.helper.add_layout(Layout(
Row(
Div('normal_user', css_class='col-sm-3'),
Div('special_user', css_class='col-sm-3'),
)
))
This form simply creates two ModelChoiceFields of the same User object, just that one field shows all "normal" users and the other all "special users"
My Urls looks lime this:
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
I figured that I would need to refresh my page all the time when I'm searching for the history items of another user, which I'm doing with JavaScript (see HTML below). I'm also setting the id of the user in the url as an extra parameter.
And finally my HTML:
{% block extra_js %}
{{ block.super }}
<script type="application/javascript">
$(function(){
var historyUrlBase = '/history/';
var getParams = function(){
return {
'normalUserId': $('#id_normal_user').val(),
'specialUserId': $('#id_special_user').val()
}
};
var getNormalUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.normalUserId;
};
$('#id_normal_user').change(function(){
window.location.href = getNormalUrl();
});
var getSpecialUrl = function(){
var params = getParams();
return historyUrlBase + 'u=' + params.specialUserId;
};
$('#id_special_user').change(function(){
window.location.href = getSpecialUrl();
});
});
</script>
{% endblock %}
{% block main %}
{% crispy filter_history_form %}
<table class="table table-bordered table-responsive-sm">
<thead class="thead-light">
<tr>
<th>Changed at</th>
<th>Object</th>
<th>Action</th>
<th>Changed by</th>
<th>Difference</th>
</tr>
</thead>
<tbody>
{% for history_item in history_items %}
<tr>
<td>
{{ history_item.changed_at|date:"d.m.Y h:i:s" }}
</td>
<td>
{{ history_item.object }}
</td>
<td>
{% if history_item.action == 'custom' %}
{{ history_item.description }}
{% else %}
{{ history_item.get_action_display }}
{% endif %}
</td>
<td>
{{ history_item.changed_by }}
</td>
<td>
{{ history_item.difference|default:'' }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
My main problem right now is that in my View the kwargs I am receiving are always an empty dict with which ofc nothing works.
But I don't know how I can receive the ID from the users I'm picking, my form always shows the correct users in the two ModelChoiceFields, but how can I get the ID's from those users to use them in my view?
The users themselves only distinguish by the special field they have, but they share the same model.
I'm using Django 2.2 and Python 3.7 btw, so maybe if there is an even easier way someone knows, that would also be welcome!
I hope someone knows a good solution or can tell me what I'm doing wrong. Thanks in regard! :)
Short Answer
The kwargs dictionary in get_context_data contains any key word arguments defined in your urls.
urls = [
path('', views.HistoryItems.as_view(), name='history_index'),
path('u=<int:pk>', views.HistoryItems.as_view(), name='history_index'),
]
Your first url has no key word arguments defined. Your second url has one key word argument, pk (i.e. not user_id). So your code should actually be
user_id = kwargs.get('pk')
Long Answer
The way you've set up your form isn't typically how you would handle filtering of data. What you want to do is to submit your form using a GET request.
https://docs.djangoproject.com/en/dev/topics/forms/#get-and-post
Which will produce a url with query string parameters that looks something like
/history/?normal_user=1&special_user=1
You can then access these query string parameters in your view via the GET dictionary from the request object.
def get_context_data(self, **kwargs):
normal_user = self.request.GET.get('normal_user')
special_user = self.request.GET.get('special_user')
# filter your history with normal_user/special_user
And finally, delete your second url as this is no longer necessary.

Django - edit HTML table rows and update database

I created a HTML table, it contains some information. However I want to add the possibility to edit table row text and by clicking "save", the database would be updated.
Can someone help me?
Do I need to use Ajax? If so please can I get some guidance?
<table style="width:100%">
<tr>
<th>Questions</th>
<th>Answers</th>
<th>Action</th>
</tr>
{% for q in questions%}
<tr>
<td contenteditable='true'>{{q.question}}</td>
<td contenteditable='true'>{{q.answer}}</td>
<td>
<center>Save Edit --- Delete</center>
</td>
</tr>
{%endfor%}
</table>
Here is my view, I know it shouldn't look like this because there is no parameter passed between the view and the HTML table, this needs to be fixed:
def edit_question(request,id):
question = Question.objects.get(id=id)
if(question):
question.update(question = quest, answer = ans)
return redirect('list_questions')
return render(request, 'generator/questions.html', {'question': question})
UPDATE
I used the solution that #xxbinxx provided, However in the view function, the condition request.method == "POST" doesn't seem to be verified even if it's in ajax function ?
heres the updated code :
<script type="text/javascript">
function saveQuestionAnswer(e, id) {
e.preventDefault();
console.log(id)
editableQuestion = $('[data-id=question-' + id + ']')
editableAnswer = $('[data-id=answer-' + id + ']')
console.log(editableQuestion.text(), editableAnswer.text())
$.ajax({
url: "list/update/"+id,
type: "POST",
dataType: "json",
data: { "question": editableQuestion.html(), "answer": editableAnswer.html() },
success: function(response) {
// set updated value as old value
alert("Updated successfully")
},
error: function() {
console.log("errr");
alert("An error occurred")
}
});
return false;
}
</script>
HTML :
<table style="width:90%">
<tr>
<th ><font color="#db0011">Questions</th>
<th><font color="#db0011">Answers</th>
<th><font color="#db0011">Action</th>
</tr>
{% for q in questions%}
<tr>
<td width="40%" height="50px" contenteditable='true' data-id="question-{{q.id}}" data-old_value='{{q.question}}' onClick="highlightEdit(this);">{{q.question}}</td>
<td width="45%" height="50px" contenteditable='true' data-id="answer-{{q.id}}" data-old_value='{{q.answer}}'>{{q.answer}}</td>
<td width="15%" height="50px"><center>
<a class="button" href="{% url 'edit_question' q.id %}" onclick="saveQuestionAnswer('{{q.id}}')">Edit</a>
<a class="button" href="{% url 'delete_question' q.id %}">Delete</a>
</center></td>
</tr>
{%endfor%}
</table>
views.py
def edit_question(request,id):
quest = Question.objects.get(id=id)
print(quest)
if request.method=='POST': # It doesn't access this condition so the updates won't occur
print("*"*100)
quest.question = request.POST.get('question')
quest.answer = request.POST.get('answer')
print(quest)
quest.save()
return redirect('list_questions')
return render(request, 'browse/questions.html', {'quest': quest})
Can someone help me solve this final issue ?
Yes you'll have to use AJAX to achieve in-place editing. I'm posting quick code so you get the idea.
NOTE: the below code has errors ;) I don't want to write in detail as it would be of no good to you. You must brainstorm and try it yourself.
contenteditable=”true” is to make column editable.
an attribute data-old_value to keep old value to check before making Ajax request to update changed value in your database table.
Code is making use of function saveQuestionAnswer()
on blur event to update changed value and function highlightEdit() to highlight column in edit mode.
<table style="width:100%">
<tr>
<th>Questions</th>
<th>Answers</th>
<th>Action</th>
</tr>
{% for q in questions%}
<tr>
<td contenteditable='true' data-id="question-{{q.id}}" data-old_value='{{q.question}}' onClick="highlightEdit(this);">{{q.question}}</td>
<td contenteditable='true' data-id="answer-{{q.id}}" data-old_value='{{q.answer}}' onClick="highlightEdit(this);">{{q.answer}}</td>
<td>
<center><a onclick="saveQuestionAnswer('{{q.id}}')">Save your edit --- </a>Delete</center>
</td>
</tr>
{%endfor%}
</table>
<script>
function saveQuestionAnswer(id) {
editableQuestion = $('a[data-id=question-'+id+']') //this will get data-id=question-1 where 1 is the question ID
editableAnswer = $('a[data-id=answer-'+id+']') //this will get data-id=answer-1 where 1 is the question ID
// no change change made then return false
if ($(editableQuestion).attr('data-old_value') === editableQuestion.innerHTML && $(editableAnswer).attr('data-old_value') === editableAnswer.innerHTML)
return false;
// send ajax to update value
$(editableObj).css("background", "#FFF url(loader.gif) no-repeat right");
$.ajax({
url: "/my-save-url/",
type: "POST",
dataType: "json",
data: {"question": editableQuestion.innerHTML, "answer": editableAnswer.innerHTML}
success: function(response) {
// set updated value as old value
$(editableQuestion).attr('data-old_value', response.question);
$(editableQuestion).css("background", "#FDFDFD");
$(editableAnswer).attr('data-old_value', response.answer);
$(editableAnswer).css("background", "#FDFDFD");
},
error: function() {
console.log("errr");
alert("An error occurred")
}
});
}
function highlightEdit(elem){
$(elem).css("background", "#e3e3e3") //just add any css or anything, it's only to depict that this area is being edited...
}
</script>
Your view will now get data in json format as {'question': <value>, 'answer': <value>}
you can add another key 'id' in this json if you want, or you can keep your url like this /saveQuestionAnswer/<id>. Here you have your id in url itself.
I hope you understand now.
Thanks

Update Django object field without refresh the page

How can I call a view function that change object field without refresh the page?
views.py
def add_like(request, pk):
book = Book.objects.get(pk=pk)
book.like = True
book.save()
return redirect('book_list')
urls.py
url(r'^add_like/(?P<pk>[0-9]+)/$', views.add_like, name='add_like'),
list.html
[...]
<td><span class="glyphicon glyphicon-heart" style="color: grey;"></span></td>
[...]
Once user click the button, I want to change like status and the tag content to:
<td><span class="glyphicon glyphicon-heart" style="color: red;"></span></td>
I know Ajax can be the answer, but I don't know how to implement it.
Thanks.
Instead of
<td><span class="glyphicon glyphicon-heart" style="color: red;"></span></td>
Use an input and give it an ID like
<td><input style="color: red" class="book btn btn-default glyphicon glyphicon-heart" value="{book.pk}" /></td>
Then according with this example call the AJAX function
<script>
$(".book").on('click', function () {
var id = $(this).val();
$.ajax({
url: '/add_like/',
data: {
'pk': id
},
dataType: 'json',
success: function (data) {
if (data) {
alert(data);
}
}
});
});
</script>
Then update your view with:
from django.http import JsonResponse
def add_like(request):
pk = request.GET.get('pk', None)
book = Book.objects.get(pk=pk)
book.like = True
book.save()
data = {'book', book}
return JsonResponse('data')

Django object not iterable, why?

I want display username if he click on i want join button using ajax.
I have html that look like this :
<div class="who_come">
<form class="form-inline" role="form" method="post" id="joinToEventForm">
{% csrf_token %}
<p align="left"><b ><button type="submit">I want join</button></b></p></b></p>
</form>
{% for u in who_come %}
<p>{{u.visiter}}</p>
{% endfor %}
</div>
i use this code to produce my ajax :
$('#joinToEventForm').on('submit', function(event){
event.preventDefault();
console.log("form submitted!") // sanity check
$.ajax({
type:'POST',
data:{
csrfmiddlewaretoken:'{{ csrf_token }}'
},
success : function () {
alert("You are on Envent")
}
});
});
it code works, and write to database what i need, but it return to me 500 error code with TypeError: 'WhoComeOnEvent' object is not iterable. I can't understand what is a problem
it is my model:
class WhoComeOnEvent(models.Model):
visiter = models.ForeignKey(User, related_name='WhoComeOnEvent')
which_event = models.ForeignKey(Topic, related_name='WhoComeOnEvent')
def __str__(self):
return '%s go to %s' % (self.visiter.username, self.which_event.subject)
it is my view :
def p(request, pk):
user = request.user
topic = get_object_or_404(Topic, pk=pk)
post = get_object_or_404(Post, pk=pk)
comment = Comments.objects.filter(pk=pk)
who_come = WhoComeOnEvent.objects.filter(pk=pk)
if request.is_ajax():
who_come = WhoComeOnEvent.objects.create(
visiter=user,
which_event=post.topic
)
if request.method == 'POST':
form = CustomCommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.creator = user
comment.save()
comment = Comments.objects.create(
body=form.cleaned_data.get('body'),
creator=user,
)
return render(request, 'post.html', {'post': post, 'topic': topic, 'comment': comment,
'form': form, 'who_come': who_come})
else:
form = CustomCommentForm()
return render(request, 'post.html', {'post': post, 'topic': topic, 'comment': comment,
'form': form, 'who_come': who_come})
I use WhoComeOnEvent.objects.filter, as far as i know it may be iterable. I was try use __iter__ and it doesn't help me. I was try use object.filter(...).values(), but it too do not help. I think may be i made wrong logic in ajax functionality. Please don't be mad if it stupid question, i use ajax first time at my life.
Edit
I solved 500 error and iterable problem by replacing
{% for u in who_come %}
<p>{{u.visiter}}</p>
{% endfor %}
to
{% for u in who_come.visiter.all %}
<p>{{u.username}}</p>
{% endfor %}
but it not display link on user in html
If you see, if this condition is true:
if request.is_ajax()
then who_come is going to be a WhoComeOnEvent.objects.create object and that's not an iterable!
You need to send back something useful to change the HTML after the AJAX call.
Solution:
from django.http import HttpResponse
def p(request, pk):
# your existing code
if request.is_ajax():
# change variable name
who_come_obj = # same create code
visitors_usernames = []
for w in who_come:
visitors_usernames.append(w.visiter.username)
return HttpResponse(json.dumps(visitors_usernames))
In Javascript AJAX success method:
$.ajax({
...
success: function(data) {
//seems more useful try to use convertation
var to_json = JSON.stringify(data);
var usernames = JSON.parse(to_json);
var html_str = '';
for (var i=0; i < usernames.length; i++) {
html_str += '<p>' + usernames[i] + '</p>';
}
$('#who_come_links').html(html_str);
}
});
Finally, wrap the links with a div with id who_come_links in HTML
<div id="who_come_links">
{% for u in who_come %}
<p>{{u.visiter.username}}</p>
{% endfor %}
</div>

Categories