Django框架学习

搭建虚拟环境

安装virtualenv

1
pip3 install virtualenv
  • 开辟虚拟空间

    1
    2
    3
    virtualenv Django
    #也可以通过-p参数指定python解释器
    virtualenv -p C:\Python27\python.exe [virtualenv name]
  • 激活虚拟环境

    1
    2
    3
    linux/mac: source Django/bin/activate
    windows: cd Django/Scripts 执行activate
    退出虚拟环境: deactivate
  • 虚拟环境安装django
    1
    pip3 install Django

virtualenvwrapper

通过这个软件包管理虚拟环境。

  • 安装virtualenvwrapper

    1
    2
    mac/linux: pip install virtualenvwrapper
    windows: pip install virtualenvwrapper-win
  • 创建虚拟环境

    1
    mkvirtualenv django-env
  • 切换到某个虚拟环境

    1
    workon django-env
  • 删除某个虚拟环境

    1
    rmvirtualenv django-env
  • 列出所有虚拟环境

    1
    lsvirtualenv
  • 进入到虚拟环境所在的目录

    1
    cdvirtualenv
  • 创建虚拟环境的时候指定python版本

    1
    2
    mkvirtualenv --python==C:\Python36\python.exe python3-env
    mkvirtualenv --python==C:\Python27\python.exe python2-env

URL与视图

视图函数

  • 视图函数的第一个参数必须是request
  • 视图函数的返回值必须是django.http.response.HttpResponseBase的子类的对象。

    url传参

  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from django.http import HttpResponse
    # Create your views here.

    def book(request):
    return HttpResponse('图书首页')
    def book_detail(request,book_id):
    text ="您获取的图书id是:%s" % book_id
    return HttpResponse(text)

    def author_detail(request):
    author_id=request.GET.get('id')
    text= '作者的id是: %s' % author_id
    return HttpResponse(text)
  • urls.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    from django.contrib import admin
    from django.urls import path
    from book import views
    from django.http import HttpResponse
    def index(request):
    return HttpResponse('首页')
    urlpatterns = [
    path('admin/', admin.site.urls),
    path('book/',views.book),
    path('',index),
    path('book/detail/<book_id>',views.book_detail),
    path('book/author/',views.author_detail)
    ]

url命名

  • 用name参数命名

    1
    path('login/',views.login,name='login')
  • 在重定向时使用

    1
    2
    3
    from django.shortcuts import redirect,reverse
    ...
    return redirect(reverse('login'))
  • 如果多个app里有同名的url,则需要使用应用命名空间

    1
    2
    3
    4
    #定义命名空间,在app的urls.py中
    app_name='cms'
    #要做反转的时候
    login_url=reverse('cms:login')

Django模板

模板介绍

  • DTL: Django Template Language

模板渲染

模板渲染有多种方式,这里列两种常用方式。

  • render_to_string:找到模板,然后将模板编译后渲染成Python的字符串格式,最后再通过HttpResponse类包装成一个HttpResponse对象返回。示例代码:

    1
    2
    3
    4
    5
    from django.template.loader import  render_to_string
    from django.http import HttpResponse
    def index(request):
    html=render_to_string("index.html")
    return HttpResponse(html)
  • django还提供了一个更简便的方式,直接将模板渲染成字符串和包装成HttpResponse对象一步到位完成。示例代码:

    1
    2
    3
    4
    5
    from django.shortcuts import render

    def index(request):

    return render(request,'index.html')

模板查找路径

在项目的settings.py文件中,有一个TEMPLATES配置,包含了模板引擎的配置,模板查找路径的配置,模板上下文的配置。

  • DIRS:存放所有模板的路径,会优先在这个路径查找

    1
    'DIRS': [os.path.join(BASE_DIR, 'templates')]
  • APP_DIRS:默认为True,会在INSTALLED_APPS的安装了的app下的templates文件中查找模板。

  • 查找顺序:首先在DIRS,然后是在当前视图所处的app下的templates文件夹中查找(已经在INSTALLED_APPS中添加),最后是在其他已经安装了的app中查找。

