Django入门

Django入门

链接

官方文档Django 文档 | Django 文档 | Django (djangoproject.com)

整合 Django + Vue.js 框架快速搭建web项目 - 云+社区 - 腾讯云 (tencent.com)

HTTP协议web开发知识点 - cls超 - 博客园 (cnblogs.com)

基础

  • Django采用MTV框架模式,M代表模型model、T代表模板template、V代表视图view。model数据存储层,template表现层,view业务逻辑层。

  • WSGI:web server gateway interface 服务器网关接口,是为python定义的web服务器和web应用程序或web框架之间的一种简单而通用的接口协议。WSGI有2部分,服务端和客户端,WSGI是一种通信规范,没有实现过程,实现服务器和web应用框架的通信传输的是服务端。实际网站架构有二级架构和三级架构,二级架构直接使用WSGI自身的服务端作为web服务器,仅适用于开发阶段;三级架构则将服务器作为中间件,实现web服务器和web应用架构的通信,适用于上线阶段。

  • 创建项目

    django-admin startproject myDjango 	#创建django项目
    python manage.py statrapp index		#创建应用index
    python manage.py runserver 8001		#运行项目,默认端口号8000,此时用8001运行
    
  • 文件结构

    --myDjango
    	--index
        	--migrations	#生成数据迁移文件,通过数据迁移文件可以自动在数据库中生成数据表
            __init__.py		#初始化文件
            admin.py		#设置后台管理功能
            apps.py			#当前app的配置信息
            models.py		#定义数据库映射类,每个类关联一张数据表
            tests.py		#自动化测试模块,用于单元测试
            views.py		#视图文件,处理业务逻辑
    	--myDjango
    		__init__.py # 初始化文件,一般无需修改
    		asgi.py		# 启动异步通信功能,在线聊天需要
    		settings.py	# 配置文件
    		urls.py		# 路由设置
    		wsgi.py		# 服务器网关接口,用于项目在服务器上部署和上线
        manage.py		# 命令行工具,python manage.py help可以查看指令信息
    
  • 网站中涉及文件存储和使用,数据库记录文件地址,若将文件以二进制数据格式写入数据库,会降低数据库响应速度。

  • setting.py

    # SECURITY WARNING: keep the secret key used in production secret!
    SECRET_KEY = 'django-insecure-l_+1qz21c-fcihgzjc&vb8!x&l3k)u!*$c12m_)brb8%0b3fz0'
    '''
    密钥配置:随机值SERECT_KEY,用于重要数据加密处理,主要用于用户密码、CSRF机制和会话session等数据加密;
        用户密码:Django内置Auth认证系统,创建用户时将用户密码通过密钥加密处理;
        CSRF机制:用于表单提交,防止窃取网站的用户信息制造恶意请求;
        会话session:存放在cookie中,一串随机的字符串,标识当前访问网站的用户身份;
    '''
    
    # 域名访问权限
    ALLOWED_HOSTS = []
    '''
    DEBUG为True时,ALLOWED_HOSTS列表为空时,只允许localhost或127.0.0.1访问项目;
    DEBUG为False时,ALLOWED_HOSTS为必填项,否则程序无法启动,若要所有域名可以访问,应设置ALLOWED_HOSTS = ['*']
    '''
    
    
    
  • 连接mysql数据库

    • mysqlclient:安装pip install mysqlclient,设置setting.py的DATABASES

      DATABASES={
          'default':{
              'ENGINE':'django.db.backends.mysql',
              'NAME':'babys',
              'USER':'root',
              'PASSWORD':'123456',
              'HOST':'127.0.0.1',
              'PORT':'3306',
          }
      }
      
    • pymysql:安装pip install pymysql,设置__init__.py

      #babys文件夹下的__init__.py
      import pymysql
      pymysql.install_as_MySQLdb
      
    • MySQL8.0以上的版本连接提示django.db.utils.OperationError错误的原因四MySQL8.0版本加密方式时CHA2加密方式,可将加密方式改回原方式,运行SQL语句

      # newpassword是已设置的用户密码
      ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'newpassword';
      FLUSH PRIVILEGES;
      

