欢迎来到罗生堂下的博客

Django回顾之_02_Django的基本使用

4. 虚拟环境

4.1 概念

之前安装python包的命令: sudo pip3 install 包名
包的安装路径:/usr/local/lib/python3.5/dist-packages

在同一个python环境中安装同一个包的不同版本,后安装的包会把原来安装的包覆盖掉。这样,如果同一台机器上两个项目依赖于相同包的不同版本,则会导致一些项目运行失败。
解决的方案就是:虚拟环境。

虚拟环境是真实python环境的复制版本。
在虚拟环境中使用的python是复制的python,安装python包也是安装在复制的python中。

4.2 安装和配置

安装虚拟环境的命令:
  • 1)sudo pip install virtualenv #安装虚拟环境
  • 2)sudo pip install virtualenvwrapper #安装虚拟环境扩展包
  • 3)编辑/home目录下面的.bashrc文件,添加下面两行。
export WORKON_HOME=$HOME/.virtualenvs
source /usr/local/bin/virtualenvwrapper.sh
  • 4)使用source .bashrc使其生效一下。

4.3 使用

  • 创建虚拟环境命令:mkvirtualenv 虚拟环境名
  • 创建python3虚拟环境:mkvirtualenv -p python3 evn_py3
    • 创建python3虚拟环境名,# 在创建虚拟环境时,必须保证有网
  • 进入虚拟环境工作:workon 虚拟环境名
  • 查看机器上有多少个虚拟环境:workon 空格 + 两个tab键
  • 退出虚拟环境:deactivate
  • 删除虚拟环境:rmvirtualenv 虚拟环境名
  • 虚拟环境下安装包的命令:pip install 包名
    注意:不能使用sudo pip install 包名,这个命令会把包安装到真实的主机环境上而不是安装到虚拟环境中。
  • 查看虚拟环境中安装了哪些python包:
pip list
pip freeze
  • 安装django环境:pip install django==3.0.3
    • 如果网不好,会报错:在python中安装包出现Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None))

-- 参考链接1

pip install django==3.0.3 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

拓展:
apt-get install 软件
pip install python包名

5. 项目创建

5.1 创建Django项目

  • 命令:django-admin startproject 项目名(test1)

    注意:创建应用必须先进入虚拟环境。

  • tree可查看项目目录

  • 项目目录如下:

    • __init__.py: 说明test1是一个python包。
    • settings.py: 项目的配置文件。
    • urls.py: 进行url路由的配置。
    • wsgi.py: web服务器和Django交互的入口。
    • manage.py: 项目的管理文件。

5.2 创建Django应用

一个项目由很多个应用组成的,每一个应用完成一个功能模块

  • 创建应用的命令如下:python manage.py startapp 应用名(booktest)
    注意:创建应用时需要先进入项目目录。
  • 应用目录如下:
  • __init__.py: 说明目录是一个Python模块。
  • models.py: 写和数据库项目的内容, 设计模型类。
  • views.py: 接收请求,进行处理,与M和T进行交互,返回应答。定义处理函数,视图函数。
    • 定义处理函数,视图函数---相对于mini-web中的处理函数 def def add_focus(ret): # 1. 获取股票代码
  • tests.py: 写测试代码的文件。
  • admin.py: 网站后台管理相关的文件。

5.3 应用注册

建立应用和项目之间的联系,需要对应用进行注册,修改settings.py中的INSTALLED_APPS配置项。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'booktest' #加入'booktest', # 进行应用的注册

]

5.4 启动项目

  • 运行开发web服务器命令:python manage.py runserver
  • 使用Django中内置的服务器:python manage.py runserver
    • 复制文件中的http://127.0.0.1:8000/到浏览器并打开(或192.168.x.xx:xxxx)
      • 如果是虚拟机中,可能出现:主机无法访问虚拟机中运行的Django项目
      • 运行Django的命令,要写成: python3 manage.py runserver 0.0.0.0:8000 ,重点就是这个0.0.0.0,这样才能让外部访问到
      • 参考链接2
    • 如果出现:Invalid HTTP_HOST header: '192.168.1.111:8000'. You may need to add '192.168.1.111' to ALLOWED_HOSTS
    • 在我们创建的项目里修改setting.py文件 ALLOWED_HOSTS = ['*'] #在这里请求的host添加了*
    • 参考链接3

6. 模型类

6.1 ORM