模板变量

  1. 模板中使用变量,需要将变量放到中。
  • views.py

    1
    2
    3
    4
    5
    6
    7
    from django.shortcuts import render
    def index(request):
    context = {
    'username':'chenxiyuan',
    'list': ['aka','bim']
    }
    return render(request,'index.html',context=context)
  • index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    Welcome {{ username }}
    <br>
    AND {{ list.1 }}
    </body>
    </html>
  1. 访问对象:对象.属性
  2. 访问字典的key对应的value:字典.key,不能通过中括号[]形式访问。
  3. 访问列表或者元组:都只能通过.的方式访问,不能通过中括号[]访问

    常用的模板标签

  4. 注释

    1
    {# ... #}
  5. if标签

    1
    2
    3
    4
    5
    {% if ... %}
    ...
    {% else %}
    ...
    {% endif %}
  6. for in标签

    1
    2
    3
    4
    {% for ... in ... %}
    ...
    {% endfor %}
    # 反向遍历,可以在后面加一个reversed
  7. url标签

  • 类似django中的reverse反转一样

    1
    <a href="{% url 'book:list' %}">图书列表页面</a>
  • 带参数传递的url反转,分为位置参数和关键字参数,注意两个不能同时使用

    1
    2
    3
    4
    5
    6
    #path部分
    path('detail/<book_id>/',views.book_detail,name='detail')
    #位置参数
    <a href="{% url 'book:detail' 1 %}"> 图书详情页面</a>
    #关键字参数
    <a href="{% url 'book:detail' book_id=1 %}">图书详情页面</a>
  • 传递查询字符串参数

    1
    <a href="{% url 'book:detail' book_id=1 %}?page=1">图书详情页面</a>

模板过滤器

add

将传进来的参数添加到原来的值上面。源代码如下:

1
2
3
4
5
6
7
8
9
def add(value, arg):
"""Add the arg to the value."""
try:
return int(value) + int(arg)
except (ValueError, TypeError):
try:
return value + arg
except Exception:
return ''

  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from django.shortcuts import render
    def hello(name):
    return "hello "+name

    def index(request):
    context = {
    'hello':'hello'
    }
    return render(request,'index.html',context=context)
  • index.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    {{ hello|add:"chenxiyuan" }}
    </body>
    </html>

cut

移除值中所指定的字符串。

1
2
# 移除value中所有的空格字符
{{value|cut:" "}}

源代码如下:

1
2
3
4
5
6
7
def cut(value, arg):
"""Remove all values of arg from the given string."""
safe = isinstance(value, SafeData)
value = value.replace(arg, '')
if safe and arg != ';':
return mark_safe(value)
return value

date

将日期按照指定格式格式化成字符串。

1
2
3
4
5
6
#数据
context = {
"time": datatime.now()
}
#模板
{{time|date:"Y-m-d"}}

输出2019-07-15

模板继承

示例代码:

  • 虚拟环境下新建frontapp:python manage.py startapp front
  • views.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    from django.shortcuts import render

    def index(request):
    context = {
    'username': '晨曦远'
    }
    return render(request,'index.html',context=context)

    def home(request):

    return render(request,'home.html')

    def about(request):
    return render(request, 'about.html')
  • urls.py

    1
    2
    3
    4
    5
    6
    7
    8
    from django.urls import path
    from front import views

    urlpatterns = [
    path('', views.index,name="index"),
    path('home/',views.home,name='home'),
    path('about/',views.about,name='about')
    ]
  • base.html:父模板

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <header>
    <ul>
    <li><a href="/">首页</a></li>
    <li><a href="{% url 'home' %}">个人中心</a></li>
    <li><a href="{% url 'about' %}">关于</a></li>
    <li>{{ username }}</li>
    </ul>
    </header>
    <div class="content">
    {% block content %}
    父模板中content的代码
    {% endblock %}
    </div>

    </body>
    </html>
  • index.html

    1
    2
    3
    4
    5
    6
    7
    {% extends 'base.html' %}
    {% block content %}
    {# 如果父模板block里有内容,会被子模板覆盖掉 #}
    <p>这是首页</p>
    {# 如果想继承父模板block内容,需要使用block.super #}
    {{ block.super }}
    {% endblock %}
  • home.html

    1
    2
    3
    4
    {% extends 'base.html' %}
    {% block content %}
    个人中心
    {% endblock %}
  • about.html

    1
    2
    3
    4
    {% extends 'base.html' %}
    {% block content %}
    关于页面
    {% endblock %}

加载静态文件

  1. 确保settings.pyINSTALLED_APPS已经安装了django.contrib.staticfiles
  2. 确保settings.py中设置了STATIC_URL
  3. 新建app,添加到INSTALLED_APPS,然后在此app下新建一个static文件夹,再创建一个同名app文件夹保存静态文件,以免不同app有同名的静态文件产生混淆
  4. 在模板中使用load标签加载static标签

    1
    2
    3
    {% load static%}
    ...
    <img src="{% static 'logo.jpg' %}" alt="">
  5. 如果静态文件不与app挂钩,则可以在主程序同路径下新建static文件夹存放静态文件,在settings.py里设置路径

    1
    2
    3
    STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
    ]

数据库操作

mysql驱动程序安装

1
pip install mysqlclient

配置数据库连接

settings.py文件里配置DATABASES

1
2
3
4
5
6
7
8
9
10
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'webtest',
'USER': 'root',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306'
}
}

