NoReverseMatch using a path that has <str:pk> - django-views

How can i pass a urls path that has str:pk into my views and templates, I want to redirected a user to the viewPhoto template but when I click on read more, it's throw an error like this: Reverse for 'photo' not found. 'photo' is not a valid view function or pattern name. How can I pass this into my view and template ?
the urls:
path('view/<str:pk>/', views.viewPhoto, name='Photo'),
path('like/<str:pk>/', views.like, name='Photo'),
the views:
def like(request, pk):
post = Photo.objects.get(pk=pk)
liked = False
like = Like.objects.filter(user=request.user, post=post)
if like:
like.delete()
else:
like = True
Like.objects.create(user=request.user, post=post)
resp = {
'liked': liked
}
response = json.dumps(resp)
return redirect('photo')
return HttpResponse(response, content_type = "application/json")
viewPhoto view:
def viewPhoto(request, pk):
post = get_object_or_404(Photo, id=pk)
photo = Photo.objects.get(id=pk)
liked = [i for i in Photo.objects.all() if like.objects.filter(user= request.user,
post = i )]
return render(request, 'photo.html', {'photo': photo, 'post': post, 'liked': liked})
this is how i pass my url in the home emplate:
<a href="{% url 'Photo' photo.id %}" class="btn btn-outline-primary btn-sm m-1">Read
More</a>

You would do something like this to avoid url conflicts :
path('view/<int:pk>/', views.viewPhoto, name='view_photo'),
path('like/<int:pk>/', views.like, name='user_likes'),
# this is for the viewPhoto
<a href="{% url 'view_photo' photo.id %}" class="btn btn-outline-primary btn-sm m-1">Read
More</a>
# Url for the like object, this would actaully help you avoid any form of url conflict
<a href="{% url 'user_likes' photo.id %}" class="btn btn-outline-primary btn-sm m-1">

Related

Django dynamic url arguements missing

Can someone spot the mistake? What i'm expecting to happen is to dynamically pass in the ids of the classes I have created, so that I can update an entry I created in a previous form.
Here is my HTML:
<td><a class="btn btn-sm btn-info" href="{% url 'update_type_4_service' type_4_service.order_reference.id type_4_service.id %}>Update</a></td>
Here is my urls:
path('order/<str:pk_test>/update_type_4_service/<str:pk>', views.updateType_4_Service, name="update_type_4_service"),
Here is my views:
def updateType_4_Service(request, pk_test, pk):
type_4_service = Type_4_Service.objects.get(id=pk)
type_4_service_form = Type_4_ServiceForm(instance=type_4_service)
if request.method == 'POST':
type_4_service_form = Type_4_ServiceForm(request.POST, order_reference=order)
type_4_service_form.instance.order_reference = order
if type_4_service_form.is_valid():
type_4_service_form.save()
return redirect('/')
context = {'type_4_service_form': type_4_service_form}
return render(request, 'orchestration/type_4_service_form.html', context)
This is the error:
Reverse for 'update_type_4_service' with arguments '('', '')' not found. 1 pattern(s) tried: ['order/(?P<pk_test>[^/]+)/update_type_4_service/(?P<pk>[^/]+)\\Z']
Try passing the name too:
<td>
<a
class="btn btn-sm btn-info"
href="{% url 'update_type_4_service' pk_test=type_4_service.order_reference.id pk=type_4_service.id %}"
>
Update
</a>
</td>

I added a Like model but I don't know how to increase the number of like

I created a Blog app, and i want to add a Like button to each post in the Blog, how can i do this ?
how can i make this happen in view and the template ?
the models:
class Like(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Photo, on_delete=models.CASCADE)
def __str__(self):
return str(self.user)
the view:
def viewPhoto(request, pk):
post = get_object_or_404(Photo, id=pk)
photo = Photo.objects.get(id=pk)
return render(request, 'photo.html', {'photo': photo, 'post': post })
In other to use the like functionality you do something like this, but i hope you know how to work the frontend part, in your html?
def like(request, pk):
post = Photo.objects.get(pk=pk)
liked= False
like = Like.objects.filter(user=request.user, post=post)
if like:
like.delete()
else:
liked = True
Like.objects.create(user=request.user, post=post)
resp = {
'liked':liked
}
response = json.dumps(resp)
return redirect('') # redirect to any url after the object has been liked
return HttpResponse(response,content_type = "application/json")
You would need to put the liked object in any view that would prefer to have the like functionality:
def viewPhoto(request, pk):
post = get_object_or_404(Photo, id=pk)
photo = Photo.objects.get(id=pk)
liked = [i for i in Photo.objects.all() if Like.objects.filter(user=request.user, post=i)]
return render(request, 'photo.html', {'photo': photo, 'post': post ,'liked':liked})
Html template this is just to give you an idea on how to do that in your html , since i don't no what type of script or css you are using. so the button might not look like a thumb in your case.
<button class="btn btn-white mr-3 like" id="{{ post.id }}">
{% if post in liked %}
<a href="{% url 'blog:like' post.pk %}" id="likebtn{{ post.pk }}"
class="flex items-center space-x-2">
<div> Unlike</div>
</a>
{% else %}
<a href="{% url 'blog:like' post.pk %}" id="likebtn{{ post.pk }}" class="flex items-center space-x-2">
<div>Like</div>
</a>
{% endif %}
</button>

NoReverseMatch at /options/ Reverse for 'sales' with arguments '('',)' not found. 1 pattern(s) tried: ['sales/(?P<pk>\\d+)/$']

