404:有域名无路由。路由是网址中 域名后 、 ?前 的那段;?后是参数,参数中15开头的13位数字通常是时间戳。
urls.py、views.py、xxxx.html中,所出现的各种相对路径:
拼接的是 IP地址(或域名):①路由函数内 开头无/的路由首参;②视图函数或html内 开头无/的项目根目录(即与manage.py同级的文件夹或文件);③视图函数或html内 开头是/的 网址;
拼接的是 路由首参等IP之后的半截网址:视图函数或html内,① 开头无/的网址;② 开头是/的项目次级目录(即与manage.py同级的某app文件夹下的子文件夹或子文件)。所以 路由函数内的 各首参网址,开头无/,结尾却要有/,不然与之对应的视图函数或html内,开头无/的各相对路径,拼接不过来。
1级路径是第1个/前的部分,指IP域名或位于项目根目录下的本地文件夹;2级路径是前2个/之间的部分,项目根目录下的某app文件夹下的2级文件夹如static, 不论作为非路由网址还是本地2级文件夹,前后都要有/;3级路径如static下的文件夹css,开头无/。
Eg:settings.py底部的STATIC_URL = ' /static /',前后都有/的原因:
①本地文件夹和网址的双重身份:static作为本地文件夹,放在project的 某个app下而非project根下,所以开头得有/;作为写在路由函数之外的网址, 拼接的是IP域名,开头同样要求有/。
②css等第3级子文件夹或子文件,并非拼接在域名后,按拼接语法开头不能有/,故网址/static, 结尾得补个/,才能接收css…等第3级路径拼接在其末尾。
**************************分割线**************************
django1.6自定义markdown过滤器:
http://www.zhidaow.com/post/django-custom-template-tag-markdown
设计个有远见的数据库=项目完成了一半=几千行代码。让当前的代码活事半功倍,而且减少日后修改的次数和面积。数据库的架构是企业的核心机密,同行业的竞争对手看到你的数据库架构,就能山寨出来一个高度相似的项目。
**************************分割线**************************
三大web框架的不同请求的各自写法:
tornado用方法 self.get_argument( 'name值' ) ,flask和django都用字典:request.xxx['name值']
①tornado:不论是get还是post请求, 都是self.get_argument('name属性的值',default=None)
②flask:get请求用 request.args[' name值'],post 请求用 request.form['name值'];
③django:
request.GET['type为 text的input标签的 name属性的值'],结果在网址尾;
request.POST[ 'name值'], request.FILES['type为 file……'],它俩的结果都藏在postData中;
request.META['某个请求头如 HTTP_REFERER']
**************************分割线**************************
html模板:① {{变量}};
② {% 语法如 if、for…in…、 with…as… 等;或函数如 load static from staticfiles、 csrf_token 等 %}
django和flask的 html模板中的 循环或判断:
(tornado例外,结尾全是 {% end %},字典用d [' key '] 而非d . key)
{% for country in countries %}
{% for city in country .cities %}
国家#{{forloop.parentloop.counter}}:{{city}}
{% if not forloop.last %}
,
{% else %}
\n
{% endif %}
{% endfor %}
{% endfor %}
****************************************分割线****************************************
django做个电影网站:
①E盘下建个movie文件夹→PyCharm新建项目选Django→location改为E:\movie→More Settings的Application写个dy ;
(注:PyCharm新建好django项目后,启动项目是在settings.py等界面,按绿方块dj+根目录如movie右侧的绿三角,而非我所自定义并习惯了的F5键Run context configuration)
**************************分割线**************************
②项目文件夹movie:
***************分割线***************
配置文件settings.py:
DEBUG = True在部署到Linux服务器之前要改为False。 INSTALLED_APPS尾已自动添加了dy…,不理会;若新建应用,则模仿dy…添加。
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
#以下四项,和软件Navicat for MySQL的连接界面一样
'HOST': 'mysql.litianqiang.com', # 潭州的远程mysql
'PORT': '7150', # mysql的默认端口3306;端口值在django中是str, MySQLdb中是int
'USER': 'movie',
'PASSWORD': '……()', # 隐藏 ……处,用的院长的绰号
'NAME': ' movie', #潭州学院那个目标数据库的名字
}
}
***************分割线***************
路由文件(各正则网址)urls.py:
from django.conf.urls import url
from django.contrib import admin
from dy import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^chengy /', views.chengy), # url函数的二参是某个视图函数的名字,不是加了()的返回值
url(r' ^$', views.index, name='index'), #首页是^$,无 / ;给路由起个别名,方便视图函数调用
]
**************************分割线**************************
③应用文件夹dy:
***************分割线***************
让Python和数据库交互(俗称ORM)的文件models.py:
在 E:\movie路径下进入cmd:python manage.py inspectdb > dy/models.py
回车后, settings.py中所配置的数据库movie中的各表,会以class的形式(首字母大写,去除表名中的_),自动写入 models .py
***************分割线***************
各路由网址呈现什么内容的文件views.py:
from django.shortcuts import render
from django.http import HttpResponse #网页显示字符串,太简陋,一般不用它
from dy.models import DyDymodels #导入 movie库中 电影数据源所在的那张表
def chengy(request):
return HttpResponse('hello,chengy')
def index(request):
movies=''
kw=request.POST.get(' kw') #键值用get()取,即便搜索词为空也不报错,返回None
if kw:
#movies=DyDymodels.objects.get(id=1) #.get()取1行记录,.all()[:50]取前50行
movies=DyDymodels.objects.filter(title __icontains=kw)[:19] #标题含关键词的前几条
context={' movies':movies}
return render(request,'index.html',context=context)
***************分割线***************
应用文件夹dy下新建个templates文件夹,其内新建个index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>电影下载-首页</title>
</head>
<body>
<form action="/" method="post">
{% csrf_token %} <!--跨域攻击;新浪上写博客不支持半角<符和autocomplete单词-->
<input type="text" name=" kw" style="width: 500px" auto ¥complete=" off">
<input type="submit" value="搜索电影">
</form><br>
{% if movies %}
{% for movie in movies %}
<li><a href="{{ movie .link }}">{{ movie .title }}</a></li>
{% endfor %}
{% endif %}
</body>
</html>
****************************************分割线****************************************
开发网盘:
①E盘下建个wangpan文件夹→……Application写个disk;
***************分割线***************
②项目文件夹wangpan:
__init__.py:
import pymysql
pymysql.install_as_MySQLdb()
settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST':'localhost','PORT':'3306','USER':'chengy','PASSWORD':'',
'NAME': '网盘'
}
}
urls.py:
from django.conf.urls import url
from django.contrib import admin
from disk import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index , name=' index' ),
url(r'^upload/$', views.upload , name=' upload' ),
url(r'^s/ (\w{32} )/$', views.content), #路由网址中的()(),是content函数的2参、3参等
url(r'^file/.*?$', views.download , name=' download ' ),
]
***************分割线***************
③应用 文件夹disk:
models.py:
from django.db import models
class FileInfo(models.Model):
# id=models.AutoField(primary_key=True) #默认创建主键自增字段id
user=models.CharField(max_length=20,null=False)
fileName=models.CharField(max_length=30,null=False)
fileSize=models.IntegerField(null=False)
fileMd5=models.CharField(max_length=32,null=False)
在 E:\wangpan进入cmd,依次执行如下两句,用models.py的各类,生成mysql的网盘库的各表:
python manage.py makemigrations
python manage.py migrate
******分割线******
views.py:
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect
import hashlib
from disk.models import FileInfo
def index(request):
return render(request,'index.html')
def upload(request):
#在用户电脑上读取文件并计算MD5值,而非上传到网盘服务器后才计算
myFile=request .FILES.get(' upfile')
if not myFile: #print(myFile)
return HttpResponse('没上传文件')
file=myFile.read()
if not file:
return HttpResponse('不能上传空文件')
fileName=myFile.name
fileSize=myFile.size
fileMd5=hashlib.md5(file).hexdigest()
existed=FileInfo.objects.filter(fileMd5=fileMd5)
if existed:
FileInfo(fileName=fileName, fileSize=fileSize, fileMd5=fileMd5).save()
# return HttpResponse('文件成功秒传') #AttributeError 'tuple' no attribute 'get'
return HttpResponseRedirect(' /s/{}'.format(fileMd5)) #拼接的是域名,s前有/
with open('file/{}'.format(fileMd5),'wb') as f: #file,是 和manage.py同级 的文件夹 ,前无/
f.write(file)
FileInfo(fileName=fileName, fileSize=fileSize, fileMd5=fileMd5).save()
# return HttpResponse('文件上传完成')
return HttpResponseRedirect(' /s/{}'.format(fileMd5))
def content(request,fileMd5):
fileInfo=FileInfo.objects.filter(fileMd5=fileMd5) #类似正则的findall,提取某行记录要加[0]
if not fileInfo:
return HttpResponse('该文件不存在或已被删除')
context={
'fileName':fileInfo[0].fileName,
'fileSize':fileInfo[0].fileSize,
'fileUrl':' /file/{}'.format(fileInfo[0].fileName)} #下载时默认的文件名,取末/后的字串
return render(request,'content.html',context=context)
def download(request):
referer=request .META.get('HTTP_REFERER') #获取来路,只在部署到Linux前用
if not referer:
return HttpResponse('该文件不存在或已被删除') #防止复制下载网址来直接下载
fileMd5=referer[-33:-1]
fileInfo=FileInfo.objects.filter(fileMd5=fileMd5)
if not fileInfo:
return HttpResponse('该文件不存在或已被删除')
file=open('file/{}'.format(fileMd5),'rb').read()
response=HttpResponse(file) #HttpResponse的一个最大用处:下载流数据
response ["Content-type"]="application/octet-stream"
return response
***************分割线***************
④index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<form action=" /upload/" method="post" enctype="multipart/form-data">
{% csrf_token %} <!--跨域攻击-->
<input type="file" name=" upfile">
<input type="submit" value="上传">
</form>
</body>
</html>
content.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件下载</title>
</head>
<body>
<li>文件名:{{ fileName }}</li>
<br> <!--换行符-->
<li>文件大小:{{ fileSize }}</li>
<br>
<li><a href="{{ fileUrl }}">点击下载</a></li>
</body>
</html>
****************************************分割线****************************************
小说网站:
①E盘下建个novel文件夹→……Application写个xs;
***************分割线***************
② settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'HOST': 'mysql.litianqiang.com', 'PORT': '7150',
'USER': 'novel', 'PASSWORD': '……()', # 隐藏 ……处, 李院长 用的他的绰号
'NAME': ' novel',
}
}
urls.py:
from django.conf.urls import url
from django.contrib import admin
from xs import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', views.index,name='index'),
]
***************分割线***************
③ models.py:
在 E:\novel路径下进入cmd: python manage.py inspectdb > xs/models.py
views.py:
from django.shortcuts import render
from xs.models import NovelCopy
def index(request):
novelsHot=NovelCopy.objects.filter().order_by('?')[:4] #ORM模型,用?表示随机排序
novelsXH=NovelCopy.objects.filter(sort='玄幻').order_by('?')[:4]
novelsWX=NovelCopy.objects.filter(sort='武侠').order_by('?')[:5]
context = {'novelsHot':novelsHot,'novelsXH':novelsXH,'novelsWX':novelsWX}
return render(request,'index.html',context=context)
***************分割线***************
④index.html:
{% load staticfiles %} <!--若static文件夹及settings.py末尾均改了名,html中只需改这1处-->
<!doctype html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="Keywords" content=""/><meta name="description" content=""/>
<title>Python探索馆 - Slice</title>
<link rel="stylesheet" href=" {% static 'css/style.css' %}" /></head>
<body>
<div class="full-pic"></div> <!--===== Full Screen BG =====-->
<header class="header"> <!--===== Begin Header =====-->
<div class="fixed-head" style="position: fixed; width: 100%;">
<div class="wrap1000 head-wrap">
<div class="logo"><a href="detail.html">Python学院图书馆</a></div>
<div class="nav"><ul class="nav-list">
<li><a href="detail.html"><span>首页</span></a></li>
<li><a href="detail.html"><span>玄幻</span></a></li>
<li><a href="detail.html"><span>修仙</span></a></li></ul></div>
<div class="search"><form action="search.html" method="get" target="_blank">
<input name="kw" placeholder="搜索书名" type="text" maxlength="10" />
<input id="search-submit-btn" type="submit"/>
<label for="search-submit-btn"><i class="iconfont icon-search"></i></label>
</form></div>
</div></div>
</header>
<!--===== Begin Main =====-->
<section class="main"><div class="main-wrap wrap1000"><div class="hot-section"><div class="hot-content">
<div class="hot-shadow"><div class="hot-title">最热</div></div>
<div class="banner"> <!-- 1、banner -->
<ul class="banner-imgs"> <!--static/img文件夹下放了几张图片,就写几个li标签-->
<li><a href="detail.html"><img src=" {% static 'img/1.jpg' %}"/></a></li>
</ul>
<div class="control-page">
<a class="iconfont icon-bannerzuo" href=";"></a>
<a class="iconfont icon-banneryou" href=";"></a>
</div>
</div>
<div class="hot-recommend"><ul class="hot-list"> <!-- 2、hot -->
{% for novel in novelsHot %}
<li><a href="detail.html"><div><img src=" {{ novel.novelimg }}"/></div>
<p> {{novel.novelname}}<span class="author"> {{novel.author}} 著</span>
<span class="book-description">
<!-- |safe把空格、换行等标点转为正常字符; |chuncatechars:'数字',把超出的字数以仨点替之-->
{{ novel.description |safe|truncatechars:'90' }}
</span></p></a></li>
{% endfor %}</ul></div>
<div class="xuanhuan"> <!-- 3、Xuanhuan -->
<div class="xuanhuan-title">
<span>玄幻</span><p class="txt">Fantasy</p><p>Novel</p>
<span class="more"><a href="more.html">更多>></a></span>
</div>
<div class="wrap890 xuanhuan-wrap"><ul class="book-list">
{% for novel in novelsXH %}
<li class="book"><div class="book-wrap">
<a class="cover" href="detail.html"><img src=" {{ novel.novelimg }}" width="136" height="180" /></a>
<div class="book-presentation"><h2><a href="detail.html"> {{ novel.novelname }}</a></h2>
<p class="book-info"><span> {{ novel.sort }}</span><span> {{ novel.state }}</span></p>
<p class="book-author"><a href=";">作者:<span> {{ novel.author }}</span></a></p>
<p class="desc"> {{ novel.description |safe|truncatechars:'90' }}</p>
</div></div></li>
{% endfor %}</ul></div>
</div>
<!-- 4、WuXia 仿照第3条的玄幻-->
</div></div></div></section> <!--=====End Main=====-->
<footer class="footer"> <!--=====Begin Footer=====-->
<div class="wrap1000 footer-wrap">
<div class="logo-footer"><a href="detail.html">
<img src=" {% static 'img/footer_logo.png' %}" alt="" width="50"/>
<span class="footer-txt">潭州教育Python学院</span></a>
<span class="footer-font">TAN ZHOU PYTHON COLLEGE</span></div>
<div class="copy-right"><p>本站仅供技术学习使用,勿用商业</p>
<p>Copyright © 2017 All Rights Reserved 潭州PYTHON</p></div>
</div></footer> <!--=====End Footer=====-->
<script src=" {% static 'js/index.js' %}"></script> <!-- Main Plugin -->
</body></html>