python从入门到实践 Django项目示例(第二部分)

用户账户

让用户能够输入数据

添加新主题

过程:

  1. 创建表单
  2. 定义一个URL。
  3. 编写一个视图。
  4. 编写一个模板。

用于添加主题的表单

进入learning_logs应用文件夹,创建forms.py文件。

from django import forms
from .models import Topic


class TopicForm(forms.ModelForm):
    class Meta:
        model = Topic
        fields = ['text']
        labels = {
     'text': ''}

设置URL

进入learning_logs文件夹下的urls.py文件,添加URL。

from django.urls import path
from . import views

app_name = 'learning_logs'
urlpatterns = [
    path('', views.index, name='index'),
    # 展示所有主题的页面
    path('topics/', views.topics, name='topics'),
    # 特定主题的详细页面
    path('topics//', views.topic, name='topic'),
    # 用于添加新主题的网页
    path('new_topic/', views.new_topic, name='new_topic'),
    
]

添加视图

进入learning_logs文件夹下的views.py文件,添加视图。

from django.shortcuts import render,redirect
from .models import Topic
from .forms import TopicForm
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('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 %}
    <p>Add a new topic:p>

    <form action="{% url 'learning_logs:new_topic' %}" method='post'> 
        {% csrf_token %}
        {
    { form.as_p }}
        <button name="submit">Add topicbutton>
    form>
{% endblock content %}

添加一个从显示所有主题页面到新建主题页面的链接

进入模板文件夹下的topics.html文件,进行修改。

{% extends "learning_logs/base.html" %}

{% block content %}

    <p>Topicsp>

    <ul>
        {% for topic in topics %}
            <li>
                <a href="{% url 'learning_logs:topic' topic.id %}">{
    { topic }}a>
            li>
        {% empty %}
            <li>No topics have been added yet.li>
        {% endfor %}
    ul>

    <a href="{% url 'learning_logs:new_topic' %}">Add a new topica>
{% endblock content %}

运行服务

python manage.py runserver

结果图:python从入门到实践 Django项目示例(第二部分)_第1张图片
python从入门到实践 Django项目示例(第二部分)_第2张图片

添加新条目

过程和上面的类似

创建用于添加新条目的表单

进入form.py中添加新表单。

from django import forms
from .models import Topic
from .models import 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': 'Entry:'}
        widgets = {
     'text': forms.Textarea(attrs={
     'cols': 80})}

设置URL

进入learning_logs文件夹下的urls.py文件,添加URL。

from django.urls import path
from . import views


app_name = 'learning_logs'
urlpatterns = [
    path('', views.index, name='index'),
    # 展示所有主题的页面
    path('topics/', views.topics, name='topics'),
    # 特定主题的详细页面
    path('topics//', views.topic, name='topic'),
    # 用于添加新主题的网页
    path('new_topic/', views.new_topic, name='new_topic'),
    # 用于添加新条目的页面
    path('new_entry//', views.new_entry, name='new_entry'),
]

编写视图

进入learning_logs文件夹下的views.py文件,添加视图。

from django.shortcuts import render,redirect
from .models import Topic
from .forms import TopicForm, EntryForm
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('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 redirect('learning_logs:topic', topic_id=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 entrybutton>
    form>
{% endblock content %}

添加一个从主题页面到新建条目页面的链接

进入模板文件夹下的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 entrya>
    p>
    <ul>
        {% for entry in entries %}
        <li>
            <p>{
    { entry.date_added|date:'M d, Y H:i' }}p>
            <p>{
    { entry.text|linebreaks }}p>
        li>
        {% empty %}
            <li>There are no entries for this topic yet.li>
        {% endfor %}
    ul>
{% endblock content %}

运行服务

python manage.py runserver

结果图:
python从入门到实践 Django项目示例(第二部分)_第3张图片

编辑条目

设置URL

进入learning_logs的urls.py文件添加url。

from django.urls import path
from . import views


app_name = 'learning_logs'
urlpatterns = [
    path('', views.index, name='index'),
    # 展示所有主题的页面
    path('topics/', views.topics, name='topics'),
    # 特定主题的详细页面
    path('topics//', views.topic, name='topic'),
    # 用于添加新主题的网页
    path('new_topic/', views.new_topic, name='new_topic'),
    # 用于添加新条目的页面
    path('new_entry//', views.new_entry, name='new_entry'),
    # Page for editing an entry.
    path('edit_entry//', views.edit_entry, name='edit_entry'),
]

编写视图函数

进入learning_logs文件夹下的views.py文件,添加视图。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('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 redirect('learning_logs:topic', topic_id=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 request.method != 'POST':
        # 初次请求,使用当前条目填充表单
        form = EntryForm(instance=entry)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=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 changesbutton>
    form>
{% endblock content %}

修改topic.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 entrya>
    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 entrya>p>
        li>
        {% empty %}
            <li>There are no entries for this topic yet.li>
        {% endfor %}
    ul>
{% endblock content %}

运行服务

python manage.py runserver

结果图:
1.
python从入门到实践 Django项目示例(第二部分)_第4张图片

python从入门到实践 Django项目示例(第二部分)_第5张图片

创建用户账号

添加应用程序users

python manage.py startapp users

将应用程序添加到settings.py文件中

"""
Django settings for learning_log project.

Generated by 'django-admin startproject' using Django 2.2.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'k)m(tgw3!xy%umq1am8!5lowyrp1lr_v35lw)t3#zj&hgu(3l3'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    # My apps 自己添加的应用
    'learning_logs',
    'users',  # 新添内容
    # Default django apps 默认应用
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'learning_log.urls'

TEMPLATES = [
    {
     
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'learning_log.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
     
    'default': {
     
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
     
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

在learning_log文件夹中的urls.py文件中添加url。

"""learning_log URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/2.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('',include('learning_logs.urls')),
    path('users/', include('users.urls')),  # users的路由表
]

创建users应用下的子路由

在users的文件夹下创建一个urls.py文件。

from django.urls import path, include
"""为users应用程序定义url"""

app_name = 'users'
urlpatterns = [
    path('', include('django.contrib.auth.urls')),
]

编写模板

在users文件夹下创建templates文件夹,再在此文件夹下创建一个registration文件夹,在它的下面创建一个login.html。
因为使用Django默认的登录界面它自动查找registration文件夹。

{% 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 inbutton>
        <input type="hidden" name="next"
        value="{% url 'learning_logs:index' %}" />
    form>
{% endblock content %}

链接到登录页面

进入learning_logs文件夹下的模板文件夹下的base.html文件,添加登录页面。

<p>
    <a href="{% url 'learning_logs:index' %}">Learning Loga> - 
    <a href="{% url 'learning_logs:topics' %}">Topicsa>
    <a href="{% url 'learning_logs:topics' %}">Topicsa> -
    {% if user.is_authenticated %}
        Hello, {
    { user.username }}.
    {% else %}
        <a href="{% url 'users:login' %}">Log ina>
    {% endif %}
p>

{% block content %}{% endblock content %}

运行服务

python manage.py runserver

结果图片:
python从入门到实践 Django项目示例(第二部分)_第6张图片

注销

设置注销的URL

编写base.html文件,添加注销按钮。

<p>
    <a href="{% url 'learning_logs:index' %}">Learning Loga> -
    <a href="{% url 'learning_logs:topics' %}">Topicsa> -
    {% if user.is_authenticated %}
        Hello, {
    { user.username }}.
        <a href="{% url 'users:logout' %}">Log outa>
    {% else %}
        <a href="{% url 'users:login' %}">Log ina>
    {% endif %}
p>

{% block content %}{% endblock content %}

设置注销页面

在registration文件夹下创建logged_out.html文件

{
     % extends "learning_logs/base.html" %}

{
     % block content %}
    <p>You have been logged out. Thank you for visiting!</p>
{
     % endblock content %}

运行服务

结果:
python从入门到实践 Django项目示例(第二部分)_第7张图片

注册

设置注册页面的URL

进入users的文件夹下的urls.py文件编写url。

from django.urls import path, include
from . import views
"""为users应用程序定义url"""

app_name = 'users'
urlpatterns = [
    # 导入默认的登录视图
    path('', include('django.contrib.auth.urls')),
    # 注册页面
    path('register/', views.register, name='register'),
]

编写视图函数register()

进入users的文件夹下的views.py文件。

from django.shortcuts import render, redirect
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm
# 在这创建你的视图

def register(request):
    """注册新用户"""
    if request.method != 'POST':
        # 显示空的注册表单
        form = UserCreationForm()
    else:
        # 处理填写好的表单
        form = UserCreationForm(data=request.POST)
        if form.is_valid():
            new_user = form.save()
            # 让用户自动登录,再重定位到主页
            login(request, new_user)
            return redirect('learning_logs:index')
    # 显示空白或无效表单
    context = {
     'form': form}
    return render(request, 'registration/register.html', context)

注册模板

在registration文件夹下创建register.html文件

{% extends "learning_logs/base.html" %}

{% block content %}
    <form method="post" action="{% url 'users:register' %}">
        {% csrf_token %}
        {
    { form.as_p }}
        <button name="submit">Registerbutton>
        <input type="hidden" name="next" value="{% url 'learning_logs:index' %}" />
    form>
{% endblock content %}

链接到注册页面

进入learning_logs文件夹下的模板文件夹下,修改base.html文件。

<p>
    <a href="{% url 'learning_logs:index' %}">Learning Loga> -
    <a href="{% url 'learning_logs:topics' %}">Topicsa> -
    {% if user.is_authenticated %}
        Hello, {
    { user.username }}.
        <a href="{% url 'users:logout' %}">Log outa>
    {% else %}
        <a href="{% url 'users:register' %}">Registera> -
        <a href="{% url 'users:login' %}">Log ina>
    {% endif %}
p>

{% block content %}{% endblock content %}

运行服务

得到的界面注册页面
python从入门到实践 Django项目示例(第二部分)_第8张图片

让用户拥有自己的数据

使用@login_required(装饰器)限制访问

限制对topics页面的访问

在learning_logs/views.py文件中进行修改。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('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 redirect('learning_logs:topic', topic_id=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 request.method != 'POST':
        # 初次请求,使用当前条目填充表单
        form = EntryForm(instance=entry)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

更改设置settings.py

进入settings.py文件

"""
Django settings for learning_log project.

Generated by 'django-admin startproject' using Django 2.2.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'k)m(tgw3!xy%umq1am8!5lowyrp1lr_v35lw)t3#zj&hgu(3l3'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# 我的设置
LOGIN_URL = 'users:login'

# Application definition
INSTALLED_APPS = [
    # My apps
    'learning_logs',
    'users',
    # Default django apps
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'learning_log.urls'

TEMPLATES = [
    {
     
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        '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',
            ],
        },
    },
]

WSGI_APPLICATION = 'learning_log.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
     
    'default': {
     
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
     
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
     
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

对‘学习笔记’进行全方面的限制

对learning_logs/views.py中的视图函数(除了index()函数),用装饰器进行限制。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


@login_required
def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')
    # 显示空白或无效表单。
    context = {
     'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


@login_required
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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空白或无效表单。
    context = {
     'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)


@login_required
def edit_entry(request, entry_id):
    """编辑既有条目"""
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # 初次请求,使用当前条目填充表单
        form = EntryForm(instance=entry)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

将数据关联到用户

修改Topic模型

进入models.py文件。

from django.db import models
from django.contrib.auth.models import User
# Create your models here.在这里创建模型


class Topic(models.Model):  # 继承Django的models包的Midel模块
    """
    用户学习的主题
    模型会在数据库中映射出一个数据库表。
    模型实际上是操作数据库的。
    文档链接 https://docs.djangoproject.com/zh-hans/2.2/topics/db/models/#fields
    """
    text = models.CharField(max_length=200)  # Topic的每一个属性都是数据库的一个字段
    date_added = models.DateTimeField(auto_now_add=True)  # 使用函数自动获取时间戳
    owner = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        """返回模型的字符串表示"""
        return self.text


class Entry(models.Model):
    """学到的有关某个主题的具体知识"""
    topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
    text = models.TextField()
    date_added = models.DateTimeField(auto_now_add=True)

    class Meta:
        verbose_name_plural = 'entries'

    def __str__(self):
        """返回模型的字符串表示"""
        return self.text[:50] + '...'

迁移数据库

按截图输入命令
python从入门到实践 Django项目示例(第二部分)_第9张图片

只允许用户自己访问自己的主题

对learning_logs的views.py文件进行修改。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.filter(owner=request.user).order_by('date_added')
    #topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


@login_required
def topic(request, topic_id):
    '''显示单个主题及其所有的条目'''
    topic = Topic.objects.get(id=topic_id)
    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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')
    # 显示空白或无效表单。
    context = {
     'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


@login_required
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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空白或无效表单。
    context = {
     'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)


@login_required
def edit_entry(request, entry_id):
    """编辑既有条目"""
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # 初次请求,使用当前条目填充表单
        form = EntryForm(instance=entry)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

保护用户的主题

再次对learning_logs的views.py文件进行修改。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
from django.http import Http404
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.filter(owner=request.user).order_by('date_added')
    #topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


@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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')
    # 显示空白或无效表单。
    context = {
     'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


@login_required
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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空白或无效表单。
    context = {
     'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)


@login_required
def edit_entry(request, entry_id):
    """编辑既有条目"""
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic

    if request.method != 'POST':
        # 初次请求,使用当前条目填充表单
        form = EntryForm(instance=entry)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

保护edit_entry页面

再次对learning_logs的views.py文件进行修改。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
from django.http import Http404
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.filter(owner=request.user).order_by('date_added')
    #topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


@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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')
    # 显示空白或无效表单。
    context = {
     'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


@login_required
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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空白或无效表单。
    context = {
     'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)


@login_required
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)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

将新主题关联到当前用户

再次对learning_logs的views.py文件进行修改。

from django.shortcuts import render,redirect
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
from django.contrib.auth.decorators import login_required
from django.http import Http404
# Create your views here. 在这创建你的视图


def index(request):
    '''学习笔记的主页面'''
    return render(request, 'learning_logs/index.html')


@login_required
def topics(request):
    """显示所有主题"""
    topics = Topic.objects.filter(owner=request.user).order_by('date_added')
    #topics = Topic.objects.order_by('date_added')
    content = {
     'topics': topics}
    return render(request,'learning_logs/topics.html',content)


@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:
        # post提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            new_topic = form.save(commit=False)
            new_topic.owner = request.user
            new_topic.save()
            #form.save()
            return redirect('learning_logs:topics')
    # 显示空白或无效表单。
    context = {
     'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


@login_required
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 redirect('learning_logs:topic', topic_id=topic_id)

    # 显示空白或无效表单。
    context = {
     'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)


@login_required
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)
    else:
        # POST提交的数据,对数据进行处理
        form = EntryForm(instance=entry, data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topic', topic_id=topic.id)
    context = {
     'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'learning_logs/edit_entry.html', context)

运行服务

python manage.py runserver

网站截图:
python从入门到实践 Django项目示例(第二部分)_第10张图片

python从入门到实践 Django项目示例(第二部分)_第11张图片
python从入门到实践 Django项目示例(第二部分)_第12张图片

点击查看下一部分

你可能感兴趣的:(python,django,python,web)