django中内嵌了ORM框架,ORM框架可以将类和数据表进行对应起来,只需要通过类和对象就可以对数据表进行操作。

  • 在Django中主要是 设计类:模型类。
    • 在models.py文件中填写
      ORM另外一个作用:根据设计的类生成数据库中的表。

6.2 模型类设计

在应用models.py中设计模型类,必须继承于models.Model类。

  • 1) 设计BookInfo类。
  • 2) 设计HeroInfo类。
    Models.ForeignKey可以建立两个模型类之间一对多的关系,django在生成表的时候,就会在多端的表中创建一列作为外键,建立两个表之间一对多的关系。

6.3 模型类生成表

    1. 生成迁移文件
    • 命令:python manage.py makemigrations
      迁移文件是根据模型类生成的。
    1. 执行迁移生成表
    • 命令:python mange.py migrate
      根据迁移文件生成表。
      生成表名的默认格式:
      应用名_模型类名小写
  • 3)安装sqliteman:sudo apt-get install sqliteman 安装失败,更换源
    • 根据迁移文件生成表,生成表名的默认格式: 应用名_模型类名小写

6.4 通过模型类操作数据表

  • 进入项目shell的命令: python manage.py shell
    以下为在相互shell终端中演示的例子:
  • 首先导入模型类:
> from booktest.models import BookInfo,HeroInfo
#1)	向booktest_bookinfo表中插入一条数据。
	b = BookInfo() #定义一个BookInfo类的对象
	b.btitle ='天龙八部' #定义b对象的属性并赋值
	b.bpub_date = date(1990,10,11) 
	b.save() #才会将数据保存进数据库
#2) 查询出booktest_bookinfo表中id为1的数据。
	b = BookInfo.objects.get(id=1) 
#3) 在上一步的基础上改变b对应图书的出版日期。
	b.bpub_date = date(1989,10,21)
	b.save() #才会更新表格中的数据
#4) 紧接上一步,删除b对应的图书的数据。
	b.delete() #才会删除
#5) 向booktest_heroInfo表中插入一条数据。
	h = HeroInfo()
	h.hname = '郭靖'
	h.hgender = False
	h.hcomment = ‘降龙十八掌’
	b2 = BookInfo.objects.get(id=2)
	h.hbook = b2  #给关系属性赋值,英雄对象所属的图书对象
	h.save() 
#6) 查询图书表里面的所有内容。
	BookInfo.objects.all()
	HeroInfo.objects.all()

6.4.1. models.py中:

from django.db import models
# 设计和表对应的类,模型类
# Create your models here.

# 一类
# 图书类


class BookInfo(models.Model):   # 要继承models.Model以后,才是一个模型类
    # '''图书模型类'''
    # 图书名称,Charfield说明是一个字符串,max_length指定字符串的最大长度
    btitle = models.CharField(max_length=20)
    # 出版日期,DateField说明是一个日期类型
    bpub_date = models.DateField()

# 生成的db.sqlite3可以用sudo apt-get install sqliteman后,打开

# django默认sqlite小型数据库,要替换成mysql



# 多类
# 英雄人物类
# 英雄名 name
# 性别 hgender
# 年龄 hage
# 备注 hcomment
# 关系属性 hbook,建立图书类和英雄人物类之间的一对多关系
class HeroInfo(models.Model):

    # '''英雄人物模型类'''

    hname = models.CharField(max_length=20)  # 英雄名称

    # 性别,BooleanField说明是bool类型,default指定默认值,False代表男
    hgender = models.BooleanField(default=False)
    # 备注
    hcomment = models.CharField(max_length=128)
    # 关系属性 hbook,建立图书类和英雄人物类之间的一对多关系
    # 关系属性对应的表的字段名格式: 关系属性名_id
    hbook = models.ForeignKey('BookInfo', on_delete=models.CASCADE,)
    # ForeignKey外键

# 通过模型类操作数据表
# 进入项目shell的命令:python manage.py shell
#
# 增加实例属性要和类属性名称一样

6.5 关联操作

1) 查询出id为2的图书中所有英雄人物的信息。

b = BookInfo.objects.get(id=2)
b.heroinfo_set.all() #查询出b图书中所有英雄人物的信息

6.5.1_png

7. 后台管理

1) 本地化

  • 语言和时区的本地化。
  • 修改settings.py文件。
# LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'zh-hans' # 使用中文

# TIME_ZONE = 'UTC'
TIME_ZONE = 'Asia/Shanghai' # 中国时间

