2018-04-28

django初级应用

一.实现在浏览器中输入内容,跳转拓展页面继续输入下一个内容, 然后提交到数据库,再从数据库中获得数据显示在浏览器中

1)配置:
Django初始化.png

添加app='stu',修改路由

(?P<stu_id>):
(?P<name>...) 子串匹配到的内容将可以用命名的name来提取url中的值。组的name必须是有效的python标识符,而且在本表达式内不重名。

工程路由,添加路由stu:
image.png

app路由,添加路由addstu:
image.png

2)models.py创建数据表

db_table 用来给表命名

from django.db import models

# Create your models here.


class Student(models.Model):

    s_name = models.CharField(max_length=10)
    s_tel = models.CharField(max_length=11)


    class Meta:
        db_table = 'day51_student'


class StudentInfo(models.Model):
    i_addr = models.CharField(max_length=30)
    s = models.OneToOneField(Student)

    class Meta:
        db_table = 'day51_stuedentinfo'

3) templates书写addStu.html

实现浏览器的输入,提交
form表单中写入路径action, 提交方法method;提交按钮的type类型为submit

<form action="" method="POST">
    <table>
        <tr>
            <th>姓名</th>
            <th>电话</th>
        </tr>
        <tr>
            <td>
                <input type="text" name="name">
            </td>
            <td>
                <input type="text" name="tel">
            </td>
        </tr>
        <tr>
            <td>
                <input type="submit" value="提交">
            </td>
        </tr>
    </table>
</form>

4)views.py写addStu方法

request.method :请求的方法;
GET:获得请求, POST:提交请求

敲黑板: reverse函数在pycharm中不能直接使用alt + enter导入,需要手动导入:from django.core.urlresolvers import reverse,用来实现跳转到指定页面

render与redict区别:
HttpResponseRediect函数:return rediect('/login.html/'):执行的的是url里面的函数,相当于又一次调用新的函数,/login.html/函数里面的所有代码都会执行,并且路径也会改变,用户再次刷新的时候不会改变
render:return render(request,'addStu.html'):只是跳到login.html这个页面上去,没有别的任何操作,和url里的调用都不执行,并且路径还是原来的路径,
当用户再次刷新时,会会重新回到原来路径下的页面

from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.core.urlresolvers import reverse
# Create your views here.
from stu.models import Student, StudentInfo

def addStu(request):

    if request.method == 'GET':
        return render(request, 'addStu.html') #跳转到addStu.html页面中

    if request.method == 'POST':
        # 跳转到学习详情页面
        name = request.POST.get('name')#获得POST请求携带的内容,数据存在form date中
        tel = request.POST.get('tel')
# 在数据库中创建相应数据
        stu = Student.objects.create(
            s_name=name,
            s_tel=tel
        )
# 跳转到下一个页面
        return HttpResponseRedirect(
# 路径别名's:red', 传入可变的参数字典 kwargs = {'stu_id':stu.id}
# 因为路径是可变的,所以需要使用别名
# stu.id 为数据中创建数据的id
            reverse('s:red', kwargs={'stu_id': stu.id})
        )

5)学生拓展表studentinfo,书写addStudentInfo方法

# 传入网址上提取到的url(stu_id)变量
def addStuInfo(request, stu_id):

    if request.method == 'GET':
        # GET请求,跳转到指定的html页面
        return render(request, 'addStuInfo.html', {'stu_id': stu_id})

    if request.method == 'POST':
        stu_id = request.POST.get('stu_id')
        addr = request.POST.get('addr')

        StudentInfo.objects.create(i_addr=addr, s_id=stu_id)
        # 提交完毕后返回首页
        return HttpResponseRedirect('/stu/index/')

6)书写studentinfo.html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="POST">
    <input type="hidden" value="{{ stu_id }}" name="stu_id">
    地址:<input type="text" name="addr">
    <input type="submit" value="提交">
</form>
</body>
</html>

7)定义首页index.html

