史高治

新随笔 联系 管理
有ip无路由是404,ip也无是无法访问此网站。url中?前的是路由,?后是GET请求的各组参数。
 
子项目和子应用下的两类urls.py:[]内的各个路由函数url,其首参网址的开头无/,结尾有/。
views中的各函数、templates下的xxx.html,所出现的各相对路径:项目的根目录(即与manage.py同级的文件夹或文件)开头不加/,次级目录开头要加/;url若拼接ip则开头加/,拼接所在函数所响应的路由则开头不加/。
 
settings.py底的STATIC_URL = '/static/',前后都有/:
①开头有/:static文件夹在子应用下而非总项目的根下;拼接的是ip②结尾有/:尾部要接受css等子文件(夹)的拼接。
 
设计个有远见的数据库=项目完成了一半=几千行代码。既让当前的代码活事半功倍,又减少日后修修补补的次数和面积。数据库的架构是机密,竞争对手看到后,或能山寨出相似的项目。

引入markdown:
www.zhidaow.com/post/django-custom-template-tag-markdown。
**************************分割线**************************
三大web框架的请求:
请求的参数为input标签(type为text,password,checkbox等)的name属性,返回为value属性的值。
 
tornado用方法self.get_argument('name值'),另俩用{}:request.xx['name']或request.xx.get('name')。
 
①tornado:get和post都是self.get_argument('name属性的值',default=None)。
②flask:get请求用request.args['name'],post用request.form['name']。
③django:request.GET['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项目后,启动项目是按绿方块dj+根目录(如本例的movie)右侧的绿三角,而非我习惯的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',    #潭州学院一远程数据库的名字
    }
}
 
sessions禁用:注释此行'django.contrib.sessions.middleware.SessionMiddleware',
 
sessions的3种存储方式:
SESSION_ENGINE='django.contrib.sessions.backends.db'    #默认存在数据库
SESSION_ENGINE='django.contrib.sessions.backends.cache'    #存在缓存
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'    #优先缓存,次选库
***************分割线***************
路由文件urls.py:
url的2参有两种写法:url('正则',views.视图函数名)、大型的url('正则',include('应用名.urls'))。
 
from django.conf.urls import url,include
from django.contrib import admin
from dy import views
 
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^$',views.index),  #首页是^$;2参是视图函数名,而非补个()的返回值
    url(r'^cy/',views.chengy,name='xm'),    #给路由起个别名,方便视图调用
    url(r'^cy/', include('dy.urls')),   #使dy下urls.py内的各url的首参,拼接ip/cy/,而非ip/
    url(r'^cy(x)/(y)/',views.info),   #def info(request,n,m):,x,y的值按位置传参给n,m
    url(r'^cy(?P<id>\w+)/',views.stu),   #def stu(request,id):,\w+的值按参数名传给id
]
**************************分割线**************************
③应用文件夹dy:
 
路由文件urls.py:本例的网址少,不必牛刀杀鸡建此文件,只是举个例子
 
from django.conf.urls import url
from dy import views
 
urlpatterns = [
    url(r'^$',views.indexDY),
    url(r'^666/',views.留空),
]
***************分割线***************
和数据库交互(俗称ORM:Object Relational Mapping)的models.py:
 
在E:\movie路径下进入cmd:python manage.py inspectdb > dy/models.py
执行后settings中所配数据库movie中的各表,以class的形式(表名删_,首字母大写)自动写入dy/models.py。
 
各类字段:
参数null默认False不许为空,参数unique若设为True则该字段列无重复。
自增主键models.AutoField(primary_key=True),布尔BooleanField,整数IntegerField,浮点数FloatField,指定总位数和小数位数的models.DecimalField(max_digits=7, decimal_places=3)。
字串字段,限制字数的短文本用models.CharField(max_length=9),一般超4000字符的大文本用TextField。
时间字段DateField或TimeField或DateTimeField,加参数auto_now=True则各行记录的该字段时间值为最后1次修改的,auto_now_add=True则为固定的创建时间。
外键字段classID=models.ForeignKey('类名如Classes'),在Classes-Students(两张数据表classes和students)的Students类一方定义。
 
Egの外键使用,html中遍历各个班里的学生:
{% for stu in students %}
    {{ stu.studentName }}∈{{ stu.classID.className }}
{% endfor %}
<br><hr><br>    //空行br、横线hr、无序列表ul
{% for c in classes %}
    班级{{ c.className }}有以下学生:
    <ul>
        {% for stu in c.students_set.all %}    //班级外键.学生表名后加_set.all,.py内all后有()
            <li>{{ stu.studentName }}</li>
        {% endfor %}
    </ul>
{% endfor %}
***************分割线***************
各路由网址呈现什么内容的文件views.py:
 
from django.shortcuts import render  #return render(request,'index.html',context=context)
from django.shortcuts import redirect    #return redirect('/login/')
from django.http import HttpResponse    #return HttpResponse('<h1>hello,world</h1>')
from django.http import JsonResponse    #return JsonResponse({'x':'hello','y':'world'})
from dy.models import DyDy    #导入movie库中电影数据源所在的那张表
 
def chengy(request):
    #.get()取键值,若无不报错;多个name为x(如type="checkbox"的各标签),则用.getlist('x')
    words=request.POST.get('keywords')
 
    #视图中session的使用:
    request.session.get('a','')    #获取session中session_key为a的session_data
    request.session['a']=1  #设置键a的值
    request.session.set_expiry(600)  #过期单位秒,默认2周,0在关浏览器时,None永不过期
    del request.session['a']    #删除session中的键a
    request.session.clear()    #各session_key的session_data置为''
    request.session.flush()    #删除session
 
    #请求的:request.COOKIES、参数获取.GET及.POST、方式.method、编码.encoding
    response=HttpResponse(f'请求的路径:{request.path}')
    response.set_cookie('name','jack',expires=60*60*24)  #设置coocie的键、值、有效期24h
    return response
 
def index(request):
    kw=request.POST.get('kw')
    if kw:
        #增=DyDy();增.title='2012';增.link='http://…';增.save()
        #DyDy.objects.all().order_by('-title')[:50].delete()    #按title降序后,删前50行记录
        #改=DyDy.objects.get(id=1);改.title='乱';改.save()  #改这条记录(若无则抛出异常)的title
        查=DyDy.objects.filter(title__icontains=kw)[:9]   #标题含关键词的前9条,若无则返回空[]
    context={'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">世界你好</span></a>
      <span class="footer-font">TAN ZHOU PYTHON COLLEGE</span></div>
    <div class="copy-right"><p>本站仅供技术学习使用,勿用商业</p>
      <p>Copyright © 2017 All Rights Reserved 世界你好</p></div>
    </div></footer> <!--=====End Footer=====-->
<script src="{% static 'js/index.js' %}"></script>  <!-- Main Plugin -->
 
</body></html>
posted on 2017-10-19 17:54  史高治  阅读(168)  评论(0编辑  收藏  举报