2) 创建管理员

  • 命令:python manage.py createsuperuser
    • 执行时,可能会报错:Django项目出现: 禁止访问(403),CSRF验证失败,相应中断
    • 解决办法:在app的views.py 文件中可以添加一个 from django.template import RequestContext 然后,渲染函数render 添加即可。
      • 如: return render(request, ‘users/register.html’,context={‘form’:form})
      • 参考链接7.2

3) 注册模型类

在应用下的admin.py中注册模型类,告诉djang框架根据注册的模型类来生成对应表管理页面。

from booktest.models import BookInfo, HeroInfo

admin.site.register(BookInfo)
admin.site.register(HeroInfo)
  • __str__:如果一个类中定义了__str__方法,那么在打印对象时,默认输出该方法的返回值
    • models.py中:重写一个__str__方法
class BookInfo(models.Model):
    """图书模型类"""
    ...  
    def \_\_str__(self):
        # 返回英雄名
        return self.hname

4) 自定义管理页面

自定义模型管理类:模型管理类就是告诉django在生成的管理页面上显示哪些内容。

class BookInfoAdmin(admin.ModelAdmin):
    """图书模型管理类"""
    list_display = ['id', 'btitle', 'bpub_date']

class HeroInfoAdmin(admin.ModelAdmin):
    """英雄人物管理类"""
    list_display = ['id', 'hname', 'hcomment']

# 注册模型类
admin.site.register(BookInfo, BookInfoAdmin)
admin.site.register(HeroInfo, HeroInfoAdmin)

8. 视图

在Django中,通过浏览器去请求一个页面时,使用视图函数来处理这个请求的,视图函数处理之后,要给浏览器返回页面内容。

8.1视图函数的使用

1) 定义视图函数

视图函数定义在views.py中。

  • 例:
def index(request):
    #进行处理。。。
    return HttpResponse('hello python')

视图函数必须有一个参数request,进行处理之后,需要返回一个HttpResponse的类对象,hello python就是返回给浏览器显示的内容。

2) 进行url配置---项目文件夹(test1)下的urls.py


url配置的目的是让建立url和视图函数的对应关系。url配置项定义在urlpatterns的列表中,每一个配置项都调用url函数。
url函数有两个参数,第一个参数是一个正则表达式,第二个是对应的处理动作。

  • 配置url时,有两种语法格式:
    • a) url(正则表达式,视图函数名)
    • b) url(正则表达式,include(应用中的urls文件))
  • 工作中在配置url时,首先在项目的urls.py文件中添加配置项,
  • 但并不写具体的url和视图函数之间的对应关系,而是写包含具体应用的urls.py文件,
  • 然后,在应用的urls.py文件中写url和视图函数的对应关系。

8.2 url匹配的过程

8.2_png
在项目的/test1/urls.py文件中包含具体应用的urls.py文件,应用的/booktest/urls.py文件中写url和视图函数的对应关系。

urlpatterns = [
    url(r'^admin/', admin.site.urls), # 配置项目
    url(r'^',include('booktest.urls')), # 包含booktest应用中urls
    # path('admin/', admin.site.urls),
]
  • 可能会报错:include()函数报错'provide the namespace argument to include() instead.' % len(arg)
    • 解决方案:url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
    • 参考链接8.2
# 建议直接将项目test1/urls.py文件的内容,直接复制到应用booktest/urls.py文件中,再将不需要的地方修改掉,这样就不会错了。

"""test/urls.py"""
from django.conf.urls import url, include
from django.contrib import admin


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
]
# ---------------------------------------------------------------------------------
"""booktest/urls.py"""
from django.conf.urls import url
from booktest import views


