Tango with Django - 第 8 章 - 练习
Posted
技术标签:
【中文标题】Tango with Django - 第 8 章 - 练习【英文标题】:Tango with Django - Chapter 8 - Exercise 【发布时间】:2015-04-06 23:43:46 【问题描述】:我需要一些帮助才能使 add_page 函数正常工作。我对 html 非常陌生,甚至对 Django 也很陌生。我正在编写的章节可以在这里找到:http://www.tangowithdjango.com/book17/chapters/forms.html。目前我的相关文件如下所示:
Forms.py
from django import forms
from rango.models import Page, Category
class CategoryForm(forms.ModelForm):
name = forms.CharField(max_length=128, help_text="Please enter the category name.")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
slug = forms.CharField(widget=forms.HiddenInput(), required=False)
# An inline class to provide additional information on the form.
class Meta:
# Provide an association between the ModelForm and a model
model = Category
fields = ('name',)
class PageForm(forms.ModelForm):
title = forms.CharField(max_length=128, help_text="Please enter the title of the page.")
url = forms.URLField(max_length=200, help_text="Please enter the URL of the page.")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
class Meta:
# Provide an association between the ModelForm and a model
model = Page
# What fields do we want to include in our form?
# This way we don't need every field in the model present.
# Some fields may allow NULL values, so we may not want to include them...
# Here, we are hiding the foreign key.
# we can either exclude the category field from the form,
exclude = ('category',)
#or specify the fields to include (i.e. not include the category field)
#fields = ('title', 'url', 'views')
def clean(self):
cleaned_data = self.cleaned_data
url = cleaned_data.get('url')
# If url is not empty and doesn't start with 'http://', prepend 'http://'.
if url and not url.startswith('http://'):
url = 'http://' + url
cleaned_data['url'] = url
return cleaned_data
Views.py:
from django.shortcuts import render
from django.http import HttpResponse
from rango.models import Category, Page
from rango.forms import CategoryForm, PageForm
def index(request):
# Query the database for a list of ALL categories currently stored.
# Order the categories by no. likes in descending order.
# Retrieve the top 5 only - or all if less than 5.
# Place the list in our context_dict dictionary which will be passed to the template engine.
category_list = Category.objects.order_by('-likes')[:5]
page_list = Page.objects.order_by('-view')[:5]
context_dict = 'categories': category_list,
'pages': page_list
# Render the response and send it back!
return render(request, 'rango/index.html', context_dict)
def category(request, category_name_slug):
# Create a context dictionary which we can pass to the template rendering engine.
context_dict =
try:
# Can we find a category name slug with the given name?
# If we can't, the .get() method raises a DoesNotExist exception.
# So the .get() method returns one model instance or raises an exception.
category = Category.objects.get(slug=category_name_slug)
context_dict['category_name'] = category.name
context_dict['category_name_slug'] = category_name_slug
# Retrieve all of the associated pages.
# Note that filter returns >= 1 model instance.
pages = Page.objects.filter(category=category)
# Adds our results list to the template context under name pages.
context_dict['pages'] = pages
# We also add the category object from the database to the context dictionary.
# We'll use this in the template to verify that the category exists.
context_dict['category'] = category
except Category.DoesNotExist:
# We get here if we didn't find the specified category.
# Don't do anything - the template displays the "no category" message for us.
pass
# Go render the response and return it to the client.
print context_dict
return render(request, 'rango/category.html', context_dict)
def add_category(request):
# A HTTP POST?
if request.method == 'POST':
form = CategoryForm(request.POST)
# Have we been provided with a valid form?
if form.is_valid():
# Save the new category to the database.
form.save(commit=True)
# Now call the index() view.
# The user will be shown the homepage.
return index(request)
else:
# The supplied form contained errors - just print them to the terminal.
print form.errors
else:
# If the request was not a POST, display the form to enter details.
form = CategoryForm()
# Bad form (or form details), no form supplied...
# Render the form with error messages (if any).
return render(request, 'rango/add_category.html', 'form': form)
def add_page(request, category_name_slug):
try:
cat = Category.objects.get(slug=category_name_slug)
except Category.DoesNotExist:
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit=False)
page.category = cat
page.views = 0
page.save()
# probably better to use a redirect here.
return category(request, category_name_slug)
else:
print form.errors
else:
form = PageForm()
context_dict = 'form':form, 'category': cat
return render(request, 'rango/add_page.html', context_dict)
urls.py
from django.conf.urls import patterns, url
from rango import views
urlpatterns = patterns('',
url(r'^$', views.index, name='index'),
# url(r'^about/$', views.about, name='about'),
url(r'^add_category/$', views.add_category, name='add_category'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/add_page/$', views.add_page, name='add_page'),
url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category'),)
我认为这个 ^ 是我遇到问题的地方。我设法进入“添加页面”屏幕,但是当我尝试提交某些内容时,我收到一条错误消息,指出我只提供 1 个参数并且 add_page() 需要 2 个。我想我可能需要一个额外的 url类似于“add_category” URL,但这一定意味着其他 URL 指向错误的地方?
category.html
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1> category_name </h1>
% if category %
% if pages %
<ul>
% for page in pages %
<li><a href=" page.url "> page.title </a></li>
% endfor %
</ul>
% else %
<strong>No pages currently in category.</strong>
% endif %
<li><a href="/rango/category/ category_name_slug /add_page/">Add a New Page</a></li>
% else %
The specified category category_name does not exist!
% endif %
</body>
</html>
add_page.html:
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/add_page/">
% csrf_token %
% for hidden in form.hidden_fields %
hidden
% endfor %
% for field in form.visible_fields %
field.errors
field.help_text
field
% endfor %
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
【问题讨论】:
请把add_page.html模板贴出来,去掉不相关的category.html和除add_page之外的所有视图。 我认为 category.html 是相关的,因为我对其进行了更改。我添加了 add_page.html 您已经将表单发布到 /rango/add_page/,而不是 /category/whatever/add_page/,因此您必须有另一个 urls.py 条目来响应它:在哪里?可以发一下吗? 我明白这一点。我不明白的是我希望该网址将我带到哪里。我是否应该告诉按钮将我带到 /category/whatever/add_page/ 就像他们在下面的答案中暗示的那样?那不只会让我绕个圈子吗? 不,因为如果你 POST 到它,你的视图会做一些不同的事情:它处理表单并创建一个新页面。 【参考方案1】:我编辑了 add_page 函数以包含 category_name_slug:
def add_page(request, category_name_slug):
try:
cat = Category.objects.get(slug=category_name_slug)
except Category.DoesNotExist:
cat = None
if request.method == 'POST':
form = PageForm(request.POST)
if form.is_valid():
if cat:
page = form.save(commit=False)
page.category = cat
page.views = 0
page.save()
# probably better to use a redirect here.
return category(request, category_name_slug)
else:
print form.errors
else:
form = PageForm()
# made the change here
context_dict = 'form':form, 'category': cat, 'category_name_slug': category_name_slug
return render(request, 'rango/add_page.html', context_dict)
然后我将 add_page.html 编辑为如下所示:
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/category/ category_name_slug /add_page/">
% csrf_token %
% for hidden in form.hidden_fields %
hidden
% endfor %
% for field in form.visible_fields %
field.errors
field.help_text
field
% endfor %
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
【讨论】:
感谢分享。add_page.html
模板的修改不是那么明显。【参考方案2】:
如果你不想编辑你的views.py
随便做
<!DOCTYPE html>
<html>
<head>
<title>Rango</title>
</head>
<body>
<h1>Add a Page</h1>
<form id="page_form" method="post" action="/rango/category/ category /add_page/">
% csrf_token %
% for hidden in form.hidden_fields %
hidden
% endfor %
% for field in form.visible_fields %
field.errors
field.help_text
field
% endfor %
<input type="submit" name="submit" value="Create Page" />
</form>
</body>
</html>
但我有问题,它仍然无法保存在数据库中。
【讨论】:
以上是关于Tango with Django - 第 8 章 - 练习的主要内容,如果未能解决你的问题,请参考以下文章