Django学习笔记二
允许用户输入数据
创建表单,以添加新主题为例
- 在应用目录下新增forms.py文件,创建TopicForm模型
from django import forms
from .models import Topic
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
- 在应用目录下的urls.py文件中添加url解析规则
path('new_topic/', views.new_topic, name='new_topic'),
- 在应用目录下的views.py中定义new_topic方法,导入部分需要做一定修改
from django.urls import reverse
from django.http import HttpResponseRedirect
from .forms import TopicForm
- 方法定义同书上即可,我这里添加了
def new_topic(request):
"""添加一个新主题"""
if request.method != 'POST':
# 没有数据被提交,创建空表单
form = TopicForm()
else:
form = TopicForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
- 新增模板文件
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Add a new topic:</p>
<form action="{% url 'learning_logs:new_topic' %}" method='post'>
{% csrf_token %}
{{ form.as_p }}
<button name="submit">add topic</button>
</form>
{% endblock content %}
- 修改topics.html,添加到 new_topic.html页面的链接
<!-- 添加到 endblock 之前即可 -->
<a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>
设置用户账号
- 创建users应用
py manage.py startapp users
- 把users添加到settings.py的INSTALLED_APPS中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# My apps
'learning_logs',
'users',
]
- 设置URL解析规则,在项目目录下的urls.py中添加如下规则
path('users/', include('users.urls', namespace='users'))
- 在users应用目录下,新建ursl.py文件,并设置如下规则
"""为users应用定义URL模式"""
from django.urls import path
from django.contrib.auth.views import LoginView
from . import views
app_name = 'users'
urlpatterns = [
# Django自带的登录页面需要按以下方法调用
path('login/', LoginView.as_view(template_name='users/login.html'), name='login'),
# 注销和注册的URL解析规则和之前一样
path('logout/', views.log_out, name='logout'),
path('register/', views.register, name='register'),
]
登录、注销和注册
以登录为例
- 添加登录模板
{% extends "learning_logs/base.html" %}
{% block content %}
<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 %}
- 修改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 }}.
{% else %}
<a href="{% url 'users:login' %}">log in</a>
{% endif %}
</p>
{% block content %}{% endblock content %}
允许用户拥有自己的数据
- 限制非登录用户所能看到的数据,在应用目录下的views.py文件修改如下内容:
from django.contrib.auth.decorators import login_required
--snip--
@login_required
def topics(request):
"""展示所有的主题"""
--snip--
@login_required
def topic(request, topic_id):
--snip--
@login_required
def new_topic(request):
--snip--
@login_required
def new_entry(request, topic_id):
--snip--
@login_required
def edit_entry(request, entry_id):
--snip--
将数据与特定用户关联
- 修改Topic模型,添加owner字段
from django.contrib.auth.models import User
--snip--
# Create your models here.
class Topic(models.Model):
"""A topic the user is learning about"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
# 这里需要添加on_delete参数,否则会报错
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self) -> str:
"""Return a string representation of the model."""
return self.text
- 识别存在的用户
py manage.py shell
>>> from django.contrib.auth.models import User
>>> User.objects.all()
>>> for user in User.objects.all():
... print(user.username, user.id)
...
- 为之前添加的主题绑定用户
py manage.py makemigrations learning_logs
# 之后会提示你选择,选择第一个,这样会把之前的主题缺失的用户字段补上,随便选一个之前查到的用户id即可
# 把改动保存到数据库
py manage.py migrate
- 限制用户能访问的主题,修改learning_logs应用下的views.py文件
--snip--
@login_required
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)
--snip--
- 保护用户的主题(同样适用于其他页面),修改learning_logs应用下的views.py文件
from django.http import HttpResponseRedirect, Http404
--snip--
@login_required
def topic(request, topic_id):
"""展示一个单独的主题以及所有在该主题下的文章"""
topic = get_object_or_404(Topic, id=topic_id)
# 确保主题属于当前用户
if not check_topic_owner(request, topic):
raise Http404
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)