一、添加新主题
建立表单,在models.py所在文件目录建立forms.py文件;
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
建立表单的目地是为了让用户能够输入新的主题信息,因此,需要为这项功能建立新的URL地址,在learning_logs/urls.py文件中输入如下内容:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),
# 用于添加新主题网页
path("new_topic/",views.new_topic,name='new_topic'),
]
在views.py中建立new_topic函数,与path想对应,代码如下,注意这里与书中不同了:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urlresolvers import reverse
from .models import Topic
from .forms import TopicForm
def index(request):
"""The home page for Learning Log."""
return render(request, 'learning_logs/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.filter(owner=request.user).order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic, and all its entries."""
topic = Topic.objects.get(id=topic_id)
# Make sure the topic belongs to the current user.
if topic.owner != request.user:
raise Http404
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
def new_topic(request):
"""Add a new topic."""
if request.method != 'POST':
# No data submitted; create a blank form.
form = TopicForm()
else:
# POST data submitted; process data.
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
创建new_topic.html 模板
{% extends "learning_logs/base.html" %}
{% block content %}
<h2>Add a new topic:</h2>
<form action="{% url 'learning_logs:new_topic' %}" method='post'>
{% csrf_token %}
{{form.as_p}}
{% buttons %}
<button name="submit">add topic</button>
{% endbuttons %}
</form>
{% endblock content %}
链接到new_topic页面,在topics中添加一个页面new_topic的链接:
topics.html模板如下:
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<h3>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</h3>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
<h3><a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a></h3>
{% endblock content %}
19.1.2 添加新条目
用于添加新条目的表单,创建一个与模型Entry相关联的表单,forms.py如下:
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
相应的urls当中,添加与之对应的地址:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),
# 用于添加新主题网页
path("new_topic/",views.new_topic,name='new_topic'),
# 用于添加新条目
path("new_entry/(?p<topic_id>\d+)/", views.new_entry,name='new_entry'),
]
同时,要是在视图当中添加相应窗口,views.py代码如下:
from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from .forms import TopicForm,EntryForm
from .models import Topic, Entry
# Create your views here.
def index(request):
return render(request,'learning_logs/index.html')
def topics(request):
topics =Topic.objects.filter(owner=request.user).order_by('date_added')
# topics =Topic.objects.order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
def topic(request,topic_id):
topic=Topic.objects.get(id=topic_id)
if topic.owner != request.user:
raise Http404
entries = topic.entry_set.order_by('-date_added')
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
def new_topic(request):
if request.method !='POST':
form = TopicForm()
else:
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
# form.save()
return(HttpResponseRedirect(reverse('learning_logs:topics')))
context = {'form':form}
return render(request,'learning_logs/new_topic.html',context)
def new_entry(request,topic_id):
"""在特定的主题中添加新条目"""
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
# 未提交数据创建一个空表单
form = EntryForm()
else:
# POST提交的数据对数据进行处理
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
context={'topic':topic,'form':form}
return render(request, 'learning_logs/new_entry.html',context)
创建模板new_entry.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p><a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a></p>
<p>Add a new entry:</p>
<form action="{%url 'learning_logs:new_entry' topic.id %}" method="post">
{%csrf_token%}
{{ form.as_p}}
<button name="submit">add entry</button>
</form>
{% endblock content%}
在特定主题页面增加new_entry的链接(属于前端HTML内容)
topic.html内容如下:
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
</p>
{% endblock content %}
19.1.3 创建一个条目,让用户能够编辑既有条目。
urls.py 文件代码如下:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),
# 用于添加新主题网页
path("new_topic/",views.new_topic,name='new_topic'),
# 用于添加新条目
path("new_entry/(?p<topic_id>\d+)/", views.new_entry,name='new_entry'),
# 编辑条目
path("edit_entry/(?p<entry_id>\d+))",views.edit_entry, name='edit_entry'),
]
views.py文件代码如下:
from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from .forms import TopicForm,EntryForm
from django.contrib.auth.decorators import login_required
from .models import Topic, Entry
# Create your views here.
def index(request):
return render(request,'learning_logs/index.html')
def topics(request):
topics =Topic.objects.filter(owner=request.user).order_by('date_added')
# topics =Topic.objects.order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
def topic(request,topic_id):
topic=Topic.objects.get(id=topic_id)
if topic.owner != request.user:
raise Http404
entries = topic.entry_set.order_by('-date_added')
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
def new_topic(request):
if request.method !='POST':
form = TopicForm()
else:
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
# form.save()
return(HttpResponseRedirect(reverse('learning_logs:topics')))
context = {'form':form}
return render(request,'learning_logs/new_topic.html',context)
def new_entry(request,topic_id):
"""在特定的主题中添加新条目"""
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
# 未提交数据创建一个空表单
form = EntryForm()
else:
# POST提交的数据对数据进行处理
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
context={'topic':topic,'form':form}
return render(request, 'learning_logs/new_entry.html',context)
这里有一个语句与书中不同:
from django.urls import reverse #如果你用的是django 2.0以上版本,这条语句是对的
模板new_entry.html代码如下:
{% extends "learning_logs/base.html" %}
{% block content %}
<p><a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a></p>
<p>Add a new entry:</p>
<form action="{%url 'learning_logs:new_entry' topic.id %}" method="post">
{%csrf_token%}
{{ form.as_p}}
<button name="submit">add entry</button>
</form>
{% endblock content%}
在topic主题当中添加new_entry,topic.html代码如下:
{%extends 'learning_logs/base.html' %}
{% block header %}
<h2>{{ topic}}</h2>
{% endblock header %}
{%block content%}
<body>Topic:{{topic}}</body>
<p>Entries:</p>
<p>
<a href="{%url 'learning_logs:new_entry' topic.id%}">add new entry</a>
</p>
<ul>
{%endblock content%}
19.1.3 编辑条目
首先在URL里面添加链接,learning_logs/urls.py 代码如下:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),
# 用于添加新主题网页
path("new_topic/",views.new_topic,name='new_topic'),
# 用于添加新条目
path("new_entry/(?p<topic_id>\d+)/", views.new_entry,name='new_entry'),
# 编辑条目
path("edit_entry/(?p<entry_id>\d+))",views.edit_entry, name='edit_entry'),
]
相应的views.py代码如下:
rom django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.urls import reverse
from .forms import TopicForm,EntryForm
from django.contrib.auth.decorators import login_required
from .models import Topic, Entry
# Create your views here.
def index(request):
return render(request,'learning_logs/index.html')
def topics(request):
topics =Topic.objects.filter(owner=request.user).order_by('date_added')
# topics =Topic.objects.order_by('date_added')
context = {'topics':topics}
return render(request,'learning_logs/topics.html',context)
@login_required
def topic(request,topic_id):
topic=Topic.objects.get(id=topic_id)
if topic.owner != request.user:
raise Http404
entries = topic.entry_set.order_by('-date_added')
context = {'topic':topic,'entries':entries}
return render(request,'learning_logs/topic.html',context)
@login_required
def new_topic(request):
if request.method !='POST':
form = TopicForm()
else:
form = TopicForm(request.POST)
if form.is_valid():
new_topic = form.save(commit=False)
new_topic.owner = request.user
new_topic.save()
# form.save()
return(HttpResponseRedirect(reverse('learning_logs:topics')))
context = {'form':form}
return render(request,'learning_logs/new_topic.html',context)
def new_entry(request,topic_id):
"""在特定的主题中添加新条目"""
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
# 未提交数据创建一个空表单
form = EntryForm()
else:
# POST提交的数据对数据进行处理
form = EntryForm(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
new_entry.topic = topic
new_entry.save()
return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
context={'topic':topic,'form':form}
return render(request, 'learning_logs/new_entry.html',context)
def edit_entry(request,entry_id):
entry=Entry.objects.get(id=entry_id)
topic = entry.topic
if topic.owner != request.user:
raise Http404
if request.method != 'POST':
form = EntryForm(instance=entry,data=request.POST)
else:
form=EntryForm(instance=entry,data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('learning_logs:topic',args=[topic.id]))
context = {'entry':entry, 'topic':topic,'form':form}
return render(request,'learning_logs/edit_entry.html',context)
模板edit_entry.html代码如下:
{% extends "learning_logs/base.html" %}
{% block content %}
<p><a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a> </p>
<p>Edit entry:</p>
<form action="{%url 'learning_logs:edit_entry' entry.id %}" method="post">
{% csrf_token %}
{{ form.as_p}}
<button name="submit">save changes</button>
</form>
{% endblock content%}
在特定的主题页面中添加edit_entry链接!topic.html代码如下:
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Topic: {{ topic }}</p>
<p>Entries:</p>
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
</p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
<p>{{ entry.text|linebreaks }}</p>
<p>
<a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a>
</p>
</li>
{% empty %}
<li>
There are no entries for this topic yet.
</li>
{% endfor %}
</ul>
{% endblock content %}
19.2 创建用户账户
19.2.1 创建程序users
python manage.py startapp users
在settings.py文件中添加app
INSTALLED_APPS = [
'users',
'learning_logs',
'bootstrap3',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
在根目录的urls.py中添加url链接
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('learning_logs.urls',namespace='learning_logs')),
path('users/',include('users.urls',namespace='users')),
]
app_name = 'learning_logs'
由此可以看出,所有应用的URL都应在根目录里面注册。
在users文件夹内,新建urls.py文件
from django.urls import path, include
from django.contrib.auth.views import LoginView
from .import views
from django.conf.urls import url
from django.urls import path, re_path
LoginView.template_name = 'login.html'
urlpatterns=[
re_path('login/',LoginView.as_view(template_name='login.html'),name='login'),
#re_path('logout/',LoginView.as_view(template_name='login.html'),name='logout'),
#re_path('register/',views.register,name='register'),
]
app_name = 'users'
注意:这里与书中代码不同,还是django版本的问题。另外,这里用的是re_path,你也可以用path
在users文件夹内建立templates文件夹,建立login模板,login.html代码如下:
{% extends "learning_logs/base.html" %}
{% block content %}
{% if form.errors %}
<p>Your username and password didn't match. Please try again.</p>
{% endif %}
<form method="post" action="{% url 'users:login' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">log in</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
(PS:这里面尤其要注意的一点是‘users:login’),这里是表示将实参设置为登录页面的URL,因此,大家注意‘login‘ 前后不能有任何空格,小编我就是多加了一个空格,结果死活就是找不到模板,也是醉了!
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a> -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>
{% block content %}{% endblock %}
19.2.3 注销
修改users/urls.py文件,代码如下:
from django.urls import path, include
from django.contrib.auth.views import LoginView
from .import views
from django.conf.urls import url
from django.urls import path, re_path
# from django.contrib.auth.views import login
LoginView.template_name = 'login.html'
urlpatterns=[
# url(r'^login/',LoginView.as_view(template_name='users/login.html'),name='login')
re_path('login/',LoginView.as_view(template_name='login.html'),name='login'),
# path('login/',LoginView.as_view(template_name='users/login.html'),name="login"),
re_path('logout/',LoginView.as_view(template_name='login.html'),name='logout'),
]
app_name = 'users'
这里还是,path与re_path都可以。
相应的,要在views.py中重新定义视图users/views.py,代码如下:
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth import logout
def logout_view(request):
"""Log the user out."""
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))
在base.html中添加链接:
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a> -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
</p>
--snip
{% block content %}{% endblock %}
19.2.4 注册页面
还是在users/urls.py中增加URL链接
from django.urls import path, include
from django.contrib.auth.views import LoginView
from .import views
from django.conf.urls import url
from django.urls import path, re_path
# from django.contrib.auth.views import login
LoginView.template_name = 'login.html'
urlpatterns=[
re_path('login/',LoginView.as_view(template_name='login.html'),name='login'),
re_path('logout/',LoginView.as_view(template_name='login.html'),name='logout'),
re_path('register/',views.register,name='register'),
]
app_name = 'users
然后在users/views.py中增加视图,views.py代码如下:
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import login,logout,authenticate
from django.contrib.auth.forms import UserChangeForm
def logout_view(request):
logout(request)
return HttpResponseRedirect(reverse('learning_logs:index'))
def register(request):
if request.method != 'POST':
form = UserCreationForm()
else:
form = UserCreationForm(data=request.POST)
if form.is_valid():
new_user = form.save()
authenticated_user = authenticate(username=new_user.username,password=request.POST['password1'])
login(request,authenticated_user)
return HttpResponseRedirect(reverse(('learning_logs:index')))
context = {'form' : form}
return render(request,'register.html',context)
这里面要记住一下几点:1、from django.urls import reverse #与书中不同
2、return render(request,'register.html',context) # register.html 路径的问题比较头疼,路径不对容易找不到模板,因此有两种方法,一是增加OS模块(这个比较复杂),二是比较简单一点的,在setting.py文件中增加模板路径,代码如下:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR,'templates','users')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
大家主要看这段'DIRS': [os.path.join(BASE_DIR,'templates','users')], 反正我是小白,我也不知道这段具体是什么意思,大家有兴趣可以找一下,其实我们对于django的框架还需要在仔细阅读一下,非计算机专业真的很难懂这些东西!
最后是注册模板,register.html代码如下:
{% extends "learning_logs/base.html" %}
{% block content %}
<form method="post" action="{% url 'users:register' %}">
{% csrf_token %}
{{ form.as_p }}
<button name="submit">register</button>
<input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
</form>
{% endblock content %}
最后,在基础模板中增加链接,代码如下,base.html
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a> -
{% if user.is_authenticated %}
Hello, {{ user.username }}.
<a href="{% url 'users:logout' %}">log out</a>
{% else %}
<a href="{% url 'users:register' %}">register</a> -
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>
{% block content %}{% endblock %}