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 章 - 练习的主要内容,如果未能解决你的问题,请参考以下文章
翻译How To Tango With Django 1.5.4 第一章
tango with django(第三章 Django基础)
翻译How To Tango With Django 1.5.4 第三章
翻译How To Tango With Django 1.5.4 第五章
How to Find and Write VAG 7th Byte CS with Tango Key Programmer