</head>
<body>
{% for stuinfo in stuinfos %}
{# 第一次首页的时候, 数据库中没有数据, 添加完毕后, 数据中则有数据,从数据库中取出相应的数据#}
    姓名: {{ stuinfo.s.s_name }}
    电话: {{ stuinfo.s.s_tel }}
    地址: {{ stuinfo.i_addr }}
{% endfor %}

<h4>--------------------------------------</h4>
<a href="{% url 's:add' %}">添加学生</a>
</body>
</html>

二. 实现浏览器登入登出,cookie的使用

登入:查询数据库有没有改用户,没有的话就跳转到注册regist页面,有就进入login页面, 再次刷新的时候需要重新登录
登出: 注册掉数据库相关数据

1)准备:采用第一个项目里的template数据,新建app:uauth

工程urls:python url(r'^uauth/', include('uauth.urls'))
app urls:

image.png

2)创建对应的数据库表

ticket 随浏览器走

from django.db import models

# Create your models here.

class Users(models.Model):
    u_name = models.CharField(max_length=10)
    u_password = models.CharField(max_length=255)
    u_ticket = models.CharField(max_length=30, null=True)


    class Meta:
        db_table = 'day51_user'

3)书写regist, login , logout相应方法

  • regist

密码加密:make_password()
密码解密:check_password()

from django.contrib.auth.hashers import make_password,check_password
from django.http import HttpResponseRedirect, HttpResponse
from django.shortcuts import render
from django.core.urlresolvers import reverse
# Create your views here.
from uauth.models import Users


def regist(request):
    if request.method == 'GET':
        return render(request, 'register.html')

    if request.method == 'POST':
        # 注册
        name = request.POST.get('name')
        password = request.POST.get('password')

        password = make_password(password)

        Users.objects.create(u_name=name,u_password=password)

        return HttpResponseRedirect('/uauth/login/')
  • login

拓展 Httpresponse.set_cookie
HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)

  • 设置一个Cookie。参数与Python 标准库中的 Morsel Cookie 对象相同。
    key:键名,字符串形式。
  • value:对应的值,字符串形式。
  • max_age:cookie 过期的相对时间,单位是秒。如果为None,则当浏览器关闭的时候过期。如果设置了 max_age 而没有设置 expires,则 expires 将根据 max_age 的值计算出来。
  • expires:设置 cookie 过期的绝对时间。应该是一个 UTC "Wdy, DD-Mon-YY HH:MM:SS GMT" 格式的字符串,或者一个 datetime.datetime 对象。如果 expires 是一个datetime 对象,则 max_age 会通过计算得到。
  • path:一个字符串,表示客户端回送 cookie 的路径,如果为‘/’,则表示该域名下的所以路径都将回送 cookie,如果是‘/blog/’;则在访问‘/blog/abc’或者‘/blog/def’等,所有包含该前缀的路径时,客户端都会回送 cookie。
  • domain:cookie有效的域。例如,其值为‘.scolia.com’时,那么在访问 www.scolia.com 或者 test.scolia.com 之类的时,都会回送 cookie ,当然通常会和 path 配合在一起使用。根据 HTTP 协议的要求,这个值必要要两到三个句点,从而防止出现 ‘.com’、‘.edu’、‘va.us’等形式的域名。当域为高层域时,只要两个句点就可以了,而高层域包括:.com、.edu、.net、.org、.gov、.mil、.int、.biz、.info、.name、 .museum、.coop、.aero、和.pro。其他的域则需要至少三个。
  • secure:当其为 True 时,表示只要在 https 连接的情况下才会回送cookie
    httponly:当其为 True 时,JavaScript 等就不能访问对应的cookie了。当然这个标记并不是cookie标准中的,但目前市面上常用的浏览器都支持。灵活使用可以提供数据的安全性。
    注意:
  • RFC 2109 和RFC 6265 都声明客户端至少应该支持 4096 个字节的Cookie。对于许多浏览器,这也是最大的大小。如果视图存储大于 4096 个字节的 Cookie,Django 不会引发异常,但是浏览器将不能正确设置 Cookie。
def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    if request.method == 'POST':
        # 如果登录成功,绑定参数到cookie中,set_cookie
        name = request.POST.get('name')
        password = request.POST.get('password')

        if Users.objects.filter(u_name=name).exists():
            user = Users.objects.get(u_name=name)
            if check_password(password, user.u_password):
                ticket = 'agdoajbfjad'
                # 绑定令牌到cookie里面
                response = HttpResponse()
