Django基础

Mi0发布

启动Django和了解它的文件组成

最先也没有接触过Django,所以从0开始了解下最最基础的部分

首先安装Django之后会有个控制命令

django-admin

1564987532197

可以通过该命令来创建Django项目

django-admin startproject Django2

1564987732449

可以看到在Django2下生成了一个文件manange.py和一个目录Django2\Django2,目录下有几个python文件

manage.py是一个管理项目的文件(工具人),可以控制项目

Django2\Django2目录下

__init__.py: 一个空文件,告诉 Python 该目录是一个 Python 包。

settings.py:该 Django 项目的设置/配置,它会涉及到数据库的连接配置,视图模板的路径配置。

urls.py:该文件是web路由的配置

wsgi.py:该文件是一个 WSGI 兼容的 Web 服务器的入口,可以理解为,可以靠他不用python来启动服务,要靠Nginx来启动服务的话,就要使用到这个文件

启动命令就可以借助刚刚的manage.py文件了

python manage.py runserver 0.0.0.0:8000

1564988574418

不同版本界面不一样的,2.1版本貌似是一个小飞机,这里是1.11.20

项目第一次启动后,在目录下就会生成一个db.sqlite3的数据库文件

1564988977286

视图的使用

要把视图显示出来,首先在/Django1/Django1下随便创个文件,写下面的内容

# sijidou.py

from django.http import HttpResponse

def hello(request):
    return HttpResponse("hello sijidou")

接下来对urls.py进行配置,把刚刚的文件import进来, 填加个url(r'hello/', sijidou.hello)路由

#urls.py

from django.conf.urls import url
from django.contrib import admin

from . import sijidou

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'hello/',sijidou.hello),
]

在Django的2.0版本,使用的path()来替换的url(),也就是

from django.urls import path

from . import sijidou

urlpatterns = [
    path('hello/', sijidou.hello),
]

在Django,按照MVC的思想,视图文件在主目录下放置templates目录,把视图文件放在里面

而python的视图文件就是模板注入的亚子

<!--Django2/templates/hello.html-->

<h3>{{ hello }}</h3>

在setting.py文件中添加templates目录的路径

1564993427392

接下来修改下之前的sijidou.py,让他使用注入的方式传入模板,注意引入的包和之前不同

#Django2/Django2/sijidou.py

from django.shortcuts import render

def hello(request):
    context = {}
    context['hello'] = 'Hello sijidou'
    return render(request, 'hello.html', context)

对于Django的模板,可以理解成类似于java的jsp文件一样,虽然Django模板是.html结尾,但是具有一定的语法

{% include "1.html" %}        //包含
{# 注释 #}                   //注释

//判断是否相等
{% ifequal var1 var2 %}
    xx
{% endifequal %}

//判断
{% if a > b %}
   xx
{% elif b < a and b == d %}
   xx
{% else %}
   xx
{% endif %}

//循环
{% for i in list %}
    <li>{{ i.value }}</li>
{% endfor %}

模型的使用

模型一般是用来连接数据库之类的

在创建模型的时候需要使用django-admin或者manager.py来创建模型,创建位置在/Django2这个根目录下

django-admin startapp app
python manager.py startapp app

1564998035544

那么问题来了django-admin startappdjango-admin startproject 有什么区别

project相当于一个项目,里面的setting会去连一个数据库

app相当于一个模块,而它会去根据业务的不同通过其中的models.py文件选择连接多个表

一个project可以由多个app,反之不行

生成app后查看下对应的目录文件

1565054900230

两个__init__.py是空的,他们的作用是说明目录是个python模块

migrations目录是用来存在数据库迁移记录的,简单的来说就是把数据库里面的字段映射到Django中,好被Django使用

admin.py是后台管理员

apps.py是这个模型的入口

models.py里面有多个模型类,每个模型类用来连接表的

tests.py是测试文件

views.py是对请求的处理

创建app后要使project找到app不是放在project项目下的目录就可以的,需要在setting.py中加上一行(我这里叫生成的目录叫app,所以加的路径就是app

1565056099156

这个INSETALLED_APPS也可以添加成app.apps.AppConfig这个路径,也就是app目录下的apps.py文件的AppConfig()函数

撰写models.py,Django在发出迁移命令后,会根据这个配置文件进行对相应数据库的修改

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
class user(models.Model):
    username = models.CharField(max_length=20)
    age = models.IntegerField()

这里将记录下mysql的连接和Postgresql的连接

mysql

对于mysql来说先在setting.py文件中配置如下信息

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  
        'NAME': 'django',                       #数据库名
        'USER': 'root',                         #数据库账号
        'PASSWORD': 'root',                     #数据库密码
        'HOST':'localhost',                     #数据库地址
        'PORT':'3306',                          #数据库端口
    }
}

