I'm having trouble making my comments editable. They work fine if I leave them uneditable, but I do want them editable. I think it has something to do with primary keys but I'm not quite getting the hang of it. I was able to edit comments earlier, but it would always edit the latest comment.
Here is my code:
models.py
class Tee_times(models.Model):
viable_courses = [
("Eslövs GK","Eslövs GK"),
("Lunds Akademiska GK","Lunds Akademiska GK"),
("Söderåsens GK","Söderåsens GK")
]
title = models.CharField(max_length=100, choices=viable_courses, default=1)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
player = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.pk})
class Comment(models.Model):
text = models.CharField(max_length=200, default="Write a comment")
tee_time = models.ForeignKey(Tee_times, related_name="comments", on_delete=models.CASCADE)
pub_date = models.DateTimeField(auto_now_add=True)
player = models.ForeignKey(User, on_delete=models.CASCADE)
class Meta:
ordering = ("pub_date",)
def __str__(self):
return f"{self.player} - {self.pub_date}"
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.tee_time.pk})
def set_time(self):
self.pub_date = models.DateTimeField(auto_now_add=True)
urls.py
urlpatterns = [
path('', TeeListView.as_view(), name="index"),
path('post/<int:pk>/', DetailTeeView.as_view(), name="post-detail"),
path('post/<int:pk>/comment/new/', CommentCreateView.as_view(), name="comment-create"),
path('post/<int:pk>/comment/<int:pkc>/update/', CommentUpdateView.as_view(), name="comment-update"),
path('post/<int:pk>/comment/<int:pkc>/delete/', CommentDeleteView.as_view(), name="comment-delete"),
path('post/new/', TeeCreateView.as_view(), name="post-create"),
path('post/<int:pk>/update/', TeeUpdateView.as_view(), name="post-update"),
path('post/<int:pk>/delete/', TeeDeleteView.as_view(), name="post-delete"),
path("second/", views.second, name="second"),
path("register/", user_views.register, name="Register")
]
views.py
```
class TeeListView(ListView):
model = Tee_times
template_name = "testapp/index.html"
context_object_name = "posts"
ordering = ["-pub_date"]
class DetailTeeView(DetailView):
model = Tee_times
class TeeCreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = Tee_times
fields = ["title",
"content"]
success_message = "New Tee Time Created!"
def form_valid(self, form):
form.instance.player = self.request.user
return super().form_valid(form)
class TeeDeleteView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, DeleteView):
model = Tee_times
success_url = "/"
success_message = f"The tee time was successfully deleted!"
def test_func(self):
tee_time = self.get_object()
if self.request.user == tee_time.player:
return True
else:
return False
class TeeUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Tee_times
fields = ["title",
"content"]
def form_valid(self, form):
form.instance.player = self.request.user
return super().form_valid(form)
# goes through userpassestexstmixin
def test_func(self):
tee_time = self.get_object()
if self.request.user == tee_time.player:
return True
else:
return False
class CommentCreateView(CreateView):
model = Comment
fields = ["text"]
def form_valid(self, form):
form.instance.tee_time_id = self.kwargs["pk"]
form.instance.player = self.request.user
return super().form_valid(form)
class CommentDeleteView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, DeleteView):
model = Comment
success_url = "/"
success_message = f"The comment was successfully deleted!"
def test_func(self):
comment = self.get_object()
if self.request.user == comment.player:
return True
else:
return False
class CommentUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Comment
fields = ["text"]
def form_valid(self, form):
form.instance.tee_time_id = self.kwargs["pk"]
form.instance.player = self.request.user
return super().form_valid(form)
# goes through userpassestexstmixin
def test_func(self):
comment = self.get_object()
if self.request.user == comment.player:
return True
else:
return False
the html page in question
<pre>
{% extends "testapp/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% load static %}
<article >
<img src="{{ object.player.profile.profile_picture.url }}">
<div >
<div >
<a href="{% url 'profile' object.player %}">{{ object.player }}</a>
<small >{{ object.pub_date }}</small>
{% if object.player == user %}
<a href="{% url 'post-update' object.id %}">Update</a>
<a href="{% url 'post-delete' object.id %}">Delete</a>
{% endif %}
</div>
<h2>{{ object.title }}</h2>
<p >{{ object.content }}</p>
</div>
</article>
{% for comment in object.comments.all %}
<article >
<div >
<div >
<a href="{% url 'profile' object.player %}">{{ comment.player }}</a>
<small >{{ comment.pub_date }}</small>
{% if comment.player == user %}
<a href="{% url 'comment-update' comment.id %}">Update</a>
<a href="{% url 'comment-delete' comment.id %}">Delete</a>
{% endif %}
</div>
<p >{{ comment.text }}</p>
</div>
</article>
{% endfor %}
<form>
<article >
<link rel="stylesheet" href="{% static 'testapp/button.css' %}">
<form>
<button formaction="{% url 'comment-create' object.id %}" type="submit" role="button">Comment</button>
</form>
</article>
</form>
{% endblock %}
</pre>
I know the <int:pkc> might not make sense - I just tried a bunch of stuff. And the problem with it all comes when i add these two lines, that are in the html file:
<pre>
<a href="{% url 'comment-update' comment.id %}">Update</a>
<a href="{% url 'comment-delete' comment.id %}">Delete</a>
</pre>
I get the following error:
"NoReverseMatch at /post/4/
Reverse for 'comment-update' with arguments '(4,)' not found. 1 pattern(s) tried: ['post/(?P<pk>[0-9] )/comment/(?P<pkc>[0-9] )/update/\\Z']"
I am very lost right now, and would be very thankful of some guidance...
CodePudding user response:
In your urls.py
path('post/<int:pk>/comment/<int:pkc>/update/', CommentUpdateView.as_view(), name="comment-update"),
path('post/<int:pk>/comment/<int:pkc>/delete/', CommentDeleteView.as_view(), name="comment-delete"),
You will see that each of these requires two variables, pk and pkc. However, when you are creating your URLS you only have one variable, comment.id
{% if comment.player == user %}
<a href="{% url 'comment-update' comment.id %}">Update</a>
<a href="{% url 'comment-delete' comment.id %}">Delete</a>
{% endif %}
You need to include the second variable, the pk for the post, for the URLs to match, eg
{% url 'comment-update' object.id comment.id %}