#response返回的是<HttpResponse status_code=200, "text/html; charset=utf-8">
                response.set_cookie('ticket', ticket)
                # 存在服务端
                user.u_ticket = ticket
                user.save()
                return response
            else:
                return HttpResponse('用户密码错误')
        else:
            return HttpResponse('用户不存在')
  • logout

删除cookie
HttpResponse.delete_cookie(key, path='/', domain=None)
cookie中删除指定的 key 及其对应的 value。如果 key 不存在则什么也不发生,也就是不会引发异常。
  由于 Cookie 的工作方式,path 和 domain 应该与 set_cookie() 中使用的值相同 —— 否则 Cookie 不会删掉。

def logout(request):
    if request.method == 'GET':
        response = HttpResponse()
        response.delete_cookie('ticket')
        return HttpResponseRedirect('/uauth/login/')

4)书写相应的html文件

  • register注册
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注册页面</title>
</head>
<body>
<form action="" method="POST">
    注册姓名:<input type="text" name="name">
    注册密码:<input type="password" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>
  • login 登录
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录页面</title>
</head>
<body>
<form action="" method="POST">
    登录姓名:<input type="text" name="name">
    登录密码:<input type="password" name="password">
    <input type="submit" value="提交">
</form>
</body>
</html>

5)书写首页index.html

实现登陆后跳转到指定页面,没登录跳转到登录页面

def index(request):

    if request.method == 'GET':
        # 获取所有学生信息
        ticket = request.COOKIES.get('ticket')
        if not ticket:
            return HttpResponseRedirect('/uauth/login/')
        if Users.objects.filter(u_ticket=ticket).exists():
            stuinfos = StudentInfo.objects.all()
            return render(request, 'index.html', {'stuinfos': stuinfos})
        else:
            return HttpResponseRedirect('/uauth/login/')

三.零碎的小规模验证应用

1.404 和 500 异常处理

404:主要是代码的错误,导致不能正常打开页面
500:主要是url输入的错误,导致服务出现问题,不能正常打开页面
1)在对应的app中编写错误处理方法

#404
def page_not_found(request):
    return render(request, '404.html')

#500
def server_error(request):
    return render(request, '500.html')

2)书写相应的html文件

404

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>这里是400,400</h1>
</body>
</html>

500

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>500错误页面</title>
</head>
<body>
<h1>这里是500, 500</h1>
</body>
</html>

3)在工程目录下urls导入写入的模块,赋值到相应的错误处理模块上

from stu.views import page_not_found, server_error
handler404 = page_not_found
handler500 = server_error

2.挖坑与填坑

在html文件中,实现内容的重复利用

  • 挖坑:base.html (标题title ---- 内容body)
    方法:{% block title %} {% endblock %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>
        {% block title %} {% endblock %}
    </title>
</head>
<body>
    {% block contains %} {% endblock %}
</body>
</html>
  • 填坑 grade.html
>引用的是base.html中的内容,将grade填掉的内容加入到base中挖掉的内容中
{% extends 'base.html' %}
{% block title %}
    班级列表
{% endblock %}


{% block contains %}
    {% for g in gs %}
        班级ID:{{ g.id }}
        <a href="/s/allstu/{{ g.id }}">
{#        <a href="{% url 's:alls' g.id %} ">#}
            班级名称:{{ g.g_name }}
        </a>
    {% endfor %}
{% endblock %}

3.数据库表的更新与删除(update, delete)

  • 更新
    方法:1-需要手动保存
def upStu(request):
    stu_id = request.GET.get('stu_id')
    stu = Student.objects.get(id=stu_id)
    stu.s_name = '修改的名字'
    stu.save()

方法2:自动保存

def upStu(request):
    stu_id = request.GET.get('stu_id')
    Student.objects.filter(id=stu_id).update(s_name='黄蓉')
    return HttpResponseRedirect('/g/allgrade/')
  • 删除
def delStu(request):

    stu_id = request.GET.get('stu_id')
    Student.objects.filter(id=stu_id).delete()
    return HttpResponseRedirect('/g/allgrade/')

4.关联关系

OnetoOneField:一对一关系
ForeignKey: 一对多关系
ManytoMany: 多对多关系

django目录结构图如下

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容