原生sql语句操作数据库

使用connection对象

1
2
3
4
5
6
7
from django.db import connection

cursor=connection.cursor()
cursor.execute("select * from user")
rows = cursor.fetchall()
for row in rows:
print(row)

PYTHON DB API规范下cursor对象常用接口

  • rowcount: 返回执行sql语句后受影响的行数
  • close: 关闭游标
  • execute(sql[,parameters]):执行sql语句

    1
    cursor.execute("select * from user where id=%s",(2,))
  • fetchone:执行查询操作后,获取第一条数据

  • fetchmany(size): 获取size条数据
  • fetchall: 获取所有数据

    ORM模型

  • ORM: Object Relational Mapping
  • ORM映射
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # models.py
    from django.db import models
    # Create your models here.
    class Student(models.Model):
    # id:int类型,自增长
    id = models.AutoField(primary_key=True)
    # name: varchar(20),不允许为空
    name =models.CharField(max_length=20,null=False)
    age = models.IntegerField(null=False,default=18)

    def __str__(self):
    return "<Student:({name},{age})>".format(name=self.name,age=self.age)
    # 使用makemigrations生成迁移脚本文件
    # 虚拟环境下在项目路径: python manage.py makemigrations
    # 使用migrate将新生成的迁移脚本文件映射到数据库中
    # python manage.py migrate

    # 一个模型的对象,对应数据库表中的一条数据
    #student1 =Student(name='chenxiyuan',age=19)
    # save方法,将数据保存到数据库
    #student1.save()
    # delete方法,从数据库中删除这条数据
    #student1.delete()

要记着在settings.py设置INSTALLED_APPS里安装app,配置好数据库。

  • 增删改查
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    #views.py
    from .models import Student
    from django.gttp import HttpResponse
    def index(request):
    #根据主键进行查找
    student1 = Student.objects.get(pk=1)
    print(student1)
    #<Student:(chenxiyuan,19)>
    #根据其他条件进行查找
    student2 = Student.objects.filter(name='chenxiyuan')
    # save方法,将数据保存到数据库
    #student1.save()
    # delete方法,从数据库中删除这条数据
    #student1.delete()
    #改就是先查后改再save
    return Httpresponse("success")