I am trying to learn django and I have encountered this error. It has persisted irrespective of the fact that I have tried the available SO remedies but for some reason, it refuses to go away. Can someone please see an error anywhere.
show_options.html
<a class="btn btn-sm btn-block bg-dark" style="color: black;" href="{% url 'Management:addProduct' %}"> Add </a>
**<a class="btn btn-sm btn-danger" href="{% url 'Management:sales' add_user_sales.pk %}"> Add Sales </a>**
<a class="btn btn-sm btn-danger" href="{% url 'Management:total' %}"> View Total </a>
function to render my show_options page
def show_options(request):
return render(request, 'show_options.html', {})
function add_user_sales
#login_required
def add_user_sales(request , pk):
current_user = request.user
context = {}
context["data"] = MadeSale.objects.get(id=pk)
profiles = UserProfile.get_profile()
for profile in profiles:
if profile.profile_name.id == current_user.id:
if request.method == 'POST':
form = SalesForm(request.POST)
if form.is_valid():
upload = form.save(commit=False)
upload.posted_by = current_user
upload.profile = profile
upload.save()
messages.success(request, f'Hi, Your data has successfully been updated' )
return redirect('addProduct')
else:
form = SalesForm()
return render(request,'addProduct.html',{"user":current_user,"form":form}, context)
my app urls
from django.conf.urls import url
from . import views
from django.conf import settings
from django.conf.urls.static import static
from rest_framework.authtoken.views import obtain_auth_token
app_name = 'Management'
url(r'^sales/(?P<pk>\d+)/$', views.add_user_sales, name='sales')
,

Django Error: NoReverseMatch at / Reverse for 'like-post' not found

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.

User can post comment only after login in Django

I'm coding a news website,I want the user can submit the comment of the news only after they have logged in,if not,the website will return to login.html.
Now I have made it that only the user who have logged in can submit a comment,the issue is once I log off and submit a comment the error says:
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x10fed10b8>>": "NewsComments.user" must be a "UserProfile" instance.
Note:I have rewrote the User models and rename it UserProfile .It works very well.
Here is my news/views.py:
def newsDetailView(request, news_pk):
news = News.objects.get(id=news_pk)
title = news.title
author = news.author_name
add_time = news.add_time
content = news.content
category = news.category
tags = news.tag.annotate(news_count=Count('news'))
all_comments = NewsComments.objects.filter(news=news)
comment_form = CommentForm(request.POST or None)
if request.method == 'POST' and comment_form.is_valid():
comments = comment_form.cleaned_data.get("comment")
comment = NewsComments(user=request.user, comments=comments, news=news)
comment.save()
return render(request, "news_detail.html", {
'title': title,
'author': author,
'add_time': add_time,
'content': content,
'tags': tags,
'category': category,
'all_comments': all_comments,
'comment_form': comment_form
})
Here is my news.detail.html
<form method="POST" action="">{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1"><h5>评论 <i class="fa fa-comments"></i></h5></label>
<textarea id="js-pl-textarea" class="form-control" rows="4"
placeholder="我就想说..." name="comment"></textarea>
<div class="text-center mt-3">
<input type="submit" id='js-pl-submit' class="btn btn-danger comment-submit-button" value='Submit'>
</input>
</div>
</div>
</form>
Here is my urls.py:
path('-<int:news_pk>', newsDetailView, name="news_detail"),
You could use djangos login-required-decorator.
#login_required
def newsDetailView(request, news_pk):
...
EDIT to expand the idea from my comments.
You could have two views, one with the login_required decorator. (You could also use class-based-views (CBV) if you prefer)
def view_news_details(request, news_pk):
...
#login_required
def post_comments(request, news_pk):
...
Each view would have their own url:
url(r'^(?P<news_pk>[0-9]+)/$', views.view_news_details, name='view-details'),
url(r'^(?P<news_pk>[0-9]+)/comment/$', views.post_comments, name='comment'),
Then you can have only one template but with conditional rendering. This template will be rendered by the view views.view_news_details, but the form will send its data to the other view (note the forms action attribute).
... display the news details here ...
{% if request.user.is_authenticated %}
<form method="POST" action="{% url 'comment' news_instance.pk %}">
... here goes the content of the form ...
</form>
{% endif %}
Redirect the user to your login view before let him submit any data in your views.py :
# Codes here
if request.method == 'POST': # We separe those two "if statements", because
# We want to redirect the user to login even if the form is not valid, User can bypass your security concern
# For Django < 2.0, use it with () if request.user.is_authenticated():
if request.user.is_authenticated:
return redirect("login_url_name") # Or HttpResponseRedirect("login_url")
if comment_form.is_valid():
comments = comment_form.cleaned_data.get("comment")
# Rest of codes
Important
In your template, give access to the form to only authenticated users
{% if request.user.is_authenticated %}
<form method="POST" action="">{% csrf_token %}
<div class="form-group">
<label for="exampleFormControlTextarea1"><h5>评论 <i class="fa fa-comments"></i></h5></label>
<textarea id="js-pl-textarea" class="form-control" rows="4"
placeholder="我就想说..." name="comment"></textarea>
<div class="text-center mt-3">
<input type="submit" id='js-pl-submit' class="btn btn-danger comment-submit-button" value='Submit' />
</div>
</div>
</form>
{% endif %}
You can check whether the requested user is logged-in or not by user.is_authenticated() method, which returns a boolean value.
Try the following snippet,
def newsDetailView(request, news_pk):
# code
if request.method == 'POST' and comment_form.is_valid():
if not request.user.is_authenticated():
return HttpResponse("Please do login")
comments = comment_form.cleaned_data.get("comment")
comment = NewsComments(user=request.user, comments=comments, news=news)
comment.save()
return render(request, "news_detail.html", {
'title': title,
'author': author,
'add_time': add_time,
'content': content,
'tags': tags,
'category': category,
'all_comments': all_comments,
'comment_form': comment_form
})