Реверс для 'edit_blog_post' с аргументами '('',)' не найден
Я пытаюсь создать способ редактирования отдельных постов блога из их индивидуального html. Вот соответствующие файлы и трассировка. Я немного понимаю, что проблема в blog_post.id из-за того, что blog_post не был перенесен из цикла for в blog_posts.html. Я читал о других людях, столкнувшихся с этой проблемой, и все они структурировали свои страницы так, чтобы кнопка редактирования находилась внутри оригинального цикла for, что вполне логично с точки зрения ретроспективы. Но теперь, когда я столкнулся с этой проблемой, я намерен понять, как я могу решить ее, не возвращаясь назад и не перестраивая свои страницы, чтобы они соответствовали другим, которые я видел.
urls.py
from django.urls import path
from . import views
app_name = 'blogs'
urlpatterns = [
# Home page
path('', views.index, name='index'),
path('blog_posts/', views.blog_posts, name='blog_posts'),
path('blog_posts/<int:blog_post_id>/', views.blog_post, name='blog_post'),
path('new_blog_post/', views.new_blog_post, name='new_blog_post'),
path('edit_blog_post/<int:blog_post_id>/', views.edit_blog_post, name='edit_blog_post'),
]
views.py
from .models import BlogPost
from .forms import BlogPostForm
def index(request):
"""Home page for Blog."""
return render(request, 'blogs/index.html')
def blog_posts(request):
"""Show all Blog Posts."""
blog_posts = BlogPost.objects.order_by('date_added')
context = {'blog_posts': blog_posts}
return render(request, 'blogs/blog_posts.html', context)
def blog_post(request, blog_post_id):
"""Show details of an individual blog post."""
blog_post = BlogPost.objects.get(id=blog_post_id)
title = blog_post.title
id = blog_post_id
date = blog_post.date_added
text = blog_post.text
context = {'title': title, 'text': text, 'date': date}
return render(request, 'blogs/blog_post.html', context)
def new_blog_post(request):
"""Add a new blog post"""
if request.method != 'POST':
# No data submitted, create a blank form.
form = BlogPostForm()
else:
# POST data submitted, process data.
form = BlogPostForm(data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:blog_posts')
# Display a blank or invalid form.
context = {'form': form}
return render(request, 'blogs/new_blog_post.html', context)
def edit_blog_post(request, blog_post_id):
"""Edit an existing blog post's title or text."""
blog_post = BlogPost.objects.get(id=blog_post_id)
if request.method != 'POST':
# Initial request, prefill with the current data.
form = BlogPostForm(instance=blog_post)
else:
# POST data submitted; process new data.
form = BlogPostForm(instance=blog_post, data=request.POST)
if form.is_valid():
form.save()
return redirect('blogs:blog_post', blog_post_id=blog_post.id)
context = {'blog_post': blog_post, 'form': form}
return render(request, 'blogs/edit_blog_post.html', context)
models.py
from django.db import models
class BlogPost(models.Model):
"""A post the user is posting on their blog."""
title = models.CharField(max_length=200)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model"""
return f"{self.title.title()}"
blog_posts.html
{% extends 'blogs/base.html' %}
{% block content %}
<p>Blog Posts</p>
<ul>
{% for blog_post in blog_posts %}
<li>
<a href="{% url 'blogs:blog_post' blog_post.id %}">{{ blog_post }}</a>
</li>
{% empty %}
<li>No posts have been made yet.</li>
{% endfor %}
</ul>
<a href="{% url 'blogs:new_blog_post' %}">Add a new blog post</a>
{% endblock content %}
blog_post.html
{% extends 'blogs/base.html' %}
{% block content %}
<p>Blog Post: {{ title }}</p>
<p>Entry:</p>
<p>{{ text }}</p>
<p>{{ date }}</p>
<p>
<a href="{% url 'blogs:edit_blog_post' blog_post.id %}">Edit Blog Post</a>
</p>
{% endblock content %}
edit_blog_post.html
{% extends "blogs/base.html" %}
{% block content %}
<p>
<a href="{% 'blogs:blog_post' blog_post.id %}">{{ blog_post }}</a>
</p>
<p>Edit Blog Post</p>
<form action="{% url 'blogs:edit_blog_post' blog_post.id %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">Save Changes</button>
</form>
{% endblock content %}
Повтор для 'edit_blog_post' с аргументами '('',)' не найден. Попытка 1 шаблона(ов): ['edit_blog_post/(?P<blog_post_id>[0-9]+)/\Z']
3 {% block content %}
4
5 <p>Blog Post: {{ title }}</p>
6
7 <p>Entry:</p>
8
9 <p>{{ text }}</p>
10 <p>{{ date }}</p>
11
12 <p>
13 <a href="{% url 'blogs:edit_blog_post' blog_post.id %}">Edit Blog Post</a>
14 </p>
15
16 {% endblock content %}
Если я правильно понял вопрос, вы получаете ошибку из-за того, что не указали необходимый ID в части построения URL в вашем шаблоне.
Вы отделяете элементы (дата, содержание и т.д.) для отправки в шаблон, но не передаете ID в то же время. Вы могли бы передавать ID в виде отдельной контекстной переменной, но это лишний набор текста без реальной награды.
Проще всего передавать пост сам через контекст и ссылаться на его атрибуты в шаблоне - мне кажется, так его легче читать. Таким образом, ID будет там, когда вам понадобится создать ссылку для редактирования, и если вы измените модель, чтобы иметь дополнительные поля, вам не нужно будет преобразовывать и добавлять в контекст, поскольку весь пост уже там.
views.py
def blog_post(request, blog_post_id):
"""Show details of an individual blog post."""
blog_post = BlogPost.objects.get(id=blog_post_id) #this is all we need
context = {"blog_post_context": blog_post}
return render(request, 'blogs/blog_post.html', context)
blog_post.html
{% extends 'blogs/base.html' %}
{% block content %}
<p>Blog Post: {{ blog_post_context.title }}</p>
<p>Entry:</p>
<p>{{ blog_post_context.text }}</p>
<p>{{ blog_post_context.date }}</p>
<p>
<a href="{% url 'blogs:edit_blog_post' blog_post_context.pk %}">Edit Blog Post</a>
</p>
{% endblock content %}
Если это все работает, рассмотрите возможность использования get_object_or_404 вместо Post.objects.get для дополнительной надежности.
Я предполагаю, что вы получили error
при попытке посетить страницу blog_post.html
. Если я прав, то вот подход, который вы могли бы использовать...
В вашем views.py
def blog_post(request, blog_post_id):
"""Show details of an individual blog post."""
# blog_post = BlogPost.objects.get(id=blog_post_id)
blog_post = get_object_or_404(id=blog_post_id) # Recommended
# Commented lines below are somewhat not necessary...
# title = blog_post.title
# id = blog_post_id
# date = blog_post.date_added
# text = blog_post.text
context = {'blog_post': blog_post}
return render(request, 'blogs/blog_post.html', context)
edit_blog_post.html
ожидает, что object
с именем blog_post
сможет получить доступ к blog_post.id
для {% url 'blogs:edit_blog_post' blog_post.id %}
.
Теперь внутри edit_blog_post.html
файла.
{% block content %}
<p>Blog Post: {{ blog_post.title }}</p>
<p>Entry:</p>
<p>{{ blog_post.text }}</p>
<p>{{ blog_post.date_added }}</p>
<p>
<a href="{% url 'blogs:edit_blog_post' blog_post.id %}">Edit Blog Post</a>
</p>
{% endblock content %}