# 创建列表urlpatterns,视图调用就是从这个列表中调用,
# 需要通过导入from django.conf.urls import url 来调用项目的urls文件
# 在应用的urls文件中进行url配置的时候:
# 1.严格匹配开头和结尾
urlpatterns = [
    # 通过url函数设置url路由配置项
    url(r'^index$', views.index),    # 写入对应的index名字,建立/index和视图index之间的关系
    # url(r'^index2', views.index2),  # 此时的输入还是“老铁,没毛病”不对,因为在上一项匹配成功后,就不再匹配下一项了
    url(r'^index2$', views.index2),   # 故,为了解决这个问题,需严格匹配开头和结尾,加上^与$
    url(r'^books$', views.show_books), # 显示图书信息,即/boos页面显示的内容
    url(r'^books/(\d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将\d+作为一个组()
]

8.2.1. 当用户输入如http://127.0.0.1:8000/aindex时,去除域名和最前面的/,剩下aindex,拿aindex字符串

8.2.2. 先到项目的urls文件中进行匹配,配置成功后,去除匹配的a字符,拿剩下的index字符串继续到项目的urls

8.2.3. 文件中进行正则匹配,匹配成功之后执行视图函数index,index视图函数返回内容hello python给浏览器显示

9. 模板

模板不仅仅是一个html文件。

9.1 模板文件的使用

  • 1 创建模板文件夹:项目test1/下面创建templates文件夹---/test1/templates/
  • 2 配置模板目录
    • settings.py文件中有TEMPLATES 选项,这个配置就是让我们去设置模板目录的。
    • 在'DIRS': []中设置模板文件的目录,设置路径,但是路径不能随便设置,而应该根据BASE_DIR来设置
    • 项目目录的绝对路径,pwd,/home/huang/bj18/test1得到的就是项目目录
    • 设置时,将BASE_DIR和模板目录进行拼接
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')], # 设置模板文件目录,路径
        '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',
            ],
        },
    },
]
  • 设置完模板目录后,即可使用,为了给多个应用(booktest等)使用,不混淆,会在模板文件夹(templates)下,再新建同名文件夹booktest,

  • 新建模板文件index.html,写好内容后,即可使用模板文件;

  • 在mini_frame框架中,手动打开一个文件读取出来,Django中不能这样做,使用模板文件应该遵循以下步骤:

  • 3 使用模板文件

    • 1.定义视图函数,HttpRequest
      • 在booktest下新建一个urls.py
      • 视图函数的作用是: 调用模板,处理数据并返回给浏览器。
      • 如果需要操作数据库,需要和M、T进行交互
    • 2.进行url配置,建立url地址和视图的对应关系,和Flask相似
      • 浏览器中输入http:127.0.0.1:8000/index # 用户要显示该url,需要在应用app中的urls列表中,添加该url
from django.shortcuts import render
from django.http import HttpResponse
from django.template import loader, RequestContext
from booktest.models import BookInfo, HeroInfo    # 导入模型类


def index(request):
    ···
    return render(request, 'booktest/index.html',
                  {'content': 'hello world', 'list':list(range(1, 10))}, )
    urlpatterns = [
        url(r'^index$', views.index),    # 写入对应的index名字,建立/index和视图index之间的关系
]

以下a)-c)为视图函数调用模板文件的分析过程,可省略:
- 发现除get_template('booktest/index.html')中的'booktest/index.html'、context中的字典不同外,其余的部分都相同,
- 故,重新定义一个函数my_render(),但此方法是多余的,因为已经导入了render,所以可以直接使用
```
def my_render(request, template_path, context_dict):
    """使用模板文件"""
    # 直接将index中的模板文件拿过来使用
    # 1.加载模板文件
    temp = loader.get_template(template_path)  # 写上目录,该目录是相对templetes的目录---改为template_path
    # 2.定义模板文件上下文:给模板文件传递数据,request,和要传递的数据,通过{}的键值对来传减去
    # 导入from django.template import loader, RequestContext
    # context = RequestContext(request, {''})   # Django1.11以后,就是直接传入{}即可,不再传入RequestContext(request, {''})---{}字典也改为通过context_dict来改变
    # context = {}
    context = context_dict
    # 3.模板渲染(目的是把使用的变量,还有一些语句给替换掉):产生标准的html内容,temp中有一个render方法,将context放进去
    res_html = temp.render(context)
    # 4.返回给浏览器
    return HttpResponse(res_html)
```
    - a)加载模板文件----views.py中,使用模板文件 # 1.加载模板文件
        - 导入包 from django.template import loader
        - temp = loader.get_template('booktest/index.html')  # 写上目录,该目录是相对templetes的目录
    - b) 定义目标上下文---给模板文件传递定义的变量的值
        - 给**模板文件传递数据**:request和要传递的数据,通过{}的键值对来传进去
            - 导入from django.template import loader, RequestContext
            - context = RequestContext(request, {''})   # Django1.11以后,就是直接传入{}即可,不再传入RequestContext(request, {''})
            - \# context = {}
    - c) 模板渲染(目的是把使用的变量,还有一些语句给替换掉):产生标准的html内容,temp中有一个render方法,将context放进去
        - res_html = temp.render(context)
    - d) 返回给浏览器
        - return HttpResponse(res_html)