model

匹配符

__exact		filter(job__exact='开发') 	#精确等于
__contains	filter(job__contains='开发')	#模糊匹配,包含即可'%开发%'
__gt		filter(id__gt=5)			#>
__in		filter(id__in=[1,2,3])		#在列表内
__startswith	filter(job__startswith='开发')	#以。。开头
__endswith		filter(job__endswith='开发')		#以。。结尾
__range			filter(dare__range=(start,end))	#类似between,日期、数字、字符均可
__year		filter(date__year=2018)		#日期字段的year

__iexact、__icontains、__istartswith、__iendswith 忽略大小写的
__gte >=		__lt <		__lte <=
__month		__day		__isnull

查询

#前三条 SQL: select * from table limit 3
v=Table.objects.all()[:3]
返回QuerySet
#or查询,引入Q
v=Table.objects.filter( Q(job='网站设计') | Q(id=4) )
#不等于查询,在Q查询前使用~或使用exclude
v=Table.objects.exclude(job='网站设计')
v=Tbale.objects.filter(~Q(job='网站设计'))
#.count()统计数量
#.distinct()去重
#.order_by('-id')根据id降序排列

values()&values_list()

QuerySet API 参考 | Django 文档 | Django (djangoproject.com)

#某一列 SQL: select job from table

#values()
返回QuerySet,组成为字典形式而不是模型实例	
# This list contains a Blog object.
>>> Blog.objects.filter(name__startswith='Beatles')
<QuerySet [<Blog: Beatles Blog>]>

# This list contains a dictionary.
>>> Blog.objects.filter(name__startswith='Beatles').values()
<QuerySet [{'id': 1, 'name': 'Beatles Blog', 'tagline': 'All the latest Beatles news.'}]>
#values()结果序列化为json格式1)将QuerySet转为list: city_list = list(cities)2)将list序列化为json: city_json = json.dumps(city_list)


# values_list()
>>> Entry.objects.values_list('id', 'headline')
<QuerySet [(1, 'First entry'), ...]>

v=Table.objects.values_list('job')
返回QuetySet,组成为元组形式 
#annotate跨表查询,作用域QuerySet,类似于group by方法,对values值进行分组,若不设置,则对主键分组
v=Table.objects.values('job').annotate(Sum('id'))#结果显示'job'字段和聚合后的sum('id')字段
#aggregate计算某个字段的值并返回计算结果,Sum、Count、Avg、Max、Min、Variance方差、StdDev标准差
v=Table.objects.aggregate(id_cnt=Count('id'))
#对查询结果取并集union、交集intersection、差集difference

多表查询

(7条消息) django中related_name作用_wuliangtianzu的博客-CSDN博客_related_name

# 表Person属性hireDate,表Vocation属性name、job,外键name关联到Person表
# 正向查询
v=Vocation.objects.filter(id=1).first()
	#或 有查询条件,第一个name是Vocation中的字段name,第二个name是Person在的字段name
    v=Vocation.objects.filter(name__name='Tim').first()
v.name.hireDate    #v.name代表外键name

# 反向查询
p=Person.objects.filter(id=2).first()
# 若name没有参数related_name
v=p.vocation_set.first() #vocation_set的返回值为QuerySet
v.job
# 若name设置参数related_name=ps
v=p.ps.first()
v.job
	#或 有查询条件 ps是name的related_name,job是Vocation的字段
    p=Person.objects.filter(ps__job='网站设计').first()
    v=p.person.first() #通过related_name反向获取Vocation模型数据
    v.job
    
# select_related方法
# select Person.name, Vocation.payment from Person left outer join Vocation on name
p=Person.objects.select_related('ps').values('name','ps__payment')
# select_performer方法

执行原生SQL语句

'''extra有6个参数
select:查询字段;where:查询条件;params:若where中有%s,啧params为其提供值;
tables:连接其他表;order_by:排序方式;select_params:为select的%s提供值
'''
Vocation.objects.extra(where=["job=%s"],params=['网站设计'],select={"seat":"%s"},select_params=['seatInfo'])

