I'm developing a simple blog with Django. I tried adding ajax functionality to my like button. But got this error:
Reverse for 'like-post' with arguments '('',)' not found. 1 pattern(s)
tried: ['like/(?P[0-9]+)$']
PS: I followed this video to create a like button and this video add ajax functionality
views.py
class PostDetailView(FormMixin, DetailView):
model = Post
form_class = CommentForm
def get_success_url(self):
return reverse('post-detail', kwargs={'pk': self.object.id})
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
postid = get_object_or_404(Post, id=self.kwargs['pk'])
total_likes = postid.total_likes()
context['form'] = CommentForm(initial={'post': self.object})
context['total_likes'] = total_likes
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super(PostDetailView, self).form_valid(form)
def LikeView(request, pk):
post = Post.objects.get(id=pk)
#post = get_object_or_404(Post, id=request.POST.get('post-id'))
post.likes.add(request.user)
context = {
'post': post,
'total_likes': post.total_likes,
}
if request.is_ajax():
html = render_to_string('blogsite/like_section.html', context, request=request)
return JsonResponse({'form': html})
return HttpResponseRedirect(reverse('blogsite-home'))
urls.py
urlpatterns = [
path('', PostListView.as_view(), name='blogsite-home'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('like/<int:pk>', LikeView, name='like-post'),
]
base.html
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<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-post" post.pk %}',
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>
like_section.html
<h5><form method="POST" action="{% url 'like-post' post.id %}">
{% csrf_token %}
<button type="submit" id="like" class="btn btn-link btn-sm" name="post-id" value="{{ post.id }}"><strong><i class="fa fa-thumbs-up"></i> {{ post.total_likes }}</strong></button><h6 align ="right" class="d-inline-block">
<i class="fa fa-facebook-f"></i> <i class="fa fa-linkedin"></i>
</h6></form>
like_section.html is then included in my post_detail.html
<div id="like-section">
{% include 'blogsite/like_section.html' %}
</div>
I can't seem to find a solution to this problem.
If believe error comes out when you try to load post detail view. You're missing post variable in get_context_data of the PostDetailView. And as you're trying to access post.pk in {% url "like-post" post.pk %}. When Django does not find variable in context, the template system inserts the value of the engine’s string_if_invalid configuration option, which defaults to ''(empty string). As a result, url tag tries to lookup for url which is like/<string:pk> which is not defined in your urls.py and thus outputs error. So, what actually you have to do is to add post to context in get_context_data.
Related
OK so I'm trying to create a page that will have a search form of Well,
I get the contents of the search in the page ex: (http://127.0.0.1:8000/wellsheet/ODN20)
I used this code
urls.py file
path('wellsheet/<slug:Evt_id>', views.wellsets, name='WellSheetg'),
views.py
def wellsets(request, Evt_id):
serchedWl = WellSheets.objects.filter(WellID__WellID__exact=Evt_id)
context ={
'title': 'Eventstopost',
'Wellslist':serchedWl,
'WIDSHT':Evt_id,
}
return render(request, 'Home/WELLINFO/W_TchD/wellshts.html', context)
in addition to this page I want to add another well ,and I have a model form to add in same page using crispy.
urls.py
path('wellsheet/<slug:WeelN>/', views.welshetad2.as_view(), name='AddWellSheet'),
views.py
class welshetad2(LoginRequiredMixin, CreateView):
model = WellSheets
template_name = 'Home/WELLINFO/W_TchD/wellshts.html'
form_class = UploadWSF2
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
but in my page I can't render the crispy form
<div class="border p-3 mb-3 mt-3 w3-round-large w3-light-grey border-dark">
<form method="POST">
{% csrf_token %}
<div class="form-row"><div class="form-group mb-0">
{{ form.as_p }}
</div></div>
this is my page
page
My goal is to see a page like this
My Goal
Hi the problem is solved by using one def as:
views.py
def wellsets(request, pk):
serchedWl = WellSheets.objects.filter(WellID__WellID__exact=pk)
form= UploadWSF2(request.POST or None)
context ={
'title': 'Wellssht',
'Wellslist':serchedWl,
'WIDSHT':pk,
'form':form,
}
return render(request, 'Home/WELLINFO/W_TchD/wellshts.html', context)
and the page will show tow results a Form and results of search
I have built a blog project and I can't access the PostCreateView for some unknown reason.
I keep getting Page 404 error although I have in the urls patterns
I am also getting the error raised by
score.views.PostDetailView
Here is the views.py
class PostCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = Post
fields = ['title', 'design']
template_name = "post_form.html"
success_url = "/score/"
success_message = "Your Post has been submitted"
def form_valid(self, form):
form.instance.designer = self.request.user
return super().form_valid(form)
here is the PostDetail Views.py
class PostDetailView(DetailView):
model = Post
template_name = "post_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
post = get_object_or_404(Post, slug=self.kwargs['slug'])
total_likes = post.total_likes()
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
context["total_likes"] = total_likes
context["liked"] = liked
return context
Here is the Urls.py
app_name = 'score'
urlpatterns = [
path('', PostListView.as_view(), name='score'),
path('<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
path('new/', PostCreateView.as_view(), name='post-create'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
]
here is the nav bar html that is taking me to the page
<a class="nav-link waves-effect" href="{% url 'score:post-create' %}" >Upload Post</a>
here is the post_form template
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4" style="padding-top: 20px;">Upload Your Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info ml-0" type="submit">Upload</button>
</div>
</form>
The problem is that your <slug:slug> will capture values like new as well. So that path will "fire", and the view will find out that there is no Post object with 'new' as slug.
You can swap the path(…)s, but then you can never access a Post with as slug new. As a rule of thumb it is better to make path(…)s that are not overlapping, for example:
app_name = 'score'
urlpatterns = [
path('', PostListView.as_view(), name='score'),
path('post/<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
path('new/', PostCreateView.as_view(), name='post-create'),
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
]
I am trying to use Ajax to submit a like button without getting the page refreshing, I have been getting several errors previously but now I am getting this error:
django.urls.exceptions.NoReverseMatch: Reverse for 'like_post' with arguments '('',)' not found. 1 pattern(s) tried: ['score/like/(?P<pk>[0-9]+)$']
I am not sure what is the reason. Need help to identify the error.
Here is the view:
class PostDetailView(DetailView):
model = Post
template_name = "post_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
stuff = get_object_or_404(Post, id=self.kwargs['pk'])
total_likes = stuff.total_likes()
liked = False
if stuff.likes.filter(id=self.request.user.id).exists():
liked = True
context["total_likes"] = total_likes
context["liked"] = liked
return context
def LikeView(request, pk):
# post = get_object_or_404(Post, id=request.POST.get('post_id'))
post = get_object_or_404(Post, id=request.POST.get('id'))
like = False
if post.likes.filter(id=request.user.id).exists():
post.likes.remove(request.user)
like = False
else:
post.likes.add(request.user)
like = True
context["total_likes"] = total_likes
context["liked"] = liked
if request.is_ajax:
html = render_to_string('like_section.html', context, request=request)
return JsonResponse({'form': html})
Here is the url.py updated:
urlpatterns = [
path('user/<str:username>', UserPostListView.as_view(), name='user-posts'),
path('', PostListView.as_view(), name='score'),
path('who_we_Are/', who_we_are, name='who_we_are'),
path('<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('like/<int:pk>', LikeView, name='like_post'),
path('new/', PostCreateView.as_view(), name='post-create'),
path('<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete')
]
Here is the template:
<form class="mt-0" action="{% url 'score:like_post' post.pk %}" method='POST'>
{% csrf_token %}
<strong> Likes: {{total_likes}} </strong>
{% if user.is_authenticated %}
{% if liked %}
<button id='like' type='submit' name='post_id' class= "btn btn-danger btn-sm"
value="{{post.id}}"> Unlike </button>
{% else %}
<button id='like' type='submit' name='post_id' class= "btn btn-primary btn-sm"
value="{{post.id}}"> Like </button>
{% endif %}
{% else %}
<p><small> Login to Like </small></p>
{% endif %}
</form>
here is the ajax
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<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 "score:like_post" post.pk %}', <---- Error in this line
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>
You need to send the post object in as context.
class PostDetailView(DetailView):
model = Post
template_name = "post_detail.html"
def get_context_data(self, *args, **kwargs):
context = super(PostDetailView, self).get_context_data()
post = get_object_or_404(Post, id=self.kwargs['pk'])
content["post"] = post
total_likes = post.total_likes()
liked = False
if post.likes.filter(id=self.request.user.id).exists():
liked = True
context["total_likes"] = total_likes
context["liked"] = liked
return context
I am now implementing a comment function on the post_detail page.
but occurred comment_create() got an unexpected keyword argument 'pk' error.
I also tried to change the def comment_creat(request, post_pk): part to def comment_creat(request, pk): on views.py.
and I try {% url 'comment_create' pk=post.pk %} --> post_pk=post.pk
views.py
#login_required
def comment_create(request, post_pk):
if request.method == 'POST':
post = get_object_or_404(Post, pk=post_pk)
content = request.POST.get('content')
com_user = request.user
if not content:
messages.info(request, 'Write please')
return redirect('post_detail', post_pk)
Comment.objects.create(post=post, comment_user=com_user, comment_content=content)
return redirect('post_detatil', post_pk)
urls.py
path('post_detail/<int:pk>/comment_create/',views.comment_create, name='comment_create')
post_detail.html
<form action="{% url 'comment_create' pk=post.pk %}" method="POST">
{% csrf_token %}
<input type="text", name="content", placeholder="comment...">
<input type="submit", value="Go">
</form>
Please help me.
In your view, the name of the argument is post_pk:
#login_required
def comment_create(request, post_pk):
# ...
but in your URL patterns, you use just pk:
path('post_detail/<int:pk>/comment_create/',views.comment_create, name='comment_create')
You can rename any of the two, but renaming the parameter in the urls.py, will result in updating all {% url ... %}s for that view as well, so it is likely that renaming the parameter in the view, will result in less editing:
#login_required
def comment_create(request, pk):
if request.method == 'POST':
post = get_object_or_404(Post, pk=pk)
content = request.POST.get('content')
com_user = request.user
if not content:
messages.info(request, 'Write please')
return redirect('post_detail', pk)
Comment.objects.create(post=post, comment_user=com_user, comment_content=content)
return redirect('post_detatil', pk)
Note that typically retrieving and validating data is done through a Form, not by the view itself.
I have a view that sub classes from Django registration 1.0:
class RegistrationView(RegistrationView):
pass
I do this because I would like to now make the post over AJAX. I'm not sure what methods I have to overwrite tho? any examples or advise?
This is my view.py:
{% block content %}
<form method="post" action="" id="registration">
{{ form.as_p }}
<input type="submit" value="{% trans 'Submit' %}" />
</form>
<script>
$('#registration').submit(function(e){
e.preventDefault(); //prevent default form submit
$.ajax({
url: '/accounts/register/',
type: 'POST',
contentType: "application/json;charset=utf-8",
dataType: "json",
data: {
'csrfmiddlewaretoken': '{% csrf_token %}',
'id_username': $("#id_username").val(),
'id_email': $("#id_email").val()
},
success: function() {
alert('Test');
},
error: function(errorThrown){
console.log(errorThrown);
alert('Error');
alert(errorThrown);
}
});
});
Django registration 1.0 view
class RegistrationView(_RequestPassingFormView):
"""
Base class for user registration views.
"""
disallowed_url = 'registration_disallowed'
form_class = RegistrationForm
http_method_names = ['get', 'post', 'head', 'options', 'trace']
success_url = None
template_name = 'registration/registration_form.html'
def dispatch(self, request, *args, **kwargs):
"""
Check that user signup is allowed before even bothering to
dispatch or do other processing.
"""
if not self.registration_allowed(request):
return redirect(self.disallowed_url)
return super(RegistrationView, self).dispatch(request, *args, **kwargs)
def form_valid(self, request, form):
new_user = self.register(request, **form.cleaned_data)
success_url = self.get_success_url(request, new_user)
# success_url may be a simple string, or a tuple providing the
# full argument set for redirect(). Attempting to unpack it
# tells us which one it is.
try:
to, args, kwargs = success_url
return redirect(to, *args, **kwargs)
except ValueError:
return redirect(success_url)
def registration_allowed(self, request):
"""
Override this to enable/disable user registration, either
globally or on a per-request basis.
"""
return True
def register(self, request, **cleaned_data):
"""
Implement user-registration logic here. Access to both the
request and the full cleaned_data of the registration form is
available here.
"""
raise NotImplementedError
The "registration 1.0" app hasn't really been created to support ajax in the first place, so you have a lot of overriding to do.
Just to make the registration working you need something like this:
import json
from django.http import HttpResponse
from django.views.generic.edit import CreateView
from django.contrib.auth.models import User
from registration.views import RegistrationView
class AjaxableResponseMixin(object):
def get_form_kwargs(self):
kwargs = {'initial': self.get_initial()}
if self.request.method in ('POST', 'PUT'):
dict_ = self.request.POST.copy()
del dict_['csrfmiddlewaretoken']
kwargs.update({
'data': dict_,
'files': self.request.FILES,
})
return kwargs
def render_to_json_response(self, context, **response_kwargs):
data = json.dumps(context)
response_kwargs['content_type'] = 'application/json'
return HttpResponse(data, **response_kwargs)
def form_invalid(self, form):
response = super(AjaxableResponseMixin, self).form_invalid(form)
if self.request.is_ajax():
return self.render_to_json_response(form.errors, status=400)
else:
return response
def form_valid(self, request, form):
if self.request.is_ajax():
new_user = self.register(request, **form.cleaned_data)
data = {
'pk': new_user.pk,
}
return self.render_to_json_response(data)
else:
response = super(AjaxableResponseMixin, self).form_valid(request, form)
return response
class MyRegistrationView(AjaxableResponseMixin, RegistrationView):
def register(self, request, **cleaned_data):
del cleaned_data['password2']
user = User.objects.create_user(data['username'], data['email'], data['password1'])
return user
urls.py
(r'^accounts/register/', MyRegistrationView.as_view()),
(r'^accounts/', include('registration.backends.default.urls')),
html
<!DOCTYPE html>
<html>
<head>
<title></title>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
<form id="registration" action="." method="post">{% csrf_token %}
{{ form }}
<input type="submit" name="submit" value="Submit" />
</form>
<script type="text/javascript">
$('#registration').submit(function(e){
e.preventDefault();
$.ajax({
url: '/accounts/register/',
type: 'POST',
dataType: "json",
beforeSend: function (request) {
request.setRequestHeader("X-CSRFToken", $('input[name="csrfmiddlewaretoken"]').val());
},
data: $('#registration').serialize(),
success: function() {
console.log('success');
},
error: function(errorThrown){
console.log(errorThrown);
}
});
});
</script>
</body>
</html>