在之前我们不需要准备数据库的表和字段

改之前可以看到,它用的是之前自动创建的db.sqlite3这个数据库(这也就是为什么运行第一次会出现一个.sqlite3文件原因)

1564996133633

把上面的内容替换成mysql连接信息(有中文,在文件最前面加个 #-*- coding:UTF-8 -*-

1564996242244

接下来运行,这段代码是把setting.py文件中的INSTALLED_APPS列表中的库加入到mysql数据库中

python manage.py migrate

运行后,数据库里面多了很多很多的表

1565057649932

先不管它有什么用,接下来运行下面的命令,它能在

python manage.py makemigrations app

1565058111193

可以看到生成app/migrations/0001_initial.py,下面有user的映射了

之后再次运行migrate,这次带上了app参数,它会依据app\migrations下的文件去更新数据库

python manage.py migrate app

这次会发生什么变化呢,在mysql中的已生成的django_migrations表中,添加了一行数据,并且会出现一个新的表,命名格式为模型名_model中的类名,之后Django进行查询是会去查该表,对比下

运行前(数据库中user表示最先添加,和Django无关)

1565058650745

1565058830839

运行后

1565058624973

1565058843054

我们拿到app_user表,它的字段是根据models.py来创建的,并且自动添加了id 主键,但是内容为空,之后可以就是写文件进行数据库查询显示了,在\Django2\Django2(project目录)下创建个showdb.py的文件

我先手动添加信息

1565066672712

postgresql

和mysql连接一样,先修改setting.py配置文件,我数据库密码设置的和账户名一样都是postgres

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',  
        'NAME': 'django',                           #数据库名
        'USER': 'postgres',                         #数据库账号
        'PASSWORD': 'postgres',                     #数据库密码
        'HOST':'localhost',                         #数据库地址
        'PORT':'5432',                              #数据库端口
    }
}

首先发出迁移,将models.py的内容写入到migrations

python manage.py makemigrations

接着讲python的所需要的表的信息,写入到数据库中

python manage.py migrate app

1565079382169

这里如果使用Django来添加数据,可以运行下面代码

#Django2/Django2/showdb.py

# -*- coding: utf-8 -*-

from django.http import HttpResponse

from app.models import user

# 数据库操作
def showdb(request):
    user1 = user(username='mi1', age=20)
    user1.save()
    user2 = user(username='mi0', age=19)
    user2.save()

    return HttpResponse("insert ok")

运行下就添加进去了

1565079717457

back

之后进行查询

#Django2/Django2/showdb.py

# -*- coding: utf-8 -*-

from django.http import HttpResponse

from app.models import user

# 数据库操作
def showdb(request):
    response = ""
    response1 = ""

    l = user.objects.all()
    for var in l:
        response1 += str(var.age) + " " +  str(var.username) + "\n"
    response = response1

    return HttpResponse("<p>" + response + "</p>")

添加一个路由

from django.conf.urls import url
from django.contrib import admin
from . import sijidou
from . import showdb

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^hello/', sijidou.hello),
    url(r'^user/',showdb.showdb),
    ]

能够进行数据库查询了

1565067195089

可以利用过滤器来选择查询的内容

# -*- coding: utf-8 -*-

from django.http import HttpResponse

from app.models import user