9.2 给模板文件传递数据

  • 模板变量使用:{{ 模板变量名 }}
  • 模板代码段:
  • for循环:
{% for i in list %}
	list不为空时执行的逻辑
{% empty %}
	list为空时执行的逻辑
{% endfor %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>模板文件</title>
    <style type="text/css">
    </style>
</head>
<body>
<h1>这是一个模板文件</h1>
使用模板变量:<br/>
{{ content }}<br/>
使用列表:<br/>
{{ list }}<br/> # 这是直接显示列表的内容,py中还可以遍历出列表中的每一个文件
for循环:<br/>
<ul>
    {% for i in list %}
        <li>{{ i }}</li>
    {% endfor %}
</ul>
</body>
</html>

9.3:小结:

  • 我们需要做的事情:
    • 1)定义视图函数
      • 视图函数定义在views.py中。
    • 2)进行url配置,项目视图+应用视图,两个。
      • """test/urls.py"""
      • """booktest/urls.py"""

10. 案例完成

编码之前的准备工作:

  • 1 设计出访问页面的url和对应的视图函数的名字,确定视图函数的功能。

    • def show_books()、detail()
  • 2 设计模板文件的名字。

    • area.html、index.html

    以下为案例中的简单设计过程:

  • 1 完成图书信息的展示:

    • 1.1 设计url,通过浏览器访问 http://127.0.0.1:8000/books 时显示图书信息页面。
      # /test1/urls.py:
      urlpatterns = [
      url(r'^admin/', admin.site.urls),
      url(r'^', include(('booktest.urls', 'booktest'), namespace='booktest')),
      ]
      
      #/booktest/urls.py:
      urlpatterns = [
          # 通过url函数设置url路由配置项
          url(r'^index$', views.index),
          url(r'^books$', views.show_books), # 显示图书信息,即/books页面显示的内容
          url(r'^books/(\d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将\d+作为一个组()
      ]
      
  • 1.2 设计url对应的视图函数show_books。

    • 查询出所有图书的信息,将这些信息传递给模板文件。
      # views.py:
      import sys
      from django.shortcuts import render
      from django.http import HttpResponse
      from django.template import loader,
      from booktest.models import BookInfo, HeroInfo    # 导入模型类
      
      
      def show_books(request):
          """显示图书的信息"""
          # 1. 通过M查找图书表中的数据
          books = BookInfo.objects.all()
          # 2. 使用模板
          return render(request, 'booktest/show_books.html', {'books': books})
      
  • 1.3 编写模板文件show_books.html。

    • 遍历显示出每一本图书的信息。
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>显示图书信息</title>
    <style type="text/css">
    </style>
</head>
<body>
图书信息如下:
    {% for book in books %}
        <li><a href="/books/{{ book.id }}">{{ book.btitle}}</a></li>
    {% endfor %}
</body>
</html>
  • 2 完成点击某本图书时,显示出图书里所有英雄信息的页面。
    • 2.1 设计url,通过访问http://127.0.0.1:8000/books/数字时显示对应的英雄信息页面。
      • 这里数字指点击的图书的id。
        url(r'^books/(\d+)$', views.detail), # 显示英雄信息,报错,需要一个bid的位置参数,这时要将\d+作为一个组()
        
    • 2.2 设计对应的视图函数detail。
      • 接收图书的id,根据id查询出相应的图书信息,然后查询出图书中的所有英雄信息。
        def detail(request, bid):
            '''查询图书关联英雄信息'''
            # 1. 根据bid查询图书信息
            book = BookInfo.objects.get(id=bid)
            # 2. 查询和book关联的信息---要分析1对多(由1查多b.heroinfo_set.all())还是多对1(h.hbook)
            # HeroInfo.objects.fliter(hbook__id=1)
            heros = book.heroinfo_set.all()
            # 需要显示图书的名字,和关联的英雄名字和备注
            # 3. 使用模板detail,创建templates/bootest/detail.html
            return render(request, 'booktest/detail.html', {'book': book, 'heros': heros})  # 注意,此处是heros,不是hero,不然图书信息就无法显示
            # 去应用booktest/urls中设置地址。
        
    • 2.3 编写模板文件detail.html:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>显示图书关联的英雄信息</title>
        <style type="text/css">    
        </style>
    </head>
    <body>
    <h1>{{ book.btitle }}</h1>
    英雄信息如下:<br/>
    <ul>
        {% for hero in heros %}
            <li>{{ hero.hname }}--{{ hero.hcomment }}</li>
        {% empty %}
            <li>没有英雄信息</li>
        {% endfor %}
    </ul>
    
    </body>
    </html>
    

posted on 2020-02-27 15:04  罗生堂下  阅读(193)  评论(0编辑  收藏  举报

导航