'''raw有4个参数
raw_query:SQL语句;params:为raw_query的%s提供数值;translations为查询的字段名设置别名;using为数据库对象'''
Vocation.objects.raw('select * from index_vocation')

'''execute无需经过ORM框架,可通过游标执行SQL语句,容易受到SQL注入攻击'''

view

  • 用视图处理HTTP请求,在视图中定义def函数,称为FBV(function base views);以类的形式实现响应与请求处理,称为CBV(class base views)
  • 视图响应式return HttpResponse类,return HttpResonse(html,status=200),其中html变量是相应内容,一般是网页内容或者json数据,网页内容以html语言为主(比如html='<h1>Hello World</h1>'),内容过大时会增加视图函数代码量,因此Django定义了render、render_to_response(2.0版本后被弃用)、redirect函数进行封装;
render(request, template_name, context=None, content_type=None, status=None, using=None)
'''request:浏览器向服务器发送的请求对象;
template_name:渲染模板的文件名,用于生成网页内容;
context:对模板上下文的变量进行赋值,以字典格式表示;(将视图函数的变量传递给模板引擎,再有模板引擎解析这些变量并展示在网页上,变量过多时使用locals()函数取代参数context,会以字典形式返回当前的所以局部变量)'''

template

  • 模板上下文也叫模板变量,{{ variable }}数据由视图函数传递,支持python所有数据类型

    valiable='字符串或者整型数字' <div>{{ variable }}</div>
    valiable={'name':'字典或实例化对象'} <div>{{ variable.name }}</div>
    valiable=['元组或列表'] <div>{{ variable.0 }}</div>  (.索引)
    
  • 标签

    (7条消息) 我的Django学习笔记(2)DTL模型的标签_hide_in_darkness的博客-CSDN博客

    (7条消息) Django自定义标签_CSDN-CSDN博客_django 自定义标签

    自定义模板(template)的标签(tags)和过滤器(filters) | Django 文档 | Django (djangoproject.com)

    {% for %} 支持嵌套,mylist可以是列表、元组或者某个对象
    	{% for item in mylist %}
    		{{ item }}
    	{% endfor %} 循环终止符
    {% if %} 判断条件夫与上下文之间要使用空格分开
    	{% if name=="Lucy" %}
    	{{name}}
    	{% elif name=="Lily" %}
    	{{name}}
    	{% endif %}
    {% url %}
    	生成不带变量的url地址<a href="{% url 'index' %}">首页</a>
    	生成带变量的url地址<a href="{% url 'page' 1 %}">第1页</a>
    	url标签:返回与给定视图和可选参数匹配的绝对路径引用(不带域名的URL)
    	url反转传递关键字参数:
    		{% url '[<appname>:]<urlname>' arg(=value) %}
    	url反转传递查询字符串,在URL外手动添加查询字符串
    		{% url '[<appname>:]<urlname>'}?next=xxx
    	注意:
    		如果反转的URL不存在,NoReverseMatch则会引发异常,这将导致您的网站显示错误页面。
    		如果您想检索一个URL但不显示它,则可以使用一个稍微不同的调用:
    		{% url '[<appname>:]<urlname>' as othername %}
    {% with %}
    	在模版中定义变量 
        {% with var(=value) %} 或:{% with value as var %} 
        注意: 在var(变量名)和value(赋值)中间不需要加空格
    {% load %}导入静态文件标签库{% load staticfiles %}
    {% static %}来自静态文件标签库{% static "css/index.css" %}
    
  • 标签继承

    <!--base.html-->
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8">
            {% block title %}
            <title>首页</title>
            {% endblock %}
        </head>
        <body>
            {% block body %}
            {% endblock %}
        </body>
    </html>
    
    <!--index.html-->
    {% extends "base.html" %}  继承base.html
    {% block body %}  重写body接口
    <a href="{% url 'index:index' }">首页</a>
    {% endblock %}
    
  • 过滤器,过滤器、冒号、参数之间不能有空格,其他可有可无

    自定义模板(template)的标签(tags)和过滤器(filters) | Django 文档 | Django (djangoproject.com)

    {{ variable | filter }}
    {{ value|cut:arg }}从value中删除所有arg的值,比如Value="string with space",arg=" ",结果为"stringwithspace"
    {{ value | floatformat:arg }} 四舍五入,没用arg时保留1位,arg为"2"时保留2位
    {{ value | length }}返回value的长度
    {{ value | random }}从给定的list中返回一个任意的item
    