# 数据库操作
def showdb(request):
    #response2 = user.objects.filter(id=1)
    response2 = user.objects.get(id=1)
    #res = response2[0].username
    res = response2.username
    return HttpResponse("<p>" + res + "</p>")

getfilter的区别在于,filter返回的是一个列表,而get返回的是一个对象值

修改数据库

# -*- coding: utf-8 -*-

from django.http import HttpResponse

from app.models import user

# 数据库操作
def showdb(request):
    response2 = user.objects.get(id=1)
    response2.username = 'sijidou'
    response2.save()

    response3 = user.objects.get(id=1)
    res = response3.username

    return HttpResponse("<p>" + res + "</p>")

删除数据

# -*- coding: utf-8 -*-

from django.http import HttpResponse

from app.models import user

# 数据库操作
def showdb(request):
    response2 = user.objects.get(id=1)
    response2.delete()

    return HttpResponse("<p>delete ok</p>")

表单的接收

Django2\Django2目录下新建一个show.py

from django.http import HttpResponse
from django.shortcuts import render_to_response

def info_form(request):
    return render_to_response("form.html")

def info(request):
    a = request.GET['a']
    return HttpResponse(a)

info_form()是显示表单输入的页面

info是显示提交后的显示页面

修改下路由

from django.conf.urls import url
from django.contrib import admin
from . import sijidou
from . import showdb
from . import show

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^hello/', sijidou.hello),
    url(r'^user/',showdb.showdb),
    url(r'^show_form/', show.info_form),
    url(r'^show', show.info),
    ]

模板文件写一下Django2\templates\form.html

<html>

<head>
    <meta charset="UTF-8">
</head>

<form action="/show" method="GET">
    <input type="text" value="" name="a" />
    <input type="submit" value="submit" name="submit" />
</form>

</html>

之后就能收到GET请求了

1565084485947

如果是post请求,和get请求稍微有所不同在于,html视图文件需要价格crsf_token的,这里要引入csrf的。

这里的对token的检查控制流程是这样的

加入token一定要用render()request包含进去,没有这一步就在页面中就没有token

只要有token,发送请求,在接收到request的时候就会检验,检查通过后,之后的返回值和处理如何就不会受影响

from django.http import HttpResponse
from django.shortcuts import render_to_response,render
from django.views.decorators import csrf

def info_form(request):
    return render(request,"form.html")

def info(request):
    text = {}
    text['back'] = request.POST['a']

    return HttpResponse(text['back'])

form.html下加入token的模板

<html>

<head>
    <meta charset="UTF-8">
</head>

<form action="" method="POST">
    <input type="text" value="" name="a" />
    {% csrf_token %}
    <input type="submit" value="submit" name="submit" />
</form>
</html>

1565094377792

cookie和session

cookie的使用

cookie设置有很多参数

HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)  #带盐的

HttpResponse.set_cookie(key, value, max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False) #不带盐的

key:

value:

salt:加盐

max_age:存活时间以秒为单位,为None则在关闭浏览器后失效

expires:过期时间,如果有这个,优先级比max_age高,设置格式Wdy, DD-Mth-YY HH:MM:SS GMT

path:作用的路径

doamin:作用的域

secure:利用https

httponly:只能通过http来解析,js没法用document.cookie获取了

获取cookie也有一整套的流程,参数相同的部分理由和上面一样,反正主要就是key和salt了

HttpRequest.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)    #带盐
HttpRequest.get_cookie(key, default=RAISE_ERROR, max_age=None)  #不带盐

删除cookie,参数相同和设置cookie一样

HttpResponse.delete_cookie(key, path='/', domain=None)

利用刚刚的show.py的demo

先写个加盐的,逻辑如果收到post,则把post的数据存在cookie中,如果不是post请求,则把cookie中的back字段显示出来,并删除掉cookie

from django.http import HttpResponse
from django.shortcuts import render_to_response,render
from django.views.decorators import csrf

def info_form(request):
    return render(request,"form.html")

