While trying to display post-detail template in a blog app, I get an error No User matches a given query. In my models I am inheriting from User model. What seems the problem?
# Third party imports.
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
from django.utils import timezone
class Post(models.Model):
"""
Creates Model for a post in the database.
"""
title = models.CharField(max_length=100)
sub_title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
"""
A string representation of the post model.
"""
return self.title
def get_absolute_url(self):
"""
Creates the absolute url for a particular post.
"""
return reverse('blog:post-detail', kwargs={'pk': self.pk})
views.py
class PostDetailView(DetailView):
"""
View for a post's details
"""
model = Post
template_name ='blog/post_detail.html'
context_object_name = 'posts'
paginate_by = 3
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
urls.py:
# Third party imports.
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView,
UserPostListView,
)
# Local application imports.
from . import views
# Specifies the app's name.
app_name = "blog"
urlpatterns = [
path('', PostListView.as_view(), name='home'), # url for post list.
path('user/<str:username>/',
UserPostListView.as_view(),
name='user-posts'), # url for specific user post.
path('post/<int:pk>/',
PostDetailView.as_view(),
name='post-detail'), # url for post detail.
path('post/new/',
PostCreateView.as_view(),
name='post-create'), # url to create new post.
path('post/<int:pk>/update/',
PostUpdateView.as_view(),
name='post-update'), # url to update post.
path('post/<int:pk>/delete/',
PostDeleteView.as_view(), name='post-delete'), # url to delete post.
path('about/', views.about, name='about'), # url for about page.
]
home.html
{% extends 'blog/base.html' %}
{% load static %}
{% block crumb %}
{% for post in posts %}
<div class="post-preview">
<a href="{% url 'blog:post-detail' post.id %}">
<h2 class="post-title">{{ post.title }} </h2>
<h3 class="post-subtitle">{{ post.sub_title }} </h3>
</a>
<p class="post-meta" style="font-weight: 300;"> Posted by
<a class="text-muted">{{post.author}} on {{ post.date_posted|date:"F d, Y" }}</a>
</p>
</div>
<hr class="my-4" />
{% endfor %}
{% endblock %}
post_detail.html
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img"
src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2"
href="{% url 'blog:user-posts' object.author.username %}">{{ object.author }}
</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1"
href="{% url 'blog:post-update' object.id %}">Update
</a>
<a class="btn btn-danger btn-sm mt-1 mb-1"
href="{% url 'blog:post-delete' object.id %}">Delete
</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
{% endblock content %}
Some notes about things that are wrong that aren't directly related to the error you're getting.
You're using a DetailView (which shows the details for a single object) where it looks like you want a ListView (to list an user's posts).
Your context_object_name is in plural, which implies you do want a list of things.
paginate_by has no effect in DetailViews, since a single-object view couldn't be paginated.
Your view refers to a blog/post_detail.html, while you've pasted in a home.html. Which one is it?
You say "In my models I am inheriting from User model.", but it looks like you're not importing a custom User model, but the default from django.contrib.auth.models import User. If you really are using a custom user model that inherits from BaseUser (not User), then that's wrong too.
The error itself, I imagine (since you're not supplying us with the traceback), comes from
user = get_object_or_404(User, username=self.kwargs.get('username'))
which means you're not passing in an <username> in the URL for that view, or the <username> you're using is incorrect (and there is no such user). (You're not showing us your urls.py, so that's just a guess.)
(A Detail view's URL, in any case, would probably not refer to an username, but the unique identifier of the post.)
EDIT
Following the edit of the original post, the issue is that the get_queryset() is simply extraneous (since no filtering by username is required) in that DetailView, so the class can be simplified to:
class PostDetailView(DetailView):
model = Post
template_name ='blog/post_detail.html'
Related
I'm currently using UpdateView to add edit functionality to my Django project. It's working correctly insofar as I can edit my data, however when I submit the new data, it returns a NoReverseMatch error:
NoReverseMatch at /MyHealth/edit/8
Reverse for 'health_hub_history' not found. 'health_hub_history' is not a valid view function or pattern name.
I've researched it and added a get_absolute_url to my model, but it isn't working. Any help would be appreciated!
models.py:
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
class HealthStats(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
date = models.DateField(auto_now=True)
weight = models.DecimalField(max_digits=5, decimal_places=2)
run_distance = models.IntegerField(default=5)
run_time = models.TimeField()
class Meta:
db_table = 'health_stats'
ordering = ['-date']
def get_absolute_url(self):
return reverse('health_hub_history')
def __str__(self):
return f"{self.user} | {self.date}"
urls.py:
from django.urls import path
from django.contrib.staticfiles.storage import staticfiles_storage
from django.views.generic.base import RedirectView
from . import views
app_name = 'HealthHub'
urlpatterns = [
path('', views.home, name='home'),
path('MyHealth/', views.health_hub, name='health_hub'),
path('MyHealth/update', views.UpdateHealth.as_view(), name='health_hub_update'),
path('MyHealth/history', views.health_history, name='health_hub_history'),
path('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url("favicon.ico"))),
path('MyHealth/delete/<item_id>', views.delete_entry, name='health_hub_delete'),
path('MyHealth/edit/<int:pk>', views.EditHealth.as_view(), name='health_hub_edit'),
]
Views.py:
class EditHealth(UpdateView):
model = HealthStats
template_name = 'health_hub_edit.html'
fields = ['weight', 'run_distance', 'run_time']
health_hub_edit.html:
{% extends 'base.html' %}
{% load static %}
{%load crispy_forms_tags %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12 text-center">
<h1>Edit my Data</h1>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-auto text-center p-3">
<form method="post" style="margin-top: 1.3em;">
{{ form | crispy }}
{% csrf_token %}
<button type="submit" class="btn btn-signup btn-lg">Submit</button>
</form>
</div>
</div>
<div class="row justify-content-center">
</div>
</div>
{% endblock content %}
This error occurs because the django couldn't resolve the url
you didn't specify a primary key to base the query on.
you should modify this function
def get_absolute_url(self):
return reverse('health_hub_history', kwargs={'user': self.user})
also that health_history url is it a class based view you should add .as_view() to the end and observe camel casing
Lastly your url should observe the primary key specified
You can do this:
class EditHealth(UpdateView):
model = HealthStats
template_name = 'health_hub_edit.html'
fields = ['weight', 'run_distance', 'run_time']
def get(self, request):
return HttpResponse("health_hub")
def post(self, request):
# do something
return redirect("health_hub")
urlpatterns = patterns('',
url('', views.home, name='home'),
url('MyHealth/', views.health_hub, name='health_hub'),
url('^MyHealth/update', views.UpdateHealth.as_view(), name='health_hub_update'),
url('MyHealth/history', views.health_history, name='health_hub_history'),
url('favicon.ico', RedirectView.as_view(url=staticfiles_storage.url("favicon.ico"))),
url('MyHealth/delete/<item_id>', views.delete_entry, name='health_hub_delete'),
url('MyHealth/edit/<int:pk>', views.EditHealth.as_view(), name='health_hub_edit'),
)
This will solve your problem
I found the answer to this issue here:
https://stackoverflow.com/a/48068932/19053957
Looks like all I need to do was refer to the app name prior to the name of the URL in get_absolute_url()!
I am a beginner in learning code and am working on making a simple django site where users can write comments but I keep getting this error
My urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("profile/<str:name>/", views.profile, name="profile")
]
views.py
class NewPostForm(forms.Form):
title = forms.CharField(label="Title")
description = forms.CharField(widget=forms.Textarea)
def index(request):
if request.method == "POST":
form = NewPostForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
author = request.user
post = NewPost(title=title, description=description, author=author)
post.save()
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "network/index.html", {
"form": form
})
return render(request, "network/index.html", {
"form": NewPostForm(),
"posts": NewPost.objects.all()
})
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
pass
class NewPost(models.Model):
title = models.CharField(max_length=32)
description = models.CharField(max_length=256)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
and my index.html
{% extends "network/layout.html" %}
{% load static %}
{% load crispy_forms_tags %}
{% block body %}
<div class="form-group">
<form method="post" action="{% url 'index' %}">
{% csrf_token %}
{{form | crispy}}
<button class="btn btn-primary"> Post </button>
</form>
</div>
{% for post in posts %}
<div class="card">
<div class="card-body"> Title: {{post.title}} </div>
<div class="card-body"> Description: {{post.description}}</div>
<p> {{post.author.username}} </p>
<div class="card-body">
<a href="{% url 'profile' post.author.username %}">
#{{post.author.username}}
</a>
</div>
</div>
{% endfor %}
{% endblock %}
But I keep getting
NoReverseMatch at / Reverse for 'profile' with arguments '('',)' not found. 1 pattern(s) tried: ['profile/(?P[^/]+)/$']
It looks like the error is occurring with
<a href="{% url 'profile' post.author.username %}">
Make sure that each of these posts that you are looping through actually has an author and that each author has a username. Django won't be able to properly construct the url if post.author.username is None.
in this url : path("profile/str:name/", views.profile, name="profile")
do you have an view called profile?
and what does name in str:name refer to? username maybe? or author
you need to provide more details,
This is because you have an project with author I faced the similar issue.
Maybe you need to check your admin panel if there is a post without author that's probably the problem
NoReverseMatch at / Reverse for 'profile' with arguments '('',)' not found. 1 pattern(s) tried: ['profile/(?P[^/]+)/$']
It's means something missing in database thats you are working for in loops .Django won't be able to properly construct the url if somthing is blank. First go to the Django admit panel and find whats are missing.Example:Author,User,Admin etc.
If you define a post without assigning a profile (owner) to it, you get this error. in other words, something that Django wants (in your database) is blank!
You must go to the admin panel and check all posts that are defined, None of them should be without an owner.
So I'm trying to make a form to appear after the user is authenticated. When the user authenticated then the form appears on the home page but it never appears. I'm pretty sure I'm doing something wrong either in paths or view but can't figure this out. When I do the same code to external new template it works fine but I want the form to appear on the same page. Here is the code:
views.py
def vpn(request):
form = vpn_form(request.POST or None)
if form.is_valid():
form.save()
context ={
'form': form
}
return render(request, 'loginas/home.html', context)
urls.py
urlpatterns = [
# /
path('', views.home, name='home'),
# TEMPORARY
path('signin', views.sign_in, name='signin'),
path('signout', views.sign_out, name='signout'),
path('callback', views.callback, name='callback'),
path('', views.vpn, name='vpn'),
models.py
class VPN(models.Model):
name = models.CharField(max_length=125)
surname = models.CharField(max_length=125)
description = models.TextField()
date_to = models.DateField()
date_from = models.DateField()
forms.py
from .models import VPN
class vpn_form(forms.ModelForm):
class Meta:
model = VPN
fields = ('name', 'surname', 'description', 'date_to', 'date_from')
home template
{% extends "loginas/layout.html" %}
{% load static %}
{% block content %}
<div class="container">
<h1 class="d-flex justify-content-center"> </h1>
<p class="d-flex justify-content-center"></p>
{% if user.is_authenticated %}
<form>
{{form.as_p}}
</form>
{% else %}
<div class="d-flex justify-content-center">
Login
</div>
{% endif %}
{% endblock %}
And the page just loads empty no form present no errors in the console. Any help how to do this would be great
The UpdateView and DeleteView not saving data back to model
views.py
class ProjectList(ListView):
model = Project
template_name = 'mainapp/browse_app.html'
context_object_name = 'projs'
class ProjectUpdate(UpdateView):
model = Project
fields = ['pname','desc','emailID']
template_name = 'mainapp/project_form_edit.html'
class ProjectDelete(DeleteView):
model = Project
fields = ['id','pname','desc','emailID','updated_on']
template_name = 'mainapp/index.html'
success_url = reverse_lazy('mainapp/projs')
def form_display(request):
data = Project.objects.all()
return render(request,'mainapp/browse_page.html',{'data':data})
...
browse_page.html: has an edit link and a delete button and it displays the project details of the project which is clicked
{% for i in data %}
<center>
{{ i }}
</center>
<!-- Modal -->
<div id="costumModal13{{ forloop.counter }}" class="modal" data-easein="bounceLeftIn" tabindex="-1" role="dialog" aria-labelledby="costumModalLabel" aria-hidden="true">
<a class="btn btn-info btn-lg fa fa-pencil-square-o" href="{% url 'project_edit' pk=i.id %}" aria-hidden="true">Edit</a>
<form method="POST" action="{% url 'project_del' pk=i.id %}">
{% csrf_token %}<input type="submit" value="Delete">
</form>
{{ i.pname }}
{{ i.id }}
{{ i.updated_on }}
</div>
{% endfor %}
urls.py
from django.contrib import admin
from django.urls import path, include, re_path
from mainapp import views
from mainapp.views import ProjectUpdate, ProjectDelete
app_name = 'mainapp'
urlpatterns = [
path('browse/',views.form_display,name="browse_page"),
re_path(r'^browse/(?P<pk>\d+)/$', ProjectUpdate.as_view(), name='project_edit'),
re_path(r'^browse/delete/(?P<pk>\d+)/$', ProjectDelete.as_view(), name='project_del'),
]
On submitting the edited form:
On clicking on delete button:
Can you help me resolve these 2 errors?
1st image problem:
The url has index.html appended to the end. Your url is defined as /browse/7/
2nd image problem:
The namespace delimeter is : not /.
class ProjectDelete(DeleteView):
...
success_url = reverse_lazy('mainapp:projs')
In a Django project, I have used crispy forms to generate a form for a user to enter a title and a comment. For the comment section, I wish the user to be able to format their input (e.g add bold and italics tags, and also embed youtube videos, so use embed snippets). This is typical of a wordpress widget (admin) which allows text formatting for any text entry. Is it possible to do this with Django's Crispy forms, and if so, what is the best way forward? I am looking for suggestions for documentation, imports (any existing libraries compatible with Django?), as I as I couldn't find any, or an idea as to how to implement this manually. e.g. specifically, in which 'file' would it be implemented.
View of the html page (current)
View of the current form and text input on the comment area.
I've looked at the other questions-answers, but none answers this specifically.
This is the sort of functioanlity I would like to add to the form text input (for the content/comment box only)
Desired text input formatting options added
The current post_form.html code is below
{% extends "socialmedia/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">Post your message</legend>
{{form|crispy}}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Post</button>
</div>
</form>
</div>
{% endblock content %}
post_detail.html
{% extends "socialmedia/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{object.author.profile.image.url}}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y"}}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}"> Update </a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}"> Delete </a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
{% endblock content %}
models.py (relevant to the form)
from django.db import models
from django.utils import timezone #don't forget to add this
from django.contrib.auth.models import User
from django.urls import reverse
class Post(models.Model):
title=models.CharField(max_length=100)
content=models.TextField(max_length=300)
date_posted=models.DateTimeField(default=timezone.now)
views.py (again relating to the form)
from django.shortcuts import render,get_object_or_404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from .models import Post #import the Models Post
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from django.http import HttpResponse
# Create your views here.
class PostListView(ListView):
model = Post #what model to query in order to create the list
template_name = 'socialmedia/home.html'
context_object_name = 'posts'
ordering = ['-date_posted']#the minus sign before the -date_posted makes it newest first
paginate_by = 10
class UserPostListView(ListView):
model = Post #what model to query in order to create the list
template_name = 'socialmedia/user_posts.html'
context_object_name = 'posts'
paginate_by = 10
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get('username'))
return Post.objects.filter(author=user).order_by('-date_posted')
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin,CreateView):
model = Post
fields=['title','content']
def form_valid(self,form):
form.instance.author = self.request.user #set author to current loggged in user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin,UserPassesTestMixin, UpdateView):
model = Post
fields=['title','content']
def form_valid(self,form):
form.instance.author = self.request.user
return super().form_valid(form)
#this only lets the user of the post update the post.....
def test_func(self):
post = self.get_object() #this gets the current post
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin,UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object() #this gets the current post
if self.request.user == post.author:
return True
return False