admin

  • __init__.py项目应用的初始化文件,在文件中设置属性default_app_config指向app.py定义的AppConfig

  • apps.py中定义AppConfig类,通过设置类属性verbose_name用于设置项目应用在admin后台系统的名称

  • admin.py将项目定义的模型注册并绑定到admin后台系统,模型在后台系统显示的名称由模型属性Metaverbose_nameverbose_name_plural设置;在admin.py中用admin.site.register()的方法将模型注册绑定到admin后台系统,但实际开发中不建议此方法,原因是功能扩展性太差,不能满足开发需求;还可以通过类继承的方式实现模型的注册绑定;

  • 自定义ModelAdmin的函数方法

    get_readonly_fields() # 数据只读函数,可以设置不同用户不同的权限
    # 设置字段样式,自定义函数colored_name(),判断相应字段的值,不同字段的color_code颜色值不同,然后返回格式化的代码format_html()
    get_queryset() #数据查询函数,默认全表查询,可自定义设置不同用户不同的查询范围
    formfield_for_choice_field() #下拉框设置函数,只能过滤已经存在的下拉框数据
    formfield_for_dbfield() #下拉框设置,使得在admin中新增数据时实现模型之间的关联
    
        def formfield_for_dbfield(self, db_field, **kwargs):
            if db_field.name == 'types':
                db_field.choices = [(x['seconds'], x['seconds'])
                                    for x in Types.objects.values('seconds')]
            return super().formfield_for_dbfield(db_field, **kwargs)
        
    save_model() #保存函数
    #数据批量处理,下面是批量导出的一个例子
        def get_datas(self, request, queryset):
            temp = []
            for d in queryset:
                t=[d.name,d.types,str(d.discount)]
                temp.append(t)
            f = open('d://data.txt', 'a')
            for t in temp:
                f.write(','.join(t) + '\r\n')
            f.close()
            # 设置提示信息
            self.message_user(request, '数据导出成功!')
        get_datas.short_description = '导出所选数据'	# 设置函数的显示名称
        actions = ['get_datas']	# 添加到“动作”栏
    

部署

部署Django项目有2种主流方案:Nginx+uWSGI+Django和Apache+WSGI+Django;

Nginx和Apache接收浏览器所有http请求并统一管理。静态资源的http请求由Nginx和Apache自己处理,非静态资源的http请求由Nginx和Apache传递给uWSGI服务器,在传递给Django应用,最后Django处理并响应。

  • 上线配置

    DEBUG = False
    ALLOWED_HOSTS = ['*']	# 域名访问权限 
    STATIC_ROOT = (BASE_DIR / 'static')  #static文件夹不存在,由指令 python manage.py collectstatic 创建
    # 项目中存在两个静态文件夹,在不同的DEBUG模式下读取不同文件夹
    
    #在项目的urls.py中添加静态资源路由信息,使得Django知道如何遭到静态资源文件
    # 定义静态资源的路由信息
    re_path('static/(?P<path>.*)', serve, {'document_root': settings.STATIC_ROOT}, name='static')
    

    在windows下用自带的IIS服务器,网上很多教程。

杂项

使用内置User实现注册登录登出
def loginView(request):
    title = '用户登录'
    classContent = 'logins'
    if request.method == 'POST':
        username = request.POST.get('username', '')
        password = request.POST.get('password', '')
        if User.objects.filter(username=username):
            #验证账号密码与模型User的账号密码是否一致
            user = authenticate(username=username, password=password)
            if user:#通过验证后使用内置函数login执行用户登录
                login(request, user)
                return redirect(reverse('shopper:shopper'))#登陆后跳转到个人中心页面
        else:#执行用户注册
            state = '注册成功'
            d = dict(username=username, password=password, is_staff=1, is_active=1)
            user = User.objects.create_user(**d)#向User模型添加新用户
            user.save()
    return render(request, 'login.html', locals())