def info(request):
    text = {}
    if request.POST:
        text['back'] = request.POST['a']
        rep =  HttpResponse(text['back'])
        rep.set_signed_cookie('back', text['back'], 'dddd')
    else:
        text['back'] = request.get_signed_cookie('back','dddd')
        rep = HttpResponse(text['back'])
        rep.delete_cookie('back')

    return rep

1565101156594

再访问次,cookie中的值先被取出来,之后被删除了

1565101236832

当然2次的盐不对就无法从cookie中取出想要的值,反而还会报错

再尝试次不带盐的,可以看到是明文了

from django.http import HttpResponse
from django.shortcuts import render_to_response,render
from django.views.decorators import csrf

def info_form(request):
    return render(request,"form.html")

def info(request):
    text = {}
    if request.POST:
        text['back'] = request.POST['a']
        rep =  HttpResponse(text['back'])
        rep.set_cookie('back', text['back'])
    else:
        text['back'] = request.get_cookie('back')
        rep = HttpResponse(text['back'])
        rep.delete_cookie('back')

    return rep

1565100837840

session的使用

在先前的post表单的demo上进行修改

from django.http import HttpResponse
from django.shortcuts import render_to_response,render
from django.views.decorators import csrf

def info_form(request):
    return render(request,"form.html")

def info(request):
    text = {}
    if request.POST:
        text['back'] = request.POST['a']
        request.session['back'] = text['back']
    else:
        text['back'] = request.session.get('back')
        request.session.flush()

    return HttpResponse(text['back'])

逻辑很清晰,如果收到post,则把post的数据存在session中,如果不是post请求,则把session中的back字段显示出来,并删除掉session

发送post后,cookie中有session字段了

1565098624329

在Django中session是存在数据库的,进入postgresql查看下

select * from django_session;

1565098694566

把这串base64进行解码

1565098737885

前面是不知道是啥的字符串,后面就是刚刚传的键值对

接着刚刚的逻辑,这次使用get请求直接访问/show,能够从session中取出数据,并且session已经消失

1565099085938

admin后台管理

django有可视化的后台管理服务,只需要启动它即可,不需要太多的编码,之前使用数据库迁移的时候会生成很多库

1565141696399

其中以auth开头的表都是用来为后台管理提供数据的,至于如何添加进来,在INSTALLED_APPS下就有声明

之后再url.py中开启路由和导入包即可访问后台了

1565141918271

1565141975539

但是此时没有账号,就没法登陆,需要通过manage.py来创建个账号

python manage.py createsuperuser

1565142681028

创建成功后进去,只能管理管理员的数据库的表,为了管理更多的表,需要进行添加关系到Django的模型下的admin.py中,这里我把之前的app_user表添加进去

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from models import user

# Register your models here.
admin.site.register(user)

之后再访问管理员页面,就有添加的表了

1565143195756

只让他显示修改username的话需要进行以下修改,需要继承admin.ModelAdmin,之后在fields属性中设置需要显示的字段(这里要用list对象),最后把类和模型中的类对应起来注册

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from models import user

# Register your models here.
class ContactAdmin(admin.ModelAdmin):
    fields = ('username',)

admin.site.register(user, ContactAdmin)

改变前

1565143718122

改变后

1565143739378

列表显示中,可以设置需要哪些列表被显示出来,列表所对应的是list_display属性

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from models import user

# Register your models here.
class ContactAdmin(admin.ModelAdmin):
    fields = ('username',)
    list_display = ('username', 'age')

admin.site.register(user, ContactAdmin)

添加前,是这样的

1565143829884

添加后

1565144163028

也可以添加搜索框,只需要设置search_fields属性

# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.contrib import admin
from models import user

# Register your models here.
class ContactAdmin(admin.ModelAdmin):
    fields = ('username',)
    list_display = ('username', 'age')
    search_fields = ('username',)

admin.site.register(user, ContactAdmin)

添加后就可以以username字段来查询了

1565144354195

参考链接:

https://www.runoob.com/django/django-form.html

https://docs.djangoproject.com/zh-hans/2.2/

https://blog.csdn.net/liubingger/article/details/80968066

https://blog.csdn.net/chen1042246612/article/details/84327046

分类: web安全

0 条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注