一、安装Django
下载地址:https://www.djangoproject.com/download/
1、tar zxvf Django-1.8.10.tar.gz
2、cd Django-1.8.10
3、python setup.py install
二、创建一个Django项目
django-admin startproject sitename
常用命令:
python manage.py runserver 0.0.0.0
python manage.py startapp appname
python manage.py syncdb
# 集成已有数据库的应用,通过数据库生成model类
python manage.py inspectdb
# 通过model类生成数据库
python manage.py makemigrations
python manage.py migrate
三、URL路由
1、每个路由规则对应一个view中的函数
from django.conf.urls import include, url
from django.contrib import admin
from views import *
urlpatterns = [
url('^hello/$',hello),
url('^time/$',current_datetime),
url(r'^time/plus/(\d{1,2})/$',hours_ahead),
]
2、根据app对应路由规则的分类
url(r'^web1/',include('web1.urls'))
app:web1.urls
from django.conf.urls import include, url, patterns
from django.contrib import admin
from web1.views import *
urlpatterns = patterns('',
url(r'^add/(?P<name>\w*)&(?P<not_name>\w*)/$',Add),
url(r'^del/(?P<id>\d*)/$',Delete),
url(r'^Update/(?P<id>\d*)&(?P<name>\w*)/$',Update),
)
添加app到框架应用
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'ops01',
)
四、数据库操作
1、配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'dbname', 'USER': 'root', 'PASSWORD': 'xxx', 'HOST': '', 'PORT': '', } }
2、根据models.Model创建数据表
#!/usr/local/python27/bin/python2.7
# coding:utf8
# Create your models here.
from django.db import models
class UserInfo2(models.Model):
username = models.CharField(max_length=50)
password = models.CharField(max_length=50)
memo = models.CharField(max_length=50)
class args(models.Model):
id = models.AutoField(primary_key = True)
name = models.CharField(max_length=20,null=True)
not_name = models.CharField(max_length=20,null=False)
create_data = models.DateTimeField(auto_now_add = True)
update_date = models.DateTimeField(auto_now = True,error_messages={"invalid":'日期格式错误'})
3、更多字段:
1、models.AutoField # 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。 2、models.CharField # 字符串字段必须 max_length 参数 3、models.BooleanField 布尔类型=tinyint(1) # 不能为空,Blank=True 4、models.ComaSeparatedIntegerField # 用逗号分割的数字=varchar 继承CharField,所以必须 max_lenght 参数 5、models.DateField # 日期类型 date 对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。 6、models.DateTimeField # 日期类型 datetime 同DateField的参数 7、models.Decimal # 十进制小数类型 = decimal 必须指定整数位max_digits和小数位decimal_places 8、models.EmailField # 字符串类型(正则表达式邮箱)=varchar 对字符串进行正则表达式 9、models.FloatField # 浮点类型 = double 10、models.IntegerField # ××× 11、models.BigIntegerField # 长××× integer_field_ranges = { 'SmallIntegerField': (-32768, 32767), 'IntegerField': (-2147483648, 2147483647), 'BigIntegerField': (-9223372036854775808, 9223372036854775807), 'PositiveSmallIntegerField': (0, 32767), 'PositiveIntegerField': (0, 2147483647), } 12、models.IPAddressField # 字符串类型(ip4正则表达式) 13、models.GenericIPAddressField # 字符串类型(ip4和ip6是可选的) # 参数protocol可以是:both、ipv4、ipv6 # 验证时,会根据设置报错 14、models.NullBooleanField # 允许为空的布尔类型 15、models.PositiveIntegerFiel # 正Integer 16、models.PositiveSmallIntegerField # 正smallInteger 17、models.SlugField # 减号、下划线、字母、数字 18、models.SmallIntegerField # 数字 数据库中的字段有:tinyint、smallint、int、bigint 19、models.TextField # 字符串=longtext 20、models.TimeField # 时间 HH:MM[:ss[.uuuuuu]] 21、models.URLField # 字符串,地址正则表达式 22、models.BinaryField # 二进制 23、models.ImageField # 图片 24、models.FilePathField # 文件
4、更多字段参数:
1、null=True # 数据库中字段是否可以为空 2、blank=True # django的 Admin 中添加数据时是否可允许空值 3、primary_key = False # 主键,对AutoField设置主键后,就会代替原来的自增 id 列 4、auto_now 和 auto_now_add # auto_now 自动创建---无论添加或修改,都是当前操作的时间 # auto_now_add 自动创建---永远是创建时的时间 5、choices # GENDER_CHOICE = ( # (u'M', u'Male'), # (u'F', u'Female'), # ) # gender = models.CharField(max_length=2,choices = GENDER_CHOICE) 6、max_length 7、default # 默认值 8、verbose_name # Admin中字段的显示名称 9、name|db_column # 数据库中的字段名称 10、unique=True # 不允许重复 11、db_index = True # 数据库索引 12、editable=True # 在Admin里是否可编辑 13、error_messages=None # 错误提示 14、auto_created=False # 自动创建 15、help_text # 在Admin中提示帮助信息 16、validators=[] 17、upload-to
5、数据库操作
from django.shortcuts import render
from web1.models import *
from django.http import HttpResponse
from django.db.models import Min,Max,Sum
from django.db import connection,transaction
# Create your views here.
# 添加数据
def Add(request,name,not_name):
args.objects.create(not_name=not_name,name=name)
return HttpResponse('ok')
# 删除数据
def Delete(request,id):
args.objects.get(id=id).delete()
return HttpResponse('delete ok')
# 更新数据,单行更新
def Update(request,id,name):
obj = args.objects.get(id=id)
obj.name = name
obj.save()
return HttpResponse('update ok')
# 根据id大于等于的条件,多行更新
args.objects.filter(id__gt=id).update(name=name)
return HttpResponse('multi update ok')
# 根据id小于等于的条件,多行更新,也可以用于多行删除
args.objects.filter(id__lt=id).update(name=name)
return HttpResponse('multi update ok')
# 根据等于的条件多行操作
args.objects.filter(id=id).update(name=name)
return HttpResponse('multi update ok')
#还可以通过filter(id__in = [1,2,3])进行多行操作
# 模糊查询
obj = args.objects.filter(name__contains=name)
# 模糊查询(忽略大小写)
obj = q.exclude(body_text__icontains="food")
# -------- 条件查询更多参数 -------------
# 表示!=
exclude
# 去重复
querySet.distinct()
# 精确等于 like 'aaa'
__exact
# 精确等于 忽略大小写 ilike 'aaa'
__iexact
# 包含 like '%aaa%'
__contains
# 包含,忽略大小写 ilike '%aaa%',但是对于sqlite来说,contains的作用效果等同于icontains。
__icontains
# 大于
_gt
# 大于等于
__gte
# 小于
__lt
# 小于等于
__lte
# 存在于一个list范围内
__in
# 以...开头
__startswith
# 以...开头 忽略大小写
__istartswith
# 以...结尾
__endswith
# 以...结尾,忽略大小写
__iendswith
# 在...范围内
__range
# 日期字段的年份
__year
# 日期字段的月份
__month
# 日期字段的日
__day
# 空集
__isnull=True/False
# 扩展学习,示例
# 大于
p1 = Permission.objects.all().filter(content_type_id__gt=12)
# 大于等于
p1 = Permission.objects.all().filter(content_type_id__gte=12)
# 去重
p1 = Permission.objects.all().filter(content_type_id__gte=12).distinct()
# 前缀查询
q1 = Entry.objects.filter(headline__startswith="What")
# 排除
q2 = q1.exclude(pub_date__gte=datetime.date.today())
# 操作时间
q1.filter(pub_date__gte=datetime.date.today())表示为时间>=now,
q1.exclude(pub_date__gte=datetime.date.today())表示为<=now
'''
关于缓存:
queryset是有缓存的,a = A.objects.all(),print [i for i in a].
第一次执行打印会查询数据库,然后结果会被保存在queryset内置的cache中,
再执行print的时候就会取自缓存。
很多时候会遇到仅需判断queryset是否为空的情况,可以
1. if queryset:pass 2.if queryset.count>0:pass 3.if queryset.exists():pass.
三种方式性能依次提升。
当queryset非常巨大时,cache会成为问题。
此时可以queryset.iterator(),迭代器的用处就不多说了,根据具体需求情况使用。
'''
# 通过values()指定获取单列数据。
alldata = args.objects.all().values('id')
alldata = args.objects.values('id')
# 获取单列去重数据
alldata = args.objects.values('id').distinct()
# 获取指定行数据,[0:3] 从0行开始向下获取3行数据
def get_limit(request):
alldata = args.objects.all()[0:3]
print alldata.query
return HttpResponse(alldata)
# 排序 ,(‘-id’)为逆序
alldata = args.objects.all().order_by('id')
alldata = args.objects.all().order_by('-id')
# 聚合函数
def juhe(request):
alldata = args.objects.aggregate(Max('id'))
print alldata
return HttpResponse(alldata)
# 使用自定义的原生SQL语句
'''
cursor = connection.cursor()
cursor.execute('SELECT DISTINCT first_name ROM people_person WHERE last_name = %s', ['Lennon'])
row = cursor.fetchone()
'''
# 实例:
def sour_sql(request,id):
cursor = connection.cursor()
cursor.execute('''SELECT id FROM web1_args where id > %s ''' % id )
row = cursor.fetchall()
print row
return HttpResponse(row)
# 通过调用SQL 函数inet_aton()将IP地址转为INT格式存储
cursor = connection.cursor()
cursor.execute("SELECT inet_aton('%s')" % wip)
data = cursor.fetchall()
sqldatawip = data[0][0]
cursor.execute("SELECT inet_aton('%s')" % lip)
data = cursor.fetchall()
sqldatalip = data[0][0]
五、模版语言
1、模版文件夹路径配置
Django1.8 setting.py
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',
],
},
},
]
2、判断语句编写格式
# 判断
{% if not user %}
<h2>have data</h2>
{% else %}
<h2>haven't data</h2>
{% endif %}
# 取反判断
{% if not user %}
<h2>have data</h2>
{% else %}
<h2>haven't data</h2>
{% endif %}
# ifequal/ifnotequal 等价判断,user 是否等于 'tuchao'
{% ifequal user 'tuchao' %}
<h3>right!</h3>
{% else %}
<h3>error!</h3>
{% endifequal %}
3、循环语句编写
# 循环装有数据的表格,使得页面中有格式的显示数据
{% for item in data %}
<tr>
<td>`item`.`id`</td>
<td>{% mymethod item.id %}</td>
<td>`item`.`name`</td>
<td>`item`.`not_name`</td>
<td>{{item.create_data|date:"Y-m-d H:i:s"}}</td>
<td>{{item.update_date|date:"Y-m-d H:i:s"}}</td>
</tr>
{% endfor %}
# 给标签增加一个 reversed 使得该列表被反向迭代:
{% for athlete in athlete_list reversed %}
...
{% endfor %}
# 先检查列表是否有数据再循环
{% if athlete_list %}
{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>
{% endfor %}
{% else %}
<p>There are no athletes. Only computer programmers.</p>
{% endif %}
# `` for`` 标签支持一个可选的`` {% empty %}`` 分句,通过它我们可以定义当列表为空时的输出内容 下面的例子与之前那个等价:
{% for athlete in athlete_list %}
<p>{{ athlete.name }}</p>
{% empty %}
<p>There are no athletes. Only computer programmers.</p>
{% endfor %}
# forloop.counter 总是一个表示当前循环的执行次数的整数计数器。 这个计数器是从1开始的,所以在第一次循环时 forloop.counter 将会被设置为1。
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
# forloop.last 是一个布尔值;在最后一次执行循环时被置为True。 一个常见的用法是在一系列的链接之间放置管道符(|)
{% for link in links %}{{ link }}{% if not forloop.last %} | {% endif %}{% endfor %}
# 上面的模板可能会产生如下的结果:
Link1 | Link2 | Link3 | Link4
# 另一个常见的用途是为列表的每个单词的加上逗号。
# Favorite places:
{% for p in places %}{{ p }}{% if not forloop.last %}, {% endif %}{% endfor %}
4、过滤器
模版过滤器是在变量被显示前修改它的值的一个简单方法
# 内容变量 name 被过滤器lower处理-转换文本为小写
{{ name|lower }}
# 过滤管道可以被* 套接* ,既是说,一个过滤器管道的输出又可以作为下一个管道的输入
# 实现查找列表的第一个元素并将其转化为大写
{{ my_list|first|upper }}
# 显示 bio变量的前30个字符
{{ bio|truncatewords:"30" }}
# date 按照指定的格式,格式化date和datetime对象
{{create_data|date:"Y-m-d H:i:s"}}
{{update_date|date:"Y-m-d H:i:s"}}
{{delete_date|date:"F j, Y" }}
# addslashes : 添加反斜杠到任何反斜杠、单引号或者双引号前面。 这在处理包含JavaScript的文本时是非常有用的。
5、自定义模版方法
1、在app目录下创建templatetags文件夹,用于保存自定义方法文件
2、创建__init__.py文件
3、创建任意.py文件编写自定义方法
# 代码实例 hand.py
#!/usr/local/python27/bin/python2.7
#coding:utf-8
from django import template
from django.template.base import resolve_variable, Node, TemplateSyntaxError
register = template.Library()
#上面的均为固定格式,注意这里定义的方法必须被自己实例化的对象里的装饰器@register.simple_tag)进行装饰才有效
@register.simple_tag
def mymethod(v1):
result = v1*1000
return result
Html调用自定义模版方法
{% extends "master/moban.html" %}
{% block content %}
<!-- 载入自定义方法文件 -->
{% load hand %}
<table border='1'>
{% for item in data %}
<tr>
<td>`item`.`id`</td>
<!-- 调用自定义方法,将id值乘1000返回 -->
<td>{% mymethod item.id %}</td>
<td>`item`.`name`</td>
<td>`item`.`not_name`</td>
</tr>
{% endfor %}
6、模版的继承
当我们在开发一个动态站点的时候,会发现在整个站点中很多页面的样式,图片、Logo、导航栏等等都有相同的部分,那我们如何减少这些冗余代码呢? 下面通过学习父板及子板继承关系的方式来解决
# 定义一个父模版,其中的block块是子板可以重载的部分。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>{% block title %}{% endblock %}</title>
</head>
<body>
<h1>My helpful timestamp site</h1>
{% block content %}{% endblock %}
{% block footer %}
<hr>
<p>Thanks for visiting my site.</p>
{% endblock %}
</body>
</html>
# 创建一个子板,继承父模版
# 该标记用于指定继承自哪个父模版,必须保证其为模板中的第一个模板标记。 否则,模板继承将不起作用。
{% extends "base.html" %}
# 重载子板的title部分
{% block title %}The current time{% endblock %}
# 重载子板的内容部分
{% block content %}
<p>It is now {{ current_date }}.</p>
{% endblock %}
# 这个子模版的title 和 body 内容部分都自己定制不继承自父模版,剩下没有被重载的任何部分都继承自父模版,如{% block footer %} 部分。
六、Django-form表单
Django 提供一个form.Form类可以快速实现表单的功能,而且提供便捷的方式解决了验证提交数据的格式是否合法的问题。
1、在app目录下创建一个forms.py的文件
# 实例代码
#!/usr/local/python27/bin/python2.7
# coding=utf8
# noinspection PyUnresolvedReferences
from django import forms
# 定义一部分需要用到的表单,attrs属性用于定义该表单的样式信息。 指定的样式需要在对应的CSS文件中编写。
class RegisterForm(forms.Form):
username = forms.CharField(widget=forms.TextInput(attrs={'class':'user_name'}))
password = forms.CharField(widget=forms.PasswordInput(attrs={'class':'pwd'}))
real_name = forms.CharField(widget=forms.TextInput)
email = forms.EmailField(required=True,error_messages={'invalid':'邮箱格式错误'})
gender = forms.BooleanField()
class AdminHostAdd(forms.Form):
othername = forms.CharField(widget=forms.TextInput(attrs={'class':'othername'}))
hostname = forms.CharField(widget=forms.TextInput(attrs={'class':'hostname'}))
hardconfig = forms.CharField(widget=forms.TextInput(attrs={'class':'hardconfig'}))
wip = forms.IPAddressField()
lip = forms.IPAddressField()
2、views.py 文件中调用实例代码
#!/usr/local/python27/bin/python2.7
# coding=utf8
# noinspection PyUnresolvedReferences
from django.shortcuts import render
# 从定义的forms.py文件中导入类
from ops01.forms import RegisterForm,AdminHostAdd
from django.http import HttpResponse
from django.shortcuts import render_to_response
from ops01.models import *
from django.db import connection,transaction
# 用户注册函数
def Register(request):
reg = RegisterForm() # 实例化
if request.method == 'POST':
form = RegisterForm(request.POST)
# 判断提交的表单数据,是否符合表单定义的数据格式。
if form.is_valid():
# 获取提交的所有数据,这里会返回一个字典对象
data = form.cleaned_data
username = data.get('username')
password = data.get('password')
realname = data.get('real_name')
email = data.get('email')
try:
# 数据库操作,将合法的数据记录到数据库
user.objects.create(username=username,password=password,realname=realname,email=email)
except e:
print (e)
print data
else:
temp = form.errors.as_data()
print temp
print type(temp)
# 在返回结果的时候将实例化的form对象reg嵌套进Html一起返回
return render_to_response('register.html',{'form':reg,'status':'注册失败'})
return render_to_response('register.html',{'form':reg})
# 主机信息添加函数
def hostinfoadd(request):
hostadd = AdminHostAdd()
if request.method == 'POST':
form = AdminHostAdd(request.POST)
if form.is_valid():
data = form.cleaned_data
hostname = data.get('hostname')
othername = data.get('othername')
wip = data.get('wip')
lip = data.get('lip')
hardconfig = data.get('hardconfig')
cursor = connection.cursor()
cursor.execute("SELECT inet_aton('%s')" % wip)
data = cursor.fetchall()
sqldatawip = data[0][0]
cursor.execute("SELECT inet_aton('%s')" % lip)
data = cursor.fetchall()
sqldatalip = data[0][0]
try:
host.objects.create(othername=othername,hostname=hostname,wanip=sqldatawip,lanip=sqldatalip,hardconfig=hardconfig)
except e:
print e
return render_to_response('admin-host-add.html',{'form':hostadd,'status':'记录添加成功!'})
else:
return render_to_response('admin-host-add.html',{'form':hostadd,'status':'数据格式错误!'})
return render_to_response('admin-host-add.html',{'form':hostadd})
3、对应的部分Html实例代码
# 注册页面
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>账户注册</title>
<style type="text/css" >
.title{
font-size: 25px;
font-weight: bold;
display: block;
margin-left: 46%;
margin-top: 40px;
}
.regdiv{
background: #FFF;
height: 500px;
width: 450px;
left: 470px;
position: relative;
top: 53px;
}
.reghead{
height: 41px;
position: absolute;
width: 100%;
top: 30px;
line-height: 0px;
border-bottom: 1px solid #F2F2F2;
}
.reghead h3{
font-size: 21px;
left: 19px;
display: block;
position: absolute;
}
.r_name{
height: 50px;
position: absolute;
width: 100%;
top: 105px;
left: 12px;
}
.u_name{
height: 30px;
position: absolute;
width: 100%;
top: 180px;
left: 12px;
}
.passwd{
height: 30px;
position: absolute;
top: 255px;
left: 12px;
}
.mail{
height: 30px;
top: 327px;
position: absolute;
width: 100%;
left: 12px;
}
.mail input{
height:30px;
width: 300px;
}
.r_name input{
width: 300px;
height: 30px;
}
.user_name {
height: 30px;
width: 300px;
}
.pwd{
width: 300px;
height: 30px;
}
.sub {
height: 32px;
position: absolute;
bottom: 42px;
left: 83px;
}
.sub input {
padding: 8px;
width: 300px;
background-color: rgb(53, 84, 146);
font-size: 20px;
font-weight: bold;
color: #FFF;
}
.gd{
bottom: 94px;
left: 80px;
font-size: 14px;
position: absolute;
}
.failstatus{
color: #ff2d28;
width: 222px;
display: block;
position: absolute;
height: 51px;
left: 141px;
top: 32px;
font-size: 28px;
font-family: "Microsoft YaHei";
font-weight: bold;
letter-spacing: 14px;
}
</style>
</head>
<body style="background:#D6E4FF; margin:0px auto; height:920px;">
<span class="title">Regsiter Page</span>
<div class="regdiv">
<div class="reghead"><h3>注册</h3></div>
<!-- 通过模版语言调用通过 render_to_response 方法传入的字典对象 -->
<span class="failstatus">{{ status }}</span>
<form action="/ops01/reg/" method="post">
<!-- 通过模版语言的格式调用form -->
<div class="r_name">真实姓名:{{ form.real_name }}</div>
<div class="u_name">用 户 名:{{ form.username }}</div>
<div class="passwd">密 码:{{ form.password }}</div>
<div class="mail">邮 箱:{{ form.email }}</div>
<div class="gd">{{ form.gender }}我已经同意<a href="#">隐私政策、服务条款</a></div>
<div class="sub"><input type="submit" value="注 册" /></div>
</form>
</div>
</body>
</html>
<!-- -------------------------------------------------------------------------------- -->
<!-- 主机信息添加页 -->
{% extends "masterplate.html" %}
{% block title %}主机添加{% endblock %}
{% block content %}
<div class="admin-content-admin-host-add content_font">
<div class="am-cf am-padding">
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">主机信息添加</strong> / <small>Host information add</small></div>
</div>
<hr />
<form action="/ops01/hostadd/" method="post">
<div style="margin-left: 20px;">
主机名<hr />
{{ form.hostname }}<hr />
</div>
<div style="margin-left: 20px;">
别名<hr />
{{ form.othername }}<hr />
</div>
<div style="margin-left: 20px;">
外网IP<hr />
<div class="wipdiv">{{ form.wip }}</div><hr />
</div>
<div style="margin-left: 20px;">
内网IP<hr />
<div class="lipdiv">{{ form.lip }}</div><hr />
</div>
<div style="margin-left: 20px;">
硬件配置<hr />
{{ form.hardconfig }}<hr />
</div>
<span class="hostaddstatus">{{ status }}</span>
<div class="hostaddbottomdiv"><input type="submit" class="hostaddbottom" name="hostinfosubmit" value="提交至数据库" /></div>
</form>
</div>
{% endblock %}
<!-- -------------------------------------------------------------------------------- -->
<!-- 主机列表页面 -->
{% extends "masterplate.html" %}
{% block title %}主机列表{% endblock %}
{% block content %}
<div class="admin-content">
<div class="am-cf am-padding">
<div class="am-fl am-cf"><strong class="am-text-primary am-text-lg">主机列表</strong> / <small>Host information</small></div>
</div>
<table border="1" class="hovertable">
<tr>
<th>主机ID</th><th>主机名</th><th>所属业务</th><th>内网IP</th><th>外网IP</th><th>配置信息</th>
</tr>
{% for i in list %}
<tr onmouseover="this.style.backgroundColor='#ffff66';" onmouseout="this.style.backgroundColor='#d4e3e5';">
<td>{{ i.hid }}</td>
<td>{{ i.hostname }}</td>
<td>{{ i.othername }}</td>
<td>{{ i.wanip }}</td>
<td>{{ i.lanip }}</td>
<td>{{ i.hardconfig }}</td>
</tr>
{% endfor %}
</table>
</div>
{% endblock %}
七、静态文件存放配置
STATIC_URL = '/static/'
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
转载于:https://blog.51cto.com/tchuairen/1750478