def logoutView(request):
    logout(request)
    return redirect(reverse('index:index'))
  • format_html()格式化生成html模板

其他

csrf防护
  • Cross-Site Request Forgery,跨网站请求伪造,也称One Click Attack或者Session Riding,常缩写为CSRF或者XSRF,是对网站的恶意利用,窃取网站用户信息制造而已请求。

  • Django默认开启CSRF防护,只适用于post请求,并不防护get请求,因为get请求是以只读的形式访问网站资源,一般情况不破坏和篡改网站数据,在post请求的表单中加入**{% csrf_token %}**

  • Django为防护csrf,在用户提交表单时会自动加入csrfmiddlewaretoken隐藏控件,控件属性的value值由django随机身材,此隐藏控件的值会与网站后台保存的csrfmiddlewaretoken进行匹配,只有匹配成功时才处理网站的表单数据;

    • Django中使用csrf防护功能首先要在settings.py中设置,创建项目时已默认开启MIDDLEWARE中的django.middleware.csrf.CsrfViewMiddleware

    • 取消此功能,在模板文件中删除{% csrf_token %},并在对应的视图函数中添加装饰器@csrf_exempt(没用这一步用户提交表单时程序会由于csrf验证失败而抛出403错误);

    • 要对整个网站取消csrf防护,注释掉中间件CsrfViewMiddleware即可;在整个网站没有csrf防护时相对某些请求设置,需要在模板做添加{% csrf_token %}并在相应的视图函数中添加装饰器@csrf_protect

    • 若网站使用前端的Ajax向Django提交表单数据,则需要设置请求参数csrfmiddlewaretoken,否则会被视为恶意请求。

      <script>
      function submitForm(){
          var csrf = $('input[name="csrfmiddlewaretoken"]').val();
          var user = $('#username').val();
          var password = $('#password').val();
          $.ajax({
              url:'/index.html', 
              type:'POST',
              data:{'user':user,
                    'password':password,
                    'csrfmiddlewaretoken':csrf,
                    success:function(arg){
                        console.log(arg)
                    }
                   }
          })
      }
      </script>
      
session与cookie

session与cookie:浏览器向服务器发送请求,服务器做出响应后,二者便会断开连接,下次用户再来访问服务器时,服务器无法识别此用户身份,导致每次刷新页面都需要重新操作一次用户登录才可以识别用户;session与cookie为了解决http协议无状态的弊端,使浏览器和服务器建立长久联系的会话而出现;

  • cookie存储在客户端,是从浏览器向服务器传递数据,使得服务器能够识别当前用户,而服务器对cookie的识别机制通过session实现;
  • session存储了当前用户的基本信息,存储在服务器端,安全性比cookie高;
  • 当获取用户的session数据时,首先从用户传递cookie里获取sessionid,然后根据sessionid在网站服务器中找到响应的session;
Ajax
  • Ajax即"Asynchronous Javascript And XML",是一种创建交互式、快速动态网页应用的网页开 发技术,无需加载整个网页,能够实现局部更新的技术。Ajax是指向网站的某个路由地址发送http请求并获取响应内容,响应内容经过Javascript处理后渲染在网页上,从而实现网页内容的局部更新,一般情况下响应内容以JSON格式为主。

  • 原生Javascript的Ajax请求

  • jQuery的Ajax请求,jQuery是一个快速、简介的Javascript框架,封装了Javascript常用的功能代码,优化HTML文档操作、事件处理、动画设计和Ajax交互;

    $.ajax{
    	url:"",//请求的url地址
    	dataType:"json",//返回的数据格式
    	async:true,//是否是异步,默认是
    	data:{"id":"value"},//请求参数
    	type:"GET",//请求方式
    	beforeSend:function(){
    		//请求前的处理
    	},
    	success:function(req){
    		//请求成功的处理
    	},
    	complete:function(){
    		//请求完成的处理
    	},
    	error:function(){
    		//请求出错的处理
    	}
    };
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值