zoukankan      html  css  js  c++  java
  • Django基础

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

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

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

    django-admin
    

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

    django-admin startproject Django2
    

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

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

    Django2Django2目录下

    __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
    

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

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

    视图的使用

    要把视图显示出来,首先在/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目录的路径

    接下来修改下之前的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
    

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

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

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

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

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

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

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

    admin.py是后台管理员

    apps.py是这个模型的入口

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

    tests.py是测试文件

    views.py是对请求的处理

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

    这个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文件原因)

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

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

    python manage.py migrate
    

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

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

    python manage.py makemigrations app
    

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

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

    python manage.py migrate app
    

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

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

    运行后

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

    我先手动添加信息

    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
    

    这里如果使用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")
    

    运行下就添加进去了

    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) + "
    "
        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),
        ]
    

    能够进行数据库查询了

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

    # -*- 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>")
    

    表单的接收

    Django2Django2目录下新建一个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 emplatesform.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请求了

    如果是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>
    

    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
    
    

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

    当然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
    

    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字段了

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

    select * from django_session;
    

    把这串base64进行解码

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

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

    admin后台管理

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

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

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

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

    python manage.py createsuperuser
    

    创建成功后进去,只能管理管理员的数据库的表,为了管理更多的表,需要进行添加关系到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)
    

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

    只让他显示修改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)
    

    改变前

    改变后

    列表显示中,可以设置需要哪些列表被显示出来,列表所对应的是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)
    

    添加前,是这样的

    添加后

    也可以添加搜索框,只需要设置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字段来查询了

    参考链接:

    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

  • 相关阅读:
    vuex 入门
    Vuex 原理
    java web开发问题集合
    JSP Servlet 路径解析 路径设置
    随笔——学习的一些步骤及注意点(不断更新)
    常用正则表达式大全!(例如:匹配中文、匹配html)
    myeclipse+tomcat 工程名改名的问题 ——————完美解决方案
    web开发的步骤
    Servlet中的GET和POST之间的区别
    html、css、javascript、JSP 、xml学习顺序应该是怎样的呢?
  • 原文地址:https://www.cnblogs.com/sijidou/p/13121249.html
Copyright © 2011-2022 走看看