django整理未整理完
创建虚拟环境
- 使用virtualenv
- 创建隔离的Python运行环境
- Windows下:
- 安装:pip install virtualenv
- 创建独立的Python运行环境
virtualenv spider
创建新的Python环境放到当前目录下的spider目录中 - 进入虚拟环境
env\spider\activate
- Linux下:
- 安装:pip install virtualenv
- 创建独立的Python运行环境
virtualenv -p /usr/bin/python3.6 env #指定Python版本
virtualenv env #默认Python2.7
创建新的Python环境放到当前目录下的env目录中 - 进入虚拟环境
cd env
source ./bin/activate - 退出虚拟环境:deactivate
- 删除虚拟环境:rmvirtualenv env
安装django
- pip install django
- 查看当前环境下的第三方库:pip list
项目创建
- 新建项目的命令:django-admin startproject projectname
- 先在命令行创建项目,然后再设置pycharm代码同步
开发服务器
开启服务器
- 方式一(不常用):
命令行模式:
在项目的根目录下执行命令
python manage.py runserver 0.0.0.0:8000 #0.0.0.0可以简写为0 - 方式二(常用):
- 选择编辑器右上角的Edit Configuration的按钮
- 点击添加Django server
- 改Host为0.0.0.0,表示的是允许连接服务器的IP #方便调试,使用什么ip都能访问到
- 点击Environment Variables项后面的…
- 将DJANGO_SETTINGS_MODULE添加到Name,将项目名.settings添加到Value
- 在apply按钮上有可能fix有红灯标志,点进去,把Enable Django Support勾选上,Django project root行点文件夹标志,选上根目录,Settings行点文件夹标志,选上根目录下的settings.py文件
访问服务器
- 当用其中的一种方式开启了服务后,打开浏览器
- 在地址栏输入IP地址和服务的端口号
- 可以看到服务正在运行的页面
- 需要注意的点:
- IP:
- 在终端用命令ifconfig查看IP,注意网络连接方式
- 虚拟机的端口转发时使用的是127.0.0.1回环地址
- port
- 远程连接ssh服务的端口号是22
- http服务端口号8000/8080
- MySQL服务的端口号3306
- IP:
新建app
-
在项目根目录下创建命令:python manage.py startapp app_name
-
在settings.py中的INSTALLED_APPS加入app,我的代码如下:(我新建了students和teachers两个app)
INSTALLED_APPS = [ 'students', 'teachers', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
新建views
-
在app下新建views.py,简单代码如下:
from django.shortcuts import render from django.http import HttpResponse #导包 def index(request): return HttpResponse('hi girl')
设置urls
-
app下新建urls.py文件,代码如下:
from django.urls import path, re_path from students import views #导包 app_name = 'students' urlpatterns = [ path('index/', views.index , name='index'), ]
-
项目的urls.py文件代码:
from django.contrib import admin from django.urls import path, re_path, include #导包 urlpatterns = [ path('admin/', admin.site.urls), path('students/', include('students.urls')) #students/前面不要加/ ]
模板路径配置
- 在主目录下(和manage.py同等级,也叫项目根目录)创建一个templates目录用来存放所有的HTML的模板文件
- templates目录里面在新建各个以app名字命名的目录来存放各个app中模板文件
渲染
return render(request, 'students/index.html')
调用渲染
- 在index.html文件中
- {{变量名}}
- 在viwes.py文件中:
- return HttpResponse(request, ‘students/index.html’, context{‘变量名’: 变量})
- 语法:命名由字母和数字以及下划线组成,不能有空格和标点符号,不能以下划线,数字开头,不能以Python,django关键字命名
- 变量的值可以是任何数据类型(字典,模型,方法,函数,列表…)
- 变量的解析规则
- 当模板引擎遇到模板变量,会计算变量,将其替换为结果
- 解析结果相当于print的值
- 模板变量中有点(.)的时候,按以下顺序查找
- 字典键值查找
- 属性或方法查找
- 数字索引查找
- 如果结果是可调用的,则调用它时不带参数,调用的结果成为模板的值(解析结果)
如果渲染失败,返回空
案例
-
views.py文件
from django.shortcuts import render, redirect, reverse from django.http import HttpResponse from django.template.loader import get_template from datetime import datetime class Test: def __init__(self, name, age): self.name = name self.age = age def student(self): return 'my girl' s = Test('xiaoge', 18) def index(request): lt = [1, 2, 3] now = datetime.now() dt = {'name': 'xiaoge', 'age': 19, 'items':'abc'} tp = (1, 2, 3) str = 'hi girl' return render(request, 'students/index.html', context={ 'now': now, 'lt': lt, 'cs': s, 'name': s.name, 'fc': s.student, 'dt': dt, 'tp': tp, 'str':str, })
模板过滤器
-
对变量进行过滤,在真正渲染出来之前,过滤器会根据功能处理好变量,然后得出结果后再替换掉原来的变量展示出来
-
语法:{{value|方法}}
-
使用参数:过滤器可以使用参数,在过滤器名称后面使用‘:’,再在引号中加上参数
- {{value|方法:‘参数’}}
-
常用模板过滤器
- add 将参数与值相加 首先尝试转换成整数相加,失败,则尝试所有可能,字符串,列表等。{{ value|add:“2” }}
- capfirst 首字母大写,如果第一个字母不是字母则不起作用。{{ value|capfirst }}
- date 日期格式化 {{ value|date:“D d M Y” }}
- time 时间格式化 {{ value|time:“H:i:s” }} 格式化格式见官方文档:https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#date
- default 如果变量解析失败,使用给定的默认值。{{ value|default:“nothing” }}(注意如果value是空字符串或者None,输出将会是’nothing’)
- first 返回列表的第一个元素 {{ value|first }}
- last 返回列表的最有一个元素 {{ value|last }}
- slice 返回一个列表的切片 {{ some_list|slice:“2” }}
- join 连接字符串列表 与str.join(list)一样 {{ value|join:" // " }}
- length 返回字符串或列表的长度
- length_is 判断字符串或列表长度是否指定的值,相等返回True {{ value|length_is:“4” }}
- lower 字符串中的字母都变小写{{ value|lower }}
- upper 字符串中的字母都变大写{{ value|upper }}
- safe 关闭变量的自动转义,使html标签生效{{ value|safe }}
- title 标题化,首字母大写 {{ value|title }}
- floatformat 浮点数格式化 不指定小数位参数,默认保留一个为小数value Template Output 34.23234 {{ value|floatformat }} 34.2 34.23234 {{ value|floatformat:3 }} 34.232
案例
-
index.html文件:
<p>现在时间{{ now|date:'Y-m-d H:i:s' }}</p> #模板过滤器 <p>列表第一个值+3:{{ lt.0|add:3 }}</p> <p>列表第一个值+3.5:{{ lt.0|add:3.5 }}</p> <p>列表第一个值+'3':{{ lt.0|add:'3' }}</p> <p>首字母大写:{{ fc|capfirst}}</p> <p>字母都大写:{{ fc|upper}}</p> <p>字母标题化:{{ fc|title}}</p> <p>浮点数:{{ 3.1413223|floatformat}}</p> <p>浮点数:{{ 3.1413223|floatformat:'3'}}</p> <p>插入/:{{ fc|join:'/'}}</p> <p>字符串长度:{{ fc|length}}</p> <p>字符串长度:{{ fc|length_is:'7'}}</p> <p>列表第一个值+'3.5':{{ lt.0|add:'3.5' }}</p> <p>函数加字符串{{ fc|add:'haha' }}</p> <p>字典的值gender是否存在{{ dt.gender|default:'nothing' }} <p>列表第一个值:{{ lt|first }}</p> <p>列表最后一个值:{{ lt|last }}</p> <p>列表切片:{{ lt|slice:'2' }}</p> #取前两个 <p>列表倒序:{{ lt|slice:'::-1' }}</p>
静态文件
- 路径设置
- 在settings.py文件中添加STATICFILES_DIRS = [os.path.join(BASE_DIR, ‘static’)]
- 新建文件
- 在项目根目录下新建static文件夹,在static下新建app名的文件夹,在app文件夹下新建css等需要的文件夹,在css文件夹下新建cover.css文件(名自己起)
- 在项目根目录下新建static文件夹,在static下新建app名的文件夹,在app文件夹下新建css等需要的文件夹,在css文件夹下新建cover.css文件(名自己起)
- 静态文件的引入
在settings.py中有STATIC_URL = ‘/static/’ #这里的static对应link中href的static,不建议改-
模板标签
-
在开头加载static,在head标签中加入link
{% load static %} #加载static <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> #在link的href中加载路径,格式为{% static 'app名/css路径' %} <link rel="stylesheet" href="{% static 'students/css/index.css' %}"> </head>
-
- F12查看网页,会发现选中的部分和硬编码一样
模板标签
效果图:
标签语法
- 由{% 和 %}来定义的,例如:{% tag %} {% endtag %}
常用标签
- 标签内的语法和Python语法大致一样
案例
-
index.html文件中的demo
<table class="table"> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> {# 如果students为空,则渲染empty下的内容#} {% for stu in students %} <tr {% if stu.age < 17 %}style="color:blue;" {% elif stu.age > 16 and stu.age < 22 %}style="color:red;" {% else %}style="color:green;" {% endif %}> {# forloop.counter获取当前for循环的迭代次数,以1开始#} {# 硬编码跳转 <td><a href="/students/detail/{{ stu.id }}/">{{ forloop.counter }}</a></td>#} <td><a href="{% url 'students:detail' stu.id %}">{{ forloop.counter }}</a></td> {# forloop.counter0获取当前for循环的迭代次数,以0开始#} {# <td>{{ forloop.counter0 }}</td>#} {# forloop.revcounter获取当前for循环的迭代次数,从大到小#} {# <td>{{ forloop.revcounter }}</td>#} {# forloop.revcounter0获取当前for循环的迭代次数,从大到小,最小为0#} {# <td>{{ forloop.counter0 }}</td>#} <td>{{ stu.name }}</td> <td>{{ stu.age }}</td> <td>{{ stu.gender }}</td> </tr> {# 如果students为空,则渲染empty下的内容#} {# {% empty %}#} {# 要渲染的内容#} {% endfor %} </table>
-
views.py文件中的demo:
def index(request): students = [ {'id':10, 'name': '小哥', 'age': 15, 'gender': '男'}, {'id':33,'name': 'yang', 'age': 15, 'gender': '女'}, {'id':53,'name': 'wen', 'age': 25, 'gender': '女'}, {'id':12,'name': 'long', 'age': 18, 'gender': '男'}, {'id':76,'name': 'na', 'age': 16, 'gender': '女'}, {'id':38,'name': 'yi', 'age': 19, 'gender': '女'}, {'id':48,'name': 'xin', 'age': 17, 'gender': '男'}, ] return render(request, 'students/index.html', context={ 'students': students, }) def detail(request, pk): #pk一般是个id,是整数primary key return HttpResponse('学生id为%s的详情页' % pk)
-
urls.py文件中的demo:
urlpatterns = [ path('index/', views.index, name='index'), #index前不要加/,django自动添加,index后面要加/ path('login/', views.login), path('detail/<int:pk>/', views.detail, name='detail'), #捕获的值传递给views.py里的detail(request,pk)的pk ]
模板的继承与引用
引用
-
将渲染好的模板放到想要放的模板中
-
用include标签将ad.html引用到index.html中
-
index.html中加入下面代码:
<div style="position:fixed; bottom:0px;"> {% include 'students/ad.html' %} </div>
-
ad.html文件中代码:
<h1 id="h1">你看不见我,你看不见我</h1> <script> var h = document.getElementById('h1') var color = 'blue' function change_color() { if(color=='blue'){ color = 'red'; }else{ color = 'blue'; } h.style.color = color; setTimeout('change_color()',400) } change_color() </script>
-
模板继承使用extends标签实现,通过使用block来给子模板开放接口
- extends必须是模板中的第一个出现的标签
- 子模板中的所有内容,必须出现在父模板定义好的block中,否则django将不会渲染
- 如果出现重复代码,就应该考虑使用模板
- 尽可能多的定义block,方便子模板实现更细的需求
- 如果在某个block中,要使用父模板的内容,使用block.super获取
- block相当于字符串中的占位符,当继承时就可以在block中间写继承模板自己的demo
- block用法:形如{% block content %}
我是base
{% endblock %},
content起定位作用
- block用法:形如{% block content %}
- block可以插入多个
不加block案例
- 效果图:
案例
-
base.html文件demo:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <title>{% block title %}base{% endblock %}</title> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script> <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script> {% block link %}{% endblock %} </head> <body> {% block content %} {% endblock %} {% block domready %} {% endblock %} </body> </html>
-
index.html文件的demo:
{% extends 'students/base.html' %} {% block title %}学生表{% endblock %} {% load static %} {% block link %}<link href="{% static 'students/css/index.css' %}" rel="stylesheet">{% endblock %} {% block content %} <div class="blog-masthead"> <div class="container"> <nav class="blog-nav"> <a class="blog-nav-item active" href="#">Home</a> <a class="blog-nav-item" href="#">New features</a> <a class="blog-nav-item" href="#">Press</a> <a class="blog-nav-item" href="#">New hires</a> <a class="blog-nav-item" href="#">About</a> </nav> </div> </div> <div class="container"> <div class="blog-header"> {# 从这里开始替换#} <table class="table"> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> {# 如果students为空,则渲染empty下的内容#} {% for stu in students %} <tr {% if stu.age < 17 %}style="color:blue;" {% elif stu.age > 16 and stu.age < 22 %}style="color:red;" {% else %}style="color:green;" {% endif %}> {# forloop.counter获取当前for循环的迭代次数,以1开始#} {# 硬编码跳转 <td><a href="/students/detail/{{ stu.id }}/">{{ forloop.counter }}</a></td>#} <td><a href="{% url 'students:detail' stu.id %}">{{ forloop.counter }}</a></td> {# forloop.counter0获取当前for循环的迭代次数,以0开始#} {# <td>{{ forloop.counter0 }}</td>#} {# forloop.revcounter获取当前for循环的迭代次数,从大到小#} {# <td>{{ forloop.revcounter }}</td>#} {# forloop.revcounter0获取当前for循环的迭代次数,从大到小,最小为0#} {# <td>{{ forloop.counter0 }}</td>#} <td>{{ stu.name }}</td> <td>{{ stu.age }}</td> <td>{{ stu.gender }}</td> </tr> {# 如果students为空,则渲染empty下的内容#} {# {% empty %}#} {# 要渲染的内容#} {% endfor %} </table> </div> </div><!-- /.blog-sidebar --> <div style="position:fixed; bottom:0px;"> {# 将渲染好的模板放到想要放的模板#} {% include 'students/ad.html' %} </div> {% endblock %} {% block domready %} <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> {% endblock %}
-
效果图:
base模块用尽可能多的block,根据实际业务,宁多勿缺
关于自定义
- 代码布局(自定义的代码放在那里)
- 某个app特有的
- app目录下创建templatetags(Python的包)(名字固定的)文件夹
- 把普通文件夹变成Python的包:在文件夹中加__init__.py
- 在templatetags文件夹下创建Python模块(py文件)
- 定义复用
- 创建一个新的app,将他们定义在新的app中,在INSTALL_APPS注册,然后就可以应用
- app特有的和复用的只是代码布局(代码所在文件夹)不同,没有什么区别
- 某个app特有的
- templates用于存放模板的目录
- templatetags用于存放自定义标签及过滤器的目录
templatetags这个目录名字是固定的,而里面的模块名是自定义的
自定义模板过滤器
- 模板过滤器本质是函数
- 有一个或两个参数,返回字符串
- 第一个参数是传递进来的模板变量
- 第二个参数是普通的参数,也可以是默认,也可以不要
- 定义非常简单,就是写一个函数,一个带有一个或两个参数的Python参数:
- (输入的)变量的值不一定是字符串形式
- 参数的值可以有一个初始值,或者完全不要这个参数
注册自定义过滤器
- 注册自定义过滤器有两种方法:
- 通过django.template.Library的实例的filter方法
django.template.Library.filter()- Library.filter()方法需要两个参数:
- name 过滤器的名称(一个字符串对象),可以不写,默认使用方法名作为过滤器的名称
- filter_func(定义的过滤器的函数),一个Python函数(不要把函数名写成字符串)
- Library.filter()方法需要两个参数:
- 也可以把register.filter()用做装饰器
- 可以传name参数,也可以不传
- 通过django.template.Library的实例的filter方法
- 没有声明name参数,Django将使用函数名作为过滤器的名字
使用自定义过滤器
- 在模板中使用自定义的过滤器
- 需要使用{% load 模块名 %}标签将我们的自定义的模块加载进来
- {% load 模块名 %}声明将会载入给定模块名中的标签/过滤器
案例
-
views.py中的index代码:
def index(request): students = [ {'id':10, 'name': '小哥', 'age': 15, 'gender': 1}, {'id':33,'name': 'yang', 'age': 15, 'gender': 0}, {'id':53,'name': 'wen', 'age': 25, 'gender': 0}, {'id':12,'name': 'long', 'age': 18, 'gender': 1}, {'id':76,'name': 'na', 'age': 16, 'gender': 0}, {'id':38,'name': 'yi', 'age': 19, 'gender': 0}, {'id':48,'name': 'xin', 'age': 17, 'gender': 1}, ] return render(request, 'students/index.html', context={ 'students': students, })
-
index.html的demo:
{% extends 'students/base.html' %} {% block title %}学生表{% endblock %} {% load static %} {% load customer_filters %} {% block link %}<link href="{% static 'students/css/index.css' %}" rel="stylesheet">{% endblock %} {% block content %} <div class="blog-masthead"> <div class="container"> <nav class="blog-nav"> <a class="blog-nav-item active" href="#">Home</a> <a class="blog-nav-item" href="#">New features</a> <a class="blog-nav-item" href="#">Press</a> <a class="blog-nav-item" href="#">New hires</a> <a class="blog-nav-item" href="#">About</a> </nav> </div> </div> <div class="container"> <div class="blog-header"> {# 从这里开始替换#} <table class="table"> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> {# 如果students为空,则渲染empty下的内容#} {% for stu in students %} <tr {% if stu.age < 17 %}style="color:blue;" {% elif stu.age > 16 and stu.age < 22 %}style="color:red;" {% else %}style="color:green;" {% endif %}> {# forloop.counter获取当前for循环的迭代次数,以1开始#} {# 硬编码跳转 <td><a href="/students/detail/{{ stu.id }}/">{{ forloop.counter }}</a></td>#} <td><a href="{% url 'students:detail' stu.id %}">{{ forloop.counter }}</a></td> {# forloop.counter0获取当前for循环的迭代次数,以0开始#} {# <td>{{ forloop.counter0 }}</td>#} {# forloop.revcounter获取当前for循环的迭代次数,从大到小#} {# <td>{{ forloop.revcounter }}</td>#} {# forloop.revcounter0获取当前for循环的迭代次数,从大到小,最小为0#} {# <td>{{ forloop.counter0 }}</td>#} <td>{{ stu.name }}</td> <td>{{ stu.age }}</td> {#to_male对应customer_filter.py的@register.filter的name名对应#} <td>{{ stu.gender|to_male:'en' }}</td> </tr> {# 如果students为空,则渲染empty下的内容#} {# {% empty %}#} {# 要渲染的内容#} {% endfor %} </table> </div> </div><!-- /.blog-sidebar --> <div style="position:fixed; bottom:0px;"> {# 将渲染好的模板放到想要放的模板#} {% include 'students/ad.html' %} </div> {% endblock %} {% block domready %} <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script> <script>window.jQuery || document.write('<script src="../../assets/js/vendor/jquery.min.js"><\/script>')</script> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> {% endblock %}
-
customer_filter.py的demo:
from django.template import Library register = Library() #register名称固定,不可改 # @register.filter() #和下一行的区别是下一行可以定义name名 #自定义过滤器的第二种方法 @register.filter(name='to_male') #'to_male'对应{{ stu.gender }}的to_male def to_male(value, arg='zh'): #默认是中文 map = { 'zh': ('女', '男'), 'en': ('female', 'male') } # if value == 0: # if arg == 'zh': # return '女' # return 'female' # if value == 1: # if arg == 'zh': # return '男' # return 'male' return map[arg][value] #等同于上几行注释掉的demo #下面三行注释掉的是一样的效果,是注册自定义过滤器的第一种方法 # register.filter('to_male', to_male) # register.filter(to_male) # register.filter(name='to_male', filter_func=to_male)
效果图:
自定义模板标签
简单标签
django.template.Labrary.simple_tag()
- 新建Python模块
- 在templatetags中创建py文件,customer_tags.py
- 注册
- 调用函数
- 装饰器
- 引用上下文变量(views中render传递到模板中的那个context)
- 只需要在simple_tag中,设置参数take_context=True
- 自定义的标签函数的第一个参数一定是context
- 使用自定义模板标签
- 需要使用{% load 模块名 %}标签将我们的自定义的模块加载进来
demo
-
views.py的代码:
format_str = '%Y-%m-%d %H:%M:%S' return render(request, 'students/index.html', context={ 'students': students, 'format_str': format_str, })
-
index.html的代码:
{% load customer_tags %} #在开头 <h1>当前时间:{% current %}</h1> #在正文部分
-
customer_tags的代码:
from django.template import Library from datetime import datetime register = Library() @register.simple_tag(name='current', takes_context=True) #注册,装饰器 def current_time(context): #context必须是第一个参数,并且名字固定,不能改 return datetime.now().strftime(context['format_str']) # register.simple_tag(current_time, name='current') #注册,调用函数
包含标签
django.template.Library.inclusion_tag()
- 通过渲染另外一个模板来展示数据,类似url中的include
定义
-
在customer_tags模板中定义一个函数,接受调用时传递的模板变量
@register.inclusion_tag('students/show_list_as_ul.html') #参数是想要传的模板路径 def show_list_as_ul(value, style): return {'ls': value, 'style': style} # registerinclusion_tag('students/show_list_as_ul.html')(show_list_as_ul)
-
定义一个模板
-
tag()方法有两个参数:
- 模板标记的名称是字符串,如果省略,将使用编译函数的名称
- 编译的函数是一个Python函数(不要把函数名写成字符串)
- 和简单标签注册一样,也可以将其用做装饰器
- 也可以拿到context,和简单标签用法一样
-
包含标签的功能是可以通过渲染另外一个模板来显示一些数据
-
很多地方都可能会用到下面这几行代码,除了choices(模板变量)这几个变量不一样之外,其他的都是格式都一样时,那么我们就可以把这部分代码封装在一个包含标签中
<ul> {% for i in choices %} <li>{{ i }}</li> {% endfor %} </ul>
案例
-
show_list_as_ul.html的代码:
{% if style == 'button' %} <div class="list-group"> {% for l in ls %} <button type="button" class="list-group-item">{{ l }}</button> {% endfor %} </div> {% elif style == 'link' %} <div class="list-group"> {% for l in ls %} <a href="#" class="list-group-item active">{{ l }}</a> {% endfor %} </div> {% else %} <ul class="list-group"> {% for l in ls %} <li class="list-group-item">{{ l }}</li> {% endfor %} </ul> {% endif %}
-
index.html的部分代码:
{# <td>{% show_list_as_ul stu.course 'link' %}</td>#} {# 等同于上行代码#} {# <td>{% show_list_as_ul stu.course style='link' %}</td>#} {# <td>{% show_list_as_ul stu.course 'button' %}</td>#} <td>{% show_list_as_ul stu.course '' %}</td>
-
customer_tags.py的部分代码:
@register.inclusion_tag('students/show_list_as_ul.html') #参数是想要传的模板路径 def show_list_as_ul(value, style): return {'ls': value, 'style': style} # register.inclusion_tag('students/show_list_as_ul.html')(show_list_as_ul)
模型的创建与映射
django模型映射关系
- 模型类必须都写在app下的models.py文件中
- 模型如果需要映射到数据库,所在的app必须被安装
- 一个数据表对应一个模型类,表中的字段对应模型中的类属性,一个实例对应数据表中的一条数据
django连接MySQL的配置流程
-
安装pymysql:pip install pymysql
-
创建数据库用户(有数据库权限的用户)
-
创建数据库(我的是django_test)
-
修改配置(settings.py)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_test', 'USER':'xiaoge', 'PASSWORD':'*****', 'HOST':'127.0.0.1', 'PORT':'****' } }
-
修改项目文件夹(和settings.py文件所在的目录)下的__init__.py添加代码:
import pymysql pymysql.install_as_MySQLdb()
-
设置时区(settings.py)
TIME_ZONE = 'Asia/Shanghai' #北京时间
创建模型
-
创建一个student的模型,代表学生
-
每一个模型都是django.db.models.Model的子类
-
类变量表示模型中的数据库字段
-
每一个字段由一个字段类的实例表示
-
数据表的名称就是模型的名称
-
在students中的models.py文件中创建模型
from django.db import models class Student(models.Model): #继承 #可以不写主键,模型会创建 # id = models.IntegerField(primary_key=True,auto_created=True) name = models.CharField(max_length=20) #字符串 age = models.SmallIntegerField(default=0) #整数,默认为0,表示没填 sex = models.SmallIntegerField(default=1) #整数,默认为1(男) qq = models.CharField(max_length=20,default='') #字符串,默认不填 phone = models.CharField(max_length=20,default='') #字符串,默认不填 c_time = models.DateTimeField(verbose_name='创建时间',auto_now_add=True) #创建时间,自动记录当前时间 def __str__(self): return '%s-%s' % (self.name,self.age)
**模型
-
在项目中注册app
- 在settings.py的INSTALLED_APPS中注册
-
运行数据库迁移命令(在项目根目录下)
python manage.py makemigrations students#如果不加students,settings.py的INSTALLED_APPS中所有的app都会迁移
- 告诉django我们做了哪些数据库的修改
数据库迁移文件见下图的0001_initial.py,再修改就会多个0002
- python manage.py sqlmigrate students 0001可以从迁移的地方获取sql语句,效果见下图
- 表名:appname_模型name(小写的),如students_student
- django会自动创建主键,一般取名为id
-
此时数据库中还没有表,需要运行migrate命令使迁移生效
python manage.py migrate students
- 要修改数据库,都要修改模型,然后运行数据库迁移命令,再运行使迁移生效命令
数据的增删改查
-
django shell调试工具
python manage.py shell
-
导入模型
from students.models import Student