美文网首页
5. PythonWeb应用程序Django1

5. PythonWeb应用程序Django1

作者: YangDxg | 来源:发表于2018-05-03 17:41 被阅读0次

    1.Django入门

    1. 准备

      Django是一个Web框架,一套用于帮助开发交互式网站的工具,Django能够响应网页请求,还能让你更轻松地读写数据库,管理用户等

      建立项目时,首先以规范的方式对项目进行描述,再建立虚拟环境,以便在其中创建项目

      通过编写一个名为"学习笔记"的Web应用程序进行学习
    2. 建立虚拟环境

      要使用Django,首先需要建立一个虚拟工作环境,虚拟环境时系统的一个位置,可以在其中安装包,并将其与其他Python包隔离(将项目的库与其他项目分离是有益的)

      为项目新建一个目录,将其命名为learning_log,切换到这个目录,并创建一个虚拟环境
    MacBook-Pro:learning_log yangdongxing$ python3 -m venv ll_env
    MacBook-Pro:learning_log yangdongxing$ 
    

    运行模块venv,创建一个名为ll_env的虚拟环境

    如果python版本比较早,安装virtualenv包

    $ pip install --user virtualenv
    

    使用virtualenv创建虚拟环境

    learning_log$ virtualenv ll_env
    New python executable in ll_env/bin/python Installing setuptools, pip...done. learning_log$
    
    1. 激活虚拟环境

      建立虚拟环境后,使用下面的命令激活
    MacBook-Pro:learning_log yangdongxing$ source ll_env/bin/activate
    (ll_env) MacBook-Pro:learning_log yangdongxing$ 
    

    这个命令运行ll_env/bin中的脚本activate。环境处于活动状态时,环境名将包含在括号内,此时,可以在环境中安装包,并使用已安装的包,在ll_envz中安装的包仅在该环境处于活动状态时才可用

    Windows中使用以下命令激活

    ll_env\Scripts\activate(不包含source)
    


    使用命令deactivate停止使用虚拟环境

    (ll_env) MacBook-Pro:learning_log yangdongxing$ deactivate
    MacBook-Pro:learning_log yangdongxing$ 
    
    1. 安装Django

      创建并激活虚拟环境后,就可以安装Django了
    MacBook-Pro:learning_log yangdongxing$ source ll_env/bin/activate
    (ll_env) MacBook-Pro:learning_log yangdongxing$ pip3 install Django
    Collecting Django
      Downloading https://files.pythonhosted.org/packages/23/91/2245462e57798e9251de87c88b2b8f996d10ddcb68206a8a020561ef7bd3/Django-2.0.5-py3-none-any.whl (7.1MB)
        100% |████████████████████████████████| 7.1MB 36kB/s 
    Collecting pytz (from Django)
      Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'ProtocolError('Connection aborted.', ConnectionResetError(54, 'Connection reset by peer'))': /simple/pytz/
      Using cached https://files.pythonhosted.org/packages/dc/83/15f7833b70d3e067ca91467ca245bae0f6fe56ddc7451aa0dc5606b120f2/pytz-2018.4-py2.py3-none-any.whl
    Installing collected packages: pytz, Django
    Successfully installed Django-2.0.5 pytz-2018.4
    You are using pip version 9.0.1, however version 10.0.1 is available.
    You should consider upgrading via the 'pip install --upgrade pip' command.
    (ll_env) MacBook-Pro:learning_log yangdongxing$ 
    
    1. 在Django中创建项目
    (ll_env) MacBook-Pro:learning_log yangdongxing$ django-admin.py startproject learning_log .
    (ll_env) MacBook-Pro:learning_log yangdongxing$ ls
    learning_log    ll_env      manage.py
    (ll_env) MacBook-Pro:learning_log yangdongxing$ ls learning_log
    __init__.py settings.py urls.py     wsgi.py
    

    新建项目(django-admin.py startproject learning_log .)创建了名为learning_log的项目。末尾又一个句点,是让新项目使用合适的目录结构,这样开发玩后可轻松的将应用程序部署到服务器

    句点不能忘,忘记了这个句点, 就将创建的文件和文件夹删除(ll_env除外),再重新运行这个命令。

    Django新建了一个名为 learning_log的目录。它还创建了一个名为manage.py的文件,这是一个简单的程序,它接受命令 并将其交给Django的相关部分去运行。我们将使用这些命令来管理诸如使用数据库和运行服务器 等任务。

    目录learning_log包含4个文件,其中最重要的是settings.py、urls.py和wsgi.py。文件 settings.py指定Django如何与你的系统交互以及如何管理项目。在开发项目的过程中,我们将修 改其中一些设置,并添加一些设置。文件urls.py告诉Django应创建哪些网页来响应浏览器请求。 文件wsgi.py帮助Django提供它创建的文件,这个文件名是web server gateway interface(Web服务 器网关接口)的首字母缩写。

    1. 创建数据库

      Django将大部分与项目相关的信息都存储在数据库中,因此需要创建一个供Django使用的数据库
    (ll_env) yangdongxingdeMacBook-Pro:learning_log yangdongxing$ python3 manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, sessions
    Running migrations:
      Applying contenttypes.0001_initial... OK
      Applying auth.0001_initial... OK
      Applying admin.0001_initial... OK
      Applying admin.0002_logentry_remove_auto_add... OK
      Applying contenttypes.0002_remove_content_type_name... OK
      Applying auth.0002_alter_permission_name_max_length... OK
      Applying auth.0003_alter_user_email_max_length... OK
      Applying auth.0004_alter_user_username_opts... OK
      Applying auth.0005_alter_user_last_login_null... OK
      Applying auth.0006_require_contenttypes_0002... OK
      Applying auth.0007_alter_validators_add_error_messages... OK
      Applying auth.0008_alter_user_username_max_length... OK
      Applying auth.0009_alter_user_last_name_max_length... OK
      Applying sessions.0001_initial... OK
    (ll_env) yangdongxingdeMacBook-Pro:learning_log yangdongxing$ ls
    db.sqlite3  learning_log    ll_env      manage.py
    

    将修改数据库成为迁移数据库,首次执行命令migrate时,将让Django确保数据库与项目的当前状态匹配。

    1. 查看项目

      使用命令runserver核实Django是否正确地创建了项目
    (ll_env) yangdongxingdeMacBook-Pro:learning_log yangdongxing$ python manage.py runserver
    Performing system checks...
    
    System check identified no issues (0 silenced).
    May 03, 2018 - 00:24:15
    Django version 2.0.5, using settings 'learning_log.settings'
    Starting development server at http://127.0.0.1:8000/
    Quit the server with CONTROL-C.
    

    Django启动了一个服务器,可以查看系统中地项目,浏览器打开http://localhost:8000/可以查看Django生成的网页

    image
    关闭服务器,使用control+C或Ctrl+C

    如果出现错误信息“That port is already in use”(指定端口已被占用),执行命令 manage.py runserver 8001,让Django使用另一个端口,如果端口依然不可用,使用8002,8003一次增大

    2.创建应用程序

    Django项目是由一系列应用程序组成,协同工作,让项目成为一个整体,目前只创建了一个应用程序,它将完成项目大部分工作。

    当前窗口运行着runserver,再打开一个终端窗口,切换到manage.py所在地目录,激活该虚拟环境,再执行命令startapp

    MacBook-Pro:learning_log yangdongxing$ source ll_env/bin/activate
    (ll_env) MacBook-Pro:learning_log yangdongxing$ python manage.py startapp learning_logs
    (ll_env) MacBook-Pro:learning_log yangdongxing$ ls
    db.sqlite3  learning_log    learning_logs   ll_env      manage.py
    (ll_env) MacBook-Pro:learning_log yangdongxing$ ls learning_logs/
    __init__.py apps.py     models.py   views.py
    admin.py    migrations  tests.py
    (ll_env) MacBook-Pro:learning_log yangdongxing$ 
    

    startapp appname命令让Django建立创建应用程序所需的基础设施,想再再项目目录下多了个learning_logs文件夹,打开这个文件夹,创建了多个文件,使用models.py来定义我们要再应用程序中管理的数据

    1. 定义模型

      打开文件models.py,查看文件中的内容
    from django.db import models
    
    # Create your models here.
    
    

    models.py中导入了模块models,在这里创建自己的模型,模型告诉Django如何处理应用程序中存储的数据,在代码层面,模型就是一个类,下面是表示用户将要存储的主题的模型

    from django.db import models
    
    # Create your models here.
    
    class Topic(models.Model):
        """用户学习的主题"""
        text = models.CharField(max_length=200)
        date_added = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            """返回模型的字符串表示"""
            return self.text
    

    属性CharFiled(由字符串或文本组成的数据,需要存储少量的文本,必须告诉Django该在数据库中预留多少空间,这里max_length设置成来200(即200个字符))

    属性date_added是一个DateTimeFiled(记录日期和时间的数据,传递了实参auto_add_now= True,每当用户创建新主题时,都让Django将这个属性自动设置成当前的日期和时间)

    https://docs.djangoproject.com/en/1.8/ref/models/fields/中查看模型中使用的各种字段

    Django调用str()来显示模型的简单表示,这里返回存储在属性text中的字符串(python2.7中,使用的方法是unicode())

    1. 激活模型

      使用模型,必须让Django将应用程序包含到项目中,打开learning/learning_log中的settings.py,查看那些应用程序安装在项目中
    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    ]
    

    这是一个元组,告诉Django项目是由那些应用程序组成的,将前面创建的应用程序添加到这个元组中

    # Application definition
    
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
    
        #我的应用程序
        'learning_logs',
    ]
    

    接下来,让Django修改数据库,使其能够存储与模型Topic相关的信息

    (ll_env) MacBook-Pro:learning_log yangdongxing$ python manage.py makemigrations learning_logs
    Migrations for 'learning_logs':
      learning_logs/migrations/0001_initial.py
        - Create model Topic
    (ll_env) MacBook-Pro:learning_log yangdongxing$ 
    

    命令makemigrations让Django确定该如何修改数据库,使其能够存储与我们定义的新模型相 关联的数据。输出表明Django创建了一个名为0001_initial.py的迁移文件,这个文件将在数据库中 为模型Topic创建一个表。

    应用上面的迁移,让Django修改数据库

    (ll_env) MacBook-Pro:learning_log yangdongxing$ python manage.py migrate
    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, learning_logs, sessions
    Running migrations:
      Applying learning_logs.0001_initial... OK
    

    最后的OK表明,Django确认为learning_logs应用迁移时一切正常

    每当修改管理的数据时,都采用下面三个步骤:修改models.py;对learning_logs调用makemigrations;让Django迁移项目

    3.Django管理网站

    1. 创建超级用户(具备所有权限的用户)
    (ll_env) MacBook-Pro:learning_log yangdongxing$ python manage.py createsuperuser
    Username (leave blank to use 'yangdongxing'): ll_admin
    Email address: 
    Password: 
    Password (again): 
    This password is too short. It must contain at least 8 characters.
    This password is too common.
    This password is entirely numeric.
    Password: 
    Password (again): 
    Superuser created successfully.
    (ll_env) MacBook-Pro:learning_log yangdongxing$ 
    

    用户名ll_admin

    Django并不存储输入的密码,而存储从该密码派生出来的一个字符串——散列值。每当你输入密码时,Django都计算其散列值,并将结果与存储的散列值进行比较

    1. 向管理网站注册模型

      Django自动在管理网站中添加了一些模型,如User和Group,但对于创建的模型,必须手工进行注册,在创建应用程序learning_logs时,Django在models.py所在的目录中创建了一个名为admin.py的文件
    from django.contrib import admin
    
    # Register your models here.
    

    向管理网站注册Topic

    from django.contrib import admin
    from learning_logs.models import Topic
    
    # Register your models here.
    admin.site.register(Topic)
    

    访问http://localhost:8000/admin/

    image
    输入刚才创建的超级用户的用户名和密码 image
    在这个网页中,能够添加和修改用户和用户组,还可以管理与刚才定义的模型Topic相关的数据

    添加主题

    单机Topic进入主题网页,还没有添加任何主题 image
    点击Add,在Text属性输入框输入Chess,保存(save) image
    在创建一个RockClimbing主题 image
    1. 定义模型Entry

      在学习笔记中添加的条目定义模型。每个条目都与特定主题相关联,这种关系被称为多对一关系,即多个条目可关联到同一个主题。
    from django.db import models
    
    # Create your models here.
    
    class Topic(models.Model):
        """用户学习的主题"""
        text = models.CharField(max_length=200)
        date_added = models.DateTimeField(auto_now_add=True)
    
        def __str__(self):
            """返回模型的字符串表示"""
            return self.text
    
    class Entry(models.Model):
        """学到的有关某个主题的具体知识"""
        #topic = models.ForeignKey(Topic)
        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]+"..."
    

    书上写的是topic = models.ForeignKey(Topic),报错init() missing 1 required positional argument: 'on_delete' ,原因是,Django 高版本中,需要写一个参数topic = models.ForeignKey(Topic,on_delete=models.CASCADE)

    第一个属性topic是一个ForeignKey实例。外键是一个数据库术语,它引用了数据库中的另一条记录;这些代码将每个条目关联到特定的主题。每个主题创建时,都给它分配了一个键(或ID)。需要在两项数据之间建立联系时, Django使用与每项信息相关联的键。稍后我们将根据这些联系获取与特定主题相关联的所有条目

    text属性是TextField实例,这种字段不需要长度限制

    在Entry类中嵌套了Meta类,Meta存储用于管理模型的额外信息,设置一个特殊属性,让Django在需要时使用Entries来表示多个条目。如果没有这个类, Django将使用Entrys来表示多个条目

    方法str()告诉Django,呈现条目时应显示哪些信息。由于条目包含的文本可能很长,让Django只显示text的前50个字符。添加了一个省略号,指出显示的并非整个条目。

    1. 迁移模型ENtry

      命令同上Topic
    python manage.py makemigrations learning_logs
    
    1. 向管理网站注册Entry

      命令同上,修改admin.py
    from django.contrib import admin
    from learning_logs.models import Topic,Entry
    
    # Register your models here.
    admin.site.register(Topic)
    admin.site.register(Entry)
    

    刷新http://localhost/admin/,进入Entries,点击Add,看到一个下拉列表,能够选择要为哪个主题创建条目,还有一个用于输入条目的文本框。从下拉列表中选择Chess,并添加一个条目

    image image
    再添加一个 image
    1. Django shell

      输入一些数据后,就可通过交互式终端会话以编程方式查看这些数据了。这种交互式环境称 为Django shell,可以用来测试项目和排除其故障
    (ll_env) MacBook-Pro:learning_log yangdongxing$ python manage.py shell
    Python 3.6.3 (v3.6.3:2c5fed86e0, Oct  3 2017, 00:32:08) 
    [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
    Type "help", "copyright", "credits" or "license" for more information.
    (InteractiveConsole)
    >>> from learning_logs.models import Topic
    >>> Top.objects.all()
    Traceback (most recent call last):
      File "<console>", line 1, in <module>
    NameError: name 'Top' is not defined
    >>> Topic.objects.all()
    <QuerySet [<Topic: Chess>, <Topic: Rock Climbing>]>
    >>> 
    
    


    遍历查询集,查看分配给每个主题对象的ID

    >>> topics = Topic.objects.all()
    >>> for topic in topics:
    ...     print(topic.id,topic)
    ... 
    1 Chess
    2 Rock Climbing
    >>> 
    


    直到对象ID后,就可以获取该对象并查看其任何属性

    >>> t = Topic.objects.get(id=1)
    >>> t.text
    'Chess'
    >>> t.date_added
    datetime.datetime(2018, 5, 3, 4, 52, 5, 942154, tzinfo=<UTC>)
    >>> 
    


    查看与主题关联的条目

    >>> t.entry_set.all()
    <QuerySet [<Entry: The opening is the first part of the game, roughly...>, <Entry: In the opening phase of the game, it’s important t...>]>
    >>> 
    

    每次修改模型后,都要重启shell,这样才能看到修改效果,退出shell会话,使用control+D

    4. 创建网页,学习笔记主页

    使用Django创建网页的过程通常分为三个阶段:定义URL,编写视图和编写模版

    1. 映射URL

      用户通过在浏览器中输入URL以及单击链接来请求网页,因此需要确定项目需要哪些 URL。主页的URL最重要,它是用户用来访问项目的基础URL。当前,基础URL(http://localhost:8000/)返回默认的Django网站,让我们知道正确地建立了项目。接下来将修改这一点,将这个基础URL映射到“学习笔记”的主页。
      打开项目主文件夹learning_log中的文件urls.py
    from django.contrib import admin
    from django.urls import path
    
    urlpatterns = [
        path('admin/', admin.site.urls),
    ]
    

    变量urlpatterns包含项目中的应用程序的URL。包含模块admin.site.urls,该模块定义了可在管理网站中请求的所有 URL。

    将learning_logs的URL添加进去

    from django.contrib import admin
    from django.urls import path,include
    
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('', include('learning_logs.urls', namespace='learning_logs')),
    ]
    


    在learning_logs下新建urls.py

    """定义learning_logs的URL模式""" 
    from django.conf.urls import url 
    from . import views
    
    app_name='learning_logs'
    
    urlpatterns = [ 
        # 主页
        url(r'^$', views.index, name='index'), ]
    

    书上没有app_name='learning_logs' ,加会报错Specifying a namespace in include() without providing an app_name 'django.co

    1. 编写视图,打开learning_logs中的文件views.py
    from django.shortcuts import render
    
    # Create your views here.
    

    为主页编写视图

    from django.shortcuts import render
    
    # Create your views here.
    
    def index(request):
        """学习笔记的主页"""
        return render(request,'learning_logs/index.html')
        pass
    
    image
    1. 创建其他网页

      创建俩个显示数据的网页,一个列出所有的主题,另一个显示特定主题的所有条目

      模版继承

      首先来创建一个名为base.html的模板,并将其存储在index.html所在的目录中。这个文件 包含所有页面都有的元素;其他的模板都继承base.html
    <p>
        <a href="{% url 'learning_logs:index' %}">Learning Log</a>
    </p>>
    
    {% block content %}{% endblock content %}
    


    子模版

    {% extends "learning_logs/base.html" %}
    
    {% block content %}
    {% endblock content %}
    

    子模板的第一行必须包含标签{% extends %},让Django知道它继 承了哪个父模板。文件base.html位于文件夹learning_logs中,因此父模板路径中包含learning_logs。 这行代码导入模板base.html的所有内容,让index.html能够指定要在content块预留的空间中添加 的内容。

    插入了一个名为content的{% block %}标签,以定义content块。不是从父模板 继承的内容都包含在content块中,在这里是一个描述项目“学习笔记”的段落

    使用标签{% endblock content %}指出了内容定义的结束位置。

    在子模板中,只需包含当前网页特有的内容。这不仅简化 了每个模板,还使得网站修改起来容易得多。要修改很多网页都包含的元素,只需在父模板中修 改该元素

    在大型项目中,通常有一个用于整个网站的父模板——base.html,且网站的每个主要部 2
    分都有一个父模板。每个部分的父模板都继承base.html,而网站的每个网页都继承相应 部分的父模板

    1. 显示所有主题的页面

      URL模式
    """定义learning_logs的URL模式""" 
    from django.conf.urls import url 
    from . import views
    
    app_name='learning_logs'
    
    urlpatterns = [ 
        # 主页
        url(r'^$', views.index, name='index'),
        
        # 显示所有的主题
        url(r'^topics/$', views.topics, name='topics'),
        ]
    


    视图

    from django.shortcuts import render
    from .models import Topic
    
    # Create your views here.
    
    def index(request):
        """学习笔记的主页"""
        return render(request,'learning_logs/index.html')
        passxxxxx
    
    def topics(request):
        """显示所有的主题"""
        topics = Topic.objects.order_by('date_added')
        context = {'topics':topics}
        return render(request,'learning_logs/topics.html',context)
        
    


    模版(新建topics.html)

    {% extends "learning_logs/base.html" %} 
    {% block content %}
      <p>Topics</p>
      <ul>
        {% for topic in topics %}
          <li>{{ topic }}</li> 
          {% empty %}
          <li>No topics have been added yet.</li> 
          {% endfor %}
      </ul>
    {% endblock content %}
    


    修改base.html,使其包含到显示所有主题的页面的链接

    <p>
        <a href="{% url 'learning_logs:index' %}">Learning Log</a>
        <a href="{% url 'learning_logs:topics' %}">Topics</a>
    </p>>
    
    {% block content %}{% endblock content %}
    
    image

    显示特定主题的页面

    URL模式,要查看主题Chess(其id为1)的详细页面,URL将为http://localhost:8000/topics/1/
    """定义learning_logs的URL模式""" 
    from django.conf.urls import url 
    from . import views
    
    app_name='learning_logs'
    
    urlpatterns = [ 
        # 主页
        url(r'^$', views.index, name='index'),
        
        # 显示所有的主题
        url(r'^topics/$', views.topics, name='topics'),
    
        # 特定主题的详细页面
        url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
        ]
    


    视图

    from django.shortcuts import render
    from .models import Topic
    
    # Create your views here.
    
    def index(request):
        """学习笔记的主页"""
        return render(request,'learning_logs/index.html')
        passxxxxx
    
    def topics(request):
        """显示所有的主题"""
        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)
        entries = topic.entry_set.order_by('-date_added')
        context = {'topic': topic, 'entries': entries}
        return render(request, 'learning_logs/topic.html', context)
    

    这个函数接受正则表达式(?P<topic_id>\d+)捕获的值,并将其存储到topic_id中

    模版

    topics.html

    {% extends "learning_logs/base.html" %} {% block content %}
      <p>Topics</p>
      <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>
    {% endblock content %}
    


    topic.html

    {% extends 'learning_logs/base.html' %} 
    {% block content %}
    
      <p>Topic: {{ topic }}</p>
      <p>Entries:</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 %}
    
    image
    image

    相关文章

      网友评论

          本文标题:5. PythonWeb应用程序Django1

          本文链接:https://www.haomeiwen.com/subject/vkslrftx.html