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>
Related
I have a Like feature, which works fine for the "Detailed Product". However, I want to add this feature on the main page, where multiple products are shown. Not sure, how to correctly do that.
urls.py:
url(r'^like$', views.like_product, name='like_product')
script in the base.html:
<script type="text/javascript">
$(document).ready(function(event){
$(document).on('click', '#like', function(event){
event.preventDefault();
var pk = $(this).attr('value');
$.ajax({
type: 'POST',
url: '{% url 'like_product' %}',
data: {'id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: 'json',
success: function(response){
$('#like-section').html(response['form'])
console.log($('#like-section').html(response['form']));
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
});
</script>
likes.html:
<form action="{% url 'like_product' %}" method="post">
{% csrf_token %}
{% if is_liked %}
<button type="submit" id="like" name="product_id" value="{{ product.id }}" class="btn btn-danger">Dislike</button>
{% else %}
<button type="submit" id="like" name="product_id" value="{{ product.id }}" class="btn btn-primary">Like</button>
{% endif %}
</form>
views.py:
def home(request):
products = Product.objects.all().order_by('-pub_date')
f = ProductFilter(request.GET, queryset=products)
context = {
'filter': f,
}
return render(request, 'product/home.html', context).
def detail(request, product_id):
product = get_object_or_404(Product, product_id=product_id)
is_liked = False
if product.likes.filter(id=request.user.id).exists():
is_liked = True
context = {
'product': product,
'is_liked': is_liked,
'total_likes': product.total_likes()
}
return render(request, 'product/detail.html', context)
def like_product(request):
product = get_object_or_404(Product, id=request.POST.get('id'))
is_liked = False
if product.likes.filter(id=request.user.id).exists():
product.likes.remove(request.user)
is_liked = False
else:
product.likes.add(request.user)
is_liked = True
context = {
'product': product,
'is_liked': is_liked,
'total_likes': product.total_likes()
}
if request.is_ajax():
html = render_to_string('product/likes.html', context, request=request)
return JsonResponse({'form': html})
Likes/Dislikes are being recorded correctly if clicked from the main page, however they are not correctly displayed (actual amount of likes and Dislike button can only be seen on the "Detailed Product" page). I suspect this is because I have id="like" in the likes.html for both buttons. I suspect the jQuery script needs to be changed as well. Not sure how to do that. Thanks in advance for your help.
I assume you are getting ID from URL to details page. It really depends how you are generating the list of products on the page but if you are using loop in templates then just add like button under each product and then use it's id to set up like form.
I am getting an error with a view that i have and i was wondering if anyone can help me figure out where it is coming from. I am pretty sure it is something small that I am not seeing where it is coming from...
Within the view there will be a form that is displayed for the user to input informaiton, once the form is submitted, it is processed and then redirect to the users home...
Here is the error:
ValueError at /transfer/
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Request Method: POST
Request URL: http://localhost:8000/transfer/
Django Version: 1.8.6
Exception Type: ValueError
Exception Value:
The view tab.views.transfers didn't return an HttpResponse object. It returned None instead.
Here is the views.py
def transfers(request):
if 'username' not in request.session:
return redirect('login')
else:
username = request.session['username']
currentUser = User.objects.get(username = username)
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
from_acct = cd['from_acct']
to_acct = cd['to_acct']
amount = cd['amount']
memo = cd['memo']
new_transfer = Transfers.objects.create(
user = currentUser,
from_acct = from_acct,
to_acct = to_acct,
amount = amount,
memo = memo,
frequency = 1,
status = 1,
)
return redirect('home_page')
else:
form = TransferForm()
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
Here is the html file:
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action="." method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Here is the forms.py file portion
class TransferForm(forms.ModelForm):
acct_choices = (('tabz', 'Tabz - Username'),
('Wells Fargo', 'Wells Fargo - Username'))
from_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
to_acct = forms.TypedChoiceField(
choices=acct_choices, widget=forms.RadioSelect, coerce=int
)
class Meta:
model = Transfers
fields = ['from_acct', 'to_acct', 'amount', 'memo']
labels = {
'from_acct':'from',
'to_acct':'to',
}
from django.http import HttpResponse, HttpResponseRedirect
if request.method == 'POST':
form = TransferForm(request.POST)
if form.is_valid():
...
return HttpResponseRedirect(reverse_lazy('home'))
else:
form.fields['from_acct'].queryset = Accounts.objects.filter(user = currentUser).all()
message = 'please fill out the below form'
parameters = {
'form':form,
'currentUser':currentUser,
'message':message,
}
return render(request, 'tabs/user_balance.html', parameters)
html add form.errors
{% extends "base.html" %}
{% block content %}
<h1>Transfer Money</h1>
{% if message %}
<p>{{message}}</p>
{% endif %}
<form action='your_url/' method="POST">
{% csrf_token %}
{{ field.errors }}
{{ form.as_p }}
<input type="submit" name="submit" value="submit">
</form>
{% endblock %}
Well, this error should be thrown simply because you are giving an invalid form to your view. If you look at the logic of the view, if it is a POST and form is not valid the view does not return anything... well None for python. That's the error you are getting right?
Try to put an else statement with return after return redirect('home_page') and see if this fixes this part.
I have created some custom error message following the documentation (as best as I can find) but I'm not getting any errors, let alone my custom errors. Here's my code:
forms.py
class UploadFileForm(forms.ModelForm):
class Meta:
model = Job
fields = ['jobID','original_file']
labels = {
'jobID': _('Job ID'),
'original_file': _('File'),
}
error_messages = {
'jobID': {
'max_length': _("Job ID is limited to 50 characters."),
'required': _("Please provide a Job ID."),
'invalid': _("Job ID must be a combination of letters, numbers, - and _.")
},
'original_file': {
'required': _("Please provide a file."),
'validators': _("Please ensure you are selecting a zipped (.zip) GDB."),
},
}
help_texts = {
'original_file': _('Please provide a zipped (.zip) GDB.'),
}
upload.html
<form method = "POST" action="{% url 'precheck:upload' %}" enctype="multipart/form-data" name="uploadForm">
{% csrf_token %}
{% for field in form %}
<div>
<strong>{{ field.errors }}</strong>
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class ="help-text">{{ field.help_text }}</p>
{% endif %}
</div>
{% endfor %}
<br />
<button type="button" id="uploadButton" data-loading-text="Loading..." class="btn btn-primary" autocomplete="off" style="margin: auto 20%; ">Upload</button>
</form>
views.py
def upload(request):
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
form.save()
request.session['jobID'] = request.POST['jobID']
#job = Job.objects.filter(user_id = request.user.id).filter(jobID = request.POST['jobID']).latest()
# initialize(job)
return render(request,'precheck/run_precheck.html')
form = UploadFileForm()
historyList = Job.objects.filter(user_id = request.user.id)[:10]
return render(request, 'precheck/upload.html',{'form': form, 'history': historyList})
I've included everything I think is relevant, let me know if you need anything more.
The problem is that if the form is not valid, you're resetting the form to the initial form:
form = UploadFileForm()
historyList = Job.objects.filter(user_id = request.user.id)[:10]
return render(request, 'precheck/upload.html',{'form': form, 'history': historyList})
Your flow should render the bound form (with its errors) so it should be:
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
# do stuff for valid form
return redirect
elif request.method == 'GET':
form = UploadFileForm()
# flow common for GET and invalid form
return render(request, template, {'form': form})
I have problem with editing form in django. Pls can someone help me?
I have form with 2 fields: description and image. By this form users can edit currect article data. For example add new several images to article or update/delete one of the currect image. To create image field I used django-multiupload app. Also I load data to server by ajax. I tried next code but it didnt show me currect images in image field. Only descrtiption field works fine and show me currect data. How to fix this problem?
models.py:
class Article(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
description = models.TextField(_('Description'))
class Image(models.Model):
article= models.ForeignKey(Article, on_delete=models.CASCADE)
image = models.FileField(_('Image'), upload_to='images/%Y/%m/%d/')
forms.py:
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('description', )
image = MultiFileField()
def save(self, commit=True):
instance = super(ArticleForm, self).save(commit)
return instance
views.py:
def article_edit(request, article_id):
data = dict()
article= get_object_or_404(Article, pk=article_id)
if request.method == 'POST':
article_form = ArticleForm(request.POST, request.FILES, instance=article)
if article_form.is_valid():
article.save()
data['form_is_valid'] = True
articles = Article.objects.all
context = {'articles': articles}
context.update(csrf(request))
data['html_article'] = render_to_string('project/article_list.html', context)
else:
data['form_is_valid'] = False
else:
article_form = ArticleForm(instance=article)
context = {'article_form': article_form}
data['html_article_form'] = render_to_string('project/article_edit.html', context, request=request)
return JsonResponse(data)
JS:
$(function () {
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal").modal("show");
},
success: function (data) {
$("#modal .modal-content").html(data.html_article_form);
}
});
};
var saveForm = function () {
var form = $(this);
var dataForm = new FormData(form.get(0));
$.ajax({
url: form.attr("action"),
data: dataForm
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#article-list").html(data.html_article);
$("#modal").modal("hide");
}
else {
$("#modal .modal-content").html(data.html_article_form);
}
}
});
return false;
};
// Create Article
$("#article-add-button").click(loadForm);
$("#modal").on("submit", ".js-article-add-form", saveForm);
// Update Article
$("#article-list").on("click", "#js-edit-article-button", loadForm);
$("#modal").on("submit", ".js-article-edit-form", saveForm);
});
article_edit:
{% load widget_tweaks %}
<form method="post" enctype="multipart/form-data" action="{% url 'article_edit' %}" class="js-article-edit-form">
{% csrf_token %}
{% for field in article_form %}
<div class="form-group{% if field.errors %} has-danger{% endif %}">
<label class="form-control-label" for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<div class="form-control-feedback">{{ error }}</div>
{% endfor %}
</div>
{% endfor %}
<button type="submit">Submit</button>
</form>
I am new to django and python, I am following a django tutorial and I keep getting the following error
UnboundLocalError at /blog/search/
local variable 'total_results' referenced before assignment
heres my code
def post_search(request):
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post)\
.filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
template = 'blog/post/search.html'
context = {
'form': form,
'cd': cd,
'results': results,
'total_results': total_results
}
return render(request, template, context)
I also tried it like this origanally because that's how the tutorial had it
return render(request, template, {
'form': form,
'cd': cd,
'results': results,
'total_results': total_results
})
but that also didn't work
I understand what the error message is saying but this is how the tutorial has it. What's the proper syntax to make this work. all guidance is welcome
EDIT: here is the template code
{% extends "blog/base.html" %}
{% block title %}Search{% endblock %}
{% block content %}
{% if "query" in request.GET %}
<h1>Posts containing "{{ cd.query }}"</h1>
<h3>Found {{ total_results }} result{{ total_results|pluralize}}</h3>
{% for result in results %}
{% with post=result.object %}
<h4>{{ post.title }}</h4>
{{ post.body|truncatewords:5 }}
{% endwith %}
{% empty %}
<p>There are no results for your query.</p>
{% endfor %}
<p>Search again</p>
{% else %}
<h1>Search for posts</h1>
<form action="." method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% endif %}
{% endblock %}
If there would not be query GET parameter passed, or the form would not pass validation - in this case total_results and results would not be defined. You need to either provide the default values for that case, e.g.:
def post_search(request):
results = []
total_results = 0
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post)\
.filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
template = 'blog/post/search.html'
context = {
'form': form,
'cd': cd,
'results': results,
'total_results': total_results
}
return render(request, template, context)
Or, throw a specific "validation" error in case there is no query parameter or form is not valid.
def post_search(request):
results = [] # or None
total_results = 0 # or None
form = SearchForm(request.GET or None)
if 'query' in request.GET:
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post)\
.filter(content=cd['query']).load_all()
# count total results
total_results = results.count()
template = 'blog/post/search.html'
context = {
'form': form,
'cd': cd,
'results': results,
'total_results': total_results
}
return render(request, template, context)
else:
return render(request, 'blog/post/search.html', {'form': form,})
else:
return render(request, 'blog/post/search.html', {'form': form,})
Python is pointing out that what will happen if the 'if' condition fails, and still you are using the variable 'total_results' in context. Therefore initialize it as 0 or none as you want. Similar with the 'results' variable too.
EDIT1: Since i don't exactly know what you are trying to achieve, my best guess would be to use this code.
EDIT2: Template code changes
{% extends "blog/base.html" %}
{% block title %}Search{% endblock %}
{% block content %}
{% if results %}
<h1>Posts containing "{{ cd.query }}"</h1>
<h3>Found {{ total_results }} result{{ total_results|pluralize}}</h3>
{% for result in results %}
{% with post=result.object %}
<h4>{{ post.title }}</h4>
{{ post.body|truncatewords:5 }}
{% endwith %}
{% empty %}
<p>There are no results for your query.</p>
{% endfor %}
<p>Search again</p>
{% else %}
<h1>Search for posts</h1>
<form action="." method="get">
{{ form.as_p }}
<input type="submit" value="Search">
</form>
{% endif %}
{% endblock %}
I've gone through the same book, and noticed the same problem with that particular view. Here was my solution in the view. I left the template the way it was (in the book):
def post_search(request):
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
total_results = results.count()
context = {'form':form, 'cd':cd, 'results':results, 'total_results':total_results}
return render (request, 'blog/post/search.html', context)
else:
form = SearchForm()
context = {'form':form}
return render (request, 'blog/post/search.html', context)
had exactly the same issue ... the code below works
def post_search(request):
results = []
total_results = 0
cd = None
form = SearchForm()
if 'query' in request.GET:
form = SearchForm(request.GET)
if form.is_valid():
cd = form.cleaned_data
results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all()
total_results = results.count()
return render(request, 'search/search.html', {'form':form,
'cd':cd,
'results':results,
'total_results':total_results,
})
But out of interest did you also find that the post_detail view produced similar errors ?? solved that one with this version of the code
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
#list of active comments for this post
comments = post.comments.filter(active=True)
if request.method == 'POST':
# A comment was posted
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
#create comment object but don't save to DB
new_comment = comment_form.save(commit=False)
# assitgn comment to post
new_comment.post = post
# save the comment to the DB
new_comment.save()
else:
comment_form =CommentForm()
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids).exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags')).order_by('-same_tags','-publish')[:4]
args = {}
args['post'] = post
args['comment_form']= comment_form
args['comments'] = comments
args['similar_posts'] = similar_posts
return render(request, 'detail.html', args )