django笔记

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: django笔记

注意:一定要使用pycharm专业版

-------------------------------------------------------------------------

django简介:

M 代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。

T 代表模板 (Template):负责如何把页面展示给用户(html)。

V 代表视图(View):   负责业务逻辑,并在适当时候调用Model和Template。

除了以上三层之外,还需要一个URL分发器,它的作用是将一个个URL的页面请求分发给不同的View处理,View再调用相应的Model和Template

-------------------------------------------------------------------------

如何下载:pip install django==2.0.13

-------------------------------------------------------------------------

查看版本:

方法一:python -m django --version

方法二:import django

django.VERSION

-------------------------------------------------------------------------

二:命令创建项目

django-admin.py startproject mysite #创建mysite项目

python manage.py startapp blog #创建项目功能

python manage.py runserver 8080 #启动项目

manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库等。

settings.py-----包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作 的变量。

urls.py ----- 负责把URL模式映射到应用程序。

-------------------------------------------------------------------------

路由分发:如果程序很多的话,记得做路由分发: 在项目下面的urls.py里面

from app1 import views

from django.urls import re_path,include

urlpatterns = [

re_path(r"",include("app1.urls")),

]

-------------------------------------------------------------------------

有名字分组:

urlpatterns = [

re_path(r'^articles/2003/$', views.special_case_2003),

re_path(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),

re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),

re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),

]

-------------------------------------------------------------------------

view试图:

一:

from django.shortcuts import render

def login(request):

name = "wusen"

return render(request,"login.html",locals())

Html:<h1>{{ name }}</h1>

二:

from django.shortcuts import HttpResponse

def login(request):

return HttpResponse("OK")

三:

from django.shortcuts import redirect

def login(request):

return redirect("/url_demo1/")

四:json

from django.http import JsonResponse

def url_demo2(request):

response = {}

response["msg"] = "访问成功"

print(request.POST)

return JsonResponse(response)

也可以自己用import json 效果一样

-------------------------------------------------------------------------

如果想要配置静态文件static必须要在setting配置:

STATIC_URL = '/static/'

# 配置静态文件路径

import os

STATICFILES_DIRS=[

os.path.join(BASE_DIR,"statics")

]

-------------------------------------------------------------------------

最简单的一个Ajax访问:

{% csrf_token %}

<h1 id="ID">{{ name }}</h1>

<script src="/static/js/jquery-3.2.1.min.js"></script>

<script>

$.ajax({

url:"/url_demo2/",

type:"post",

data:{

"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val()

},

success:function (data){

{#$("#ID").text(data.msg)#}

console.log(data)

}

})

</script>

注意:csrf_token与setting有关:

'django.middleware.csrf.CsrfViewMiddleware',

-------------------------------------------------------------------------

区别:html text val

console.log($("#ID").html()) =html代码

console.log($("#ID").text()) =文本值

console.log($("#ID").val()) =value

-------------------------------------------------------------------------

小记一下:queryset前台识别不了,但是django可以哦。

-------------------------------------------------------------------------

反向解析:

path(r"login/",views.login,name="LG"),

{% url "LG" %}

-------------------------------------------------------------------------

reverse反向解析和命名空间还没有整明白?????????

re_path("",include(("app1.urls","a"),namespace="a")),

-------------------------------------------------------------------------

多个参数:正则匹配需要多练习??????

path(r"article/<int:year>/<int:month>",views.article),

# 文章详情页

re_path('^(?P<username>\w+)/articles/(?P<article_id>\d+)$',views.article_detail),

# 个人站点url

re_path('^(?P<username>\w+)/$',views.home_site),

re_path('^(?P<username>\w+)/(?P<condition>tag|category|archive)/(?P<param>.*)/$',views.home_site),

-------------------------------------------------------------------------

post和get请求参数:

get请求: 浏览器直接方位 和 Ajax

post请求: form提交 和 Ajax

print(request.GET)

print(request.POST)

-------------------------------------------------------------------------

request的一些方法:::::::::::::

1.HttpRequest.GET

 一个类似于字典的对象,包含 HTTP GET 的所有参数。详情请参考 QueryDict 对象。

2.HttpRequest.POST

 一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成 QueryDict 对象。

 POST 请求可以带有空的 POST 字典 —— 如果通过 HTTP POST 方法发送一个表单,但是表单中没有任何的数据,QueryDict 对象依然会被创建。

因此,不应该使用 if request.POST 来检查使用的是否是POST 方法;应该使用 if request.method == "POST"

 另外:如果使用 POST 上传文件的话,文件信息将包含在 FILES 属性中。

注意:键值对的值是多个的时候,比如checkbox类型的input标签,select标签,需要用:

request.POST.getlist("hobby")

3.HttpRequest.body

 一个字符串,代表请求报文的主体。在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML,Json等。

 但是,如果要处理表单数据的时候,推荐还是使用 HttpRequest.POST 。

4.HttpRequest.path

 一个字符串,表示请求的路径组件(不含域名)。

 例如:"/music/bands/the_beatles/"

5.HttpRequest.method

 一个字符串,表示请求使用的HTTP 方法。必须使用大写。

 例如:"GET"、"POST"

6.HttpRequest.encoding

 一个字符串,表示提交的数据的编码方式(如果为 None 则表示使用 DEFAULT_CHARSET 的设置,默认为 'utf-8')。

这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。

接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的 encoding 值。

如果你知道表单数据的编码不是 DEFAULT_CHARSET ,则使用它。

7.HttpRequest.META

 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器,下面是一些示例:

CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。

CONTENT_TYPE —— 请求的正文的MIME 类型。

HTTP_ACCEPT —— 响应可接收的Content-Type。

HTTP_ACCEPT_ENCODING —— 响应可接收的编码。

HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。

HTTP_HOST —— 客服端发送的HTTP Host 头部。

HTTP_REFERER —— Referring 页面。

HTTP_USER_AGENT —— 客户端的user-agent 字符串。

QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。

REMOTE_ADDR —— 客户端的IP 地址。

REMOTE_HOST —— 客户端的主机名。

REMOTE_USER —— 服务器认证后的用户。

REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。

SERVER_NAME —— 服务器的主机名。

SERVER_PORT —— 服务器的端口(是一个字符串)。

 从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,

都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。

所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

8.HttpRequest.FILES

 一个类似于字典的对象,包含所有的上传文件信息。

FILES 中的每个键为<input type="file" name="" /> 中的name,值则为对应的数据。

 注意,FILES 只有在请求的方法为POST 且提交的<form> 带有enctype="multipart/form-data" 的情况下才会

包含数据。否则,FILES 将为一个空的类似于字典的对象。

9.HttpRequest.COOKIES

 一个标准的Python 字典,包含所有的cookie。键和值都为字符串。

10.HttpRequest.session

 一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。

完整的细节参见会话的文档。

11.HttpRequest.user(用户认证组件下使用)

 一个 AUTH_USER_MODEL 类型的对象,表示当前登录的用户。

 如果用户当前没有登录,user 将设置为 django.contrib.auth.models.AnonymousUser 的一个实例。你可以通过 is_authenticated() 区分它们。

例如:

if request.user.is_authenticated():

# Do something for logged-in users.

else:

# Do something for anonymous users.

 user 只有当Django 启用 AuthenticationMiddleware 中间件时才可用。

-------------------------------------------------------------------------------------

匿名用户

class models.AnonymousUser

django.contrib.auth.models.AnonymousUser 类实现了django.contrib.auth.models.User 接口,但具有下面几个不同点:

id 永远为None。

username 永远为空字符串。

get_username() 永远返回空字符串。

is_staff 和 is_superuser 永远为False。

is_active 永远为 False。

groups 和 user_permissions 永远为空。

is_anonymous() 返回True 而不是False。

is_authenticated() 返回False 而不是True。

set_password()、check_password()、save() 和delete() 引发 NotImplementedError。

New in Django 1.8:

新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。

*/

print("--------",request.is_ajax())

print("--------", request.get_full_path())

-------------------------------------------------------------------------

模板:

模板变量:{{ name }}

模板过滤器: {{ name |safe }}

模板标签:{% for %}

-------------------------------------------------------------------------

模板变量:直接就可以点出来

<p>{{ name.upper }}</p>

<p>{{ name.lower }}</p>

-------------------------------------------------------------------------

模板过滤器:

1、add :将value的值增加2。使用形式为:{{ value | add: "2"}}。

2、addslashes:在value中的引号前增加反斜线。使用形式为:{{ value | addslashes }}。

3、capfirst:value的第一个字符转化成大写形式。使用形式为:{{ value | capfirst }}。

4、cut:从给定value中删除所有arg的值。使用形式为:{{ value | cut:arg}}。

5、date: 格式化时间格式。使用形式为:{{ value | date:"Y-m-d H:M:S" }}

6、default:如果value是False,那么输出使用缺省值。使用形式:{{ value | default: "nothing" }}。例如,如果value是“”,那么输出将是nothing

7、default_if_none:如果value是None,那么输出将使用缺省值。使用形式:{{ value | default_if_none:"nothing" }},例如,如果value是None,那么输出将是nothing

8、dictsort:如果value的值是一个字典,那么返回值是按照关键字排序的结果

使用形式:{{ value | dictsort:"name"}},例如,

如果value是:

[{'name': 'python'},{'name': 'java'},{'name': 'c++'},]

那么,输出是:

[{'name': 'c++'},{'name': 'java'},{'name': 'python'}, ]

9、dictsortreversed:如果value的值是一个字典,那么返回值是按照关键字排序的结果的反序。使用形式:与dictsort过滤器相同。

10、divisibleby:如果value能够被arg整除,那么返回值将是True。使用形式:{{ value | divisibleby:arg}},如果value是9,arg是3,那么输出将是True

11、escape:替换value中的某些字符,以适应HTML格式。使用形式:{{ value | escape}}。例如,< 转化为 &lt;> 转化为 &gt;' 转化为 &#39;" 转化为 &quot;

13、filesizeformat:格式化value,使其成为易读的文件大小。使用形式:{{ value | filesizeformat }}。例如:13KB,4.1MB等。

14、first:返回列表/字符串中的第一个元素。使用形式:{{ value | first }}

16、iriencode:如果value中有非ASCII字符,那么将其进行转化成URL中适合的编码,如果value已经进行过URLENCODE,改操作就不会再起作用。使用形式:{{value | iriencode}}

17、join:使用指定的字符串连接一个list,作用如同python的str.join(list)。使用形式:{{ value | join:"arg"}},如果value是['a','b','c'],arg是'//'那么输出是a//b//c

18、last:返回列表/字符串中的最后一个元素。使用形式:{{ value | last }}

19、length:返回value的长度。使用形式:{{ value | length }}

20、length_is:如果value的长度等于arg的时候返回True。使用形式:{{ value | length_is:"arg"}}。例如:如果value是['a','b','c'],arg是3,那么返回True

21、linebreaks:value中的"\n"将被<br/>替代,并且整个value使用</p>包围起来。使用形式:{{value|linebreaks}}

22、linebreaksbr:value中的"\n"将被<br/>替代。使用形式:{{value |linebreaksbr}}

23、linenumbers:显示的文本,带有行数。使用形式:{{value | linenumbers}}

24、ljust:在一个给定宽度的字段中,左对齐显示value。使用形式:{{value | ljust}}

25、center:在一个给定宽度的字段中,中心对齐显示value。使用形式:{{value | center}}

26、rjust::在一个给定宽度的字段中,右对齐显示value。使用形式:{{value | rjust}}

27、lower:将一个字符串转换成小写形式。使用形式:{{value | lower}}

30、random:从给定的list中返回一个任意的Item。使用形式:{{value | random}}

31、removetags:删除value中tag1,tag2....的标签。使用形式:{{value | removetags:"tag1 tag2 tag3..."}}

32、safe:当系统设置autoescaping打开的时候,该过滤器使得输出不进行escape转换。使用形式:{{value | safe}}

33、safeseq:与safe基本相同,但有一点不同的就是:safe是针对字符串,而safeseq是针对多个字符串组成的sequence

34、slice:与python语法中的slice相同。使用形式:{{some_list | slice:"2"}}

37、striptags:删除value中的所有HTML标签.使用形式:{{value | striptags}}

38、time:格式化时间输出。使用形式:{{value | time:"H:i"}}或者{{value | time}}

39、title:转换一个字符串成为title格式。

40、truncatewords:将value切成truncatewords指定的单词数目。使用形式:{{value | truncatewords:2}}。例如,如果value是Joel is a slug 那么输出将是:Joel is ...

42、upper:转换一个字符串为大写形式

43、urlencode:将一个字符串进行URLEncode

46、wordcount:返回字符串中单词的数目

-------------------------------------------------------------------------

模板标签:for if

{% for i in arr %}

<h1>{{ forloop.counter }}----->{{ i }}</h1>

{% endfor %}

记住:if条件的时间一定要遵循p8规范,不然会报错

{% for i in arr %}

{% if i > 5 %}

<h1 style="color: aquamarine">{{ i }}</h1>

{% elif i > 3 %}

<h1 style="color: bisque">{{ i }}</h1>

{% else %}

<h1 style="color: blue">{{ i }}</h1>

{% endif %}

{% endfor %}

这个有点鸡肋,我没试出来什么时候起作用。empty

{% for i in arr %}

<h1>---->{{ i.name }}</h1>

{% empty %}

shabi

{% endfor %}

with:没测试,暂时不知道怎么用,???????

with

使用一个简单地名字缓存一个复杂的变量,当你需要使用一个“昂贵的”方法(比如访问数据库)很多次的时候是非常有用的

例如:

{% with total=business.employees.count %}

{{ total }} employee{{ total|pluralize }}

{% endwith %}

-------------------------------------------------------------------------

自定义标签和过滤器步骤:

1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

2、在app中创建templatetags模块(模块名只能是templatetags)

3、创建任意 .py 文件,如:my_tags.py

注意:register = template.Library()

必须是register 还有就是L是大写

html想用的时候先导入,再用

-------------------------------------------------------------------------

自定义模板标签:

@register.simple_tag

def simple_tag_multi1(v1,v2):

return v1 * v2

HTML调用:

{% load my_tags %}

{% simple_tag_multi1 1 2 %}

-------------------------------------------------------------------------

自定义模板过滤器:

from django import template

from django.utils.safestring import mark_safe

register = template.Library()

@register.filter

def filter_mul1(x):

return x*x

@register.filter

def filter_mul2(x,y):

return x*y

HTML调用:

{% load my_tags %}

{{ arr.2|filter_mul1}}

{{ arr.2|filter_mul2:2}}

-------------------------------------------------------------------------

他们的区别:

过滤器和模板标签的区别:

@register.filter

只能传递两个变量,多个的话要用循环

能在%if变量判断时使用 {%if i|myxx1:3 >100%} 可以这样用,我觉得和for一起用的更多

@register.simple)_tag

能传递多个变量

不能在%if变量判断时使用

-------------------------------------------------------------------------

模板继承 (extend):

在base.html里面留个空

{% block content %}

{% endblock %}

然后再子类login.html去继承,去重写空

{% extends "base.html" %}

{% block content %}

<div class="container bg-info">

我不爱你了

</div>

{% endblock %}

-------------------------------------------------------------------------

ORM模型来喽:

首先要写表结构:

from django.db import models

# Create your models here.

# 单表

# class Book(models.Model):

# id=models.AutoField(primary_key=True)

# title=models.CharField(max_length=32)

# state=models.BooleanField()

# pub_date=models.DateField()

# price=models.DecimalField(max_digits=8,decimal_places=2)

# publish=models.CharField(max_length=32)

class Author(models.Model):

nid = models.AutoField(primary_key=True)

name=models.CharField( max_length=32)

age=models.IntegerField()

# 与AuthorDetail建立一对一的关系

authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)

class AuthorDetail(models.Model):

nid = models.AutoField(primary_key=True)

birthday=models.DateField()

telephone=models.BigIntegerField()

addr=models.CharField( max_length=64)

class Publish(models.Model):

nid = models.AutoField(primary_key=True)

name=models.CharField( max_length=32)

city=models.CharField( max_length=32)

email=models.EmailField()

class Book(models.Model):

nid = models.AutoField(primary_key=True)

title = models.CharField( max_length=32)

publishDate=models.DateField()

price=models.DecimalField(max_digits=5,decimal_places=2)

comment_num=models.IntegerField(default=0)

read_num = models.IntegerField(default=0)

# 与Publish建立一对多的关系,外键字段建立在多的一方 null=true 2版本用外键一定要加on_delete

publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)

# 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表

authors=models.ManyToManyField(to='Author')

-------------------------------------------------------------------------

第一步:model.py写表结构

第二步: 配置setting

DATABASES = {

'default': {

'ENGINE': 'django.db.backends.mysql',

'NAME': 'orm', # 要连接的数据库,连接前需要创建好

'USER': 'root', # 连接数据库的用户名

'PASSWORD': '123456', # 连接数据库的密码

'HOST': '127.0.0.1', # 连接主机,默认本级

'PORT': 3306 # 端口 默认3306

}

}

第三步:在项目/项目/init.py下写入

import pymysql

pymysql.install_as_MySQLdb()

第四步:

接下来在ww1窗口命令下执行:数据库迁移

python manage.py makemigrations

python manage.py migrate

第五步:创建一个超级用户

python manage.py createsuperuser

-------------------------------------------------------------------------

如何可以在浏览器通过admin修改数据

需要在 项目/程序/admin.py配置

from django.contrib import admin

from app1 import models

admin.site.register(models.Publish)

admin.site.register(models.Author)

admin.site.register(models.AuthorDetail)

admin.site.register(models.Book)

-------------------------------------------------------------------------

首先说一下登录功能:?????????不知道auth.login是干什么的

from django.contrib import auth

def login(request):

if request.method == "POST":

user = request.POST.get("user")

pwd = request.POST.get("pwd")

user = auth.authenticate(username=user,password=pwd)

if user:

auth.login(request,user)

return render(request, "index.html", locals())

return render(request,"login.html",locals())

-------------------------------------------------------------------------

注册功能:需要自己写form组件

from django.contrib.auth.models import AbstractUser

def register(request):

if request.method == "POST":

user = request.POST.get("user")

pwd = request.POST.get("pwd")

print(user,pwd)

user = auth.models.User.objects.filter(username=user)

print("注册:",user)

if not user:

auth.models.User.objects.create(username=user,password=pwd)

return redirect("/login/")

return render(request, "register.html", locals())

如果自己写组件的话:在程序下创建my_forms.py

from blog.models import UserInfo

from django import forms

from django.forms import widgets

from django.core.exceptions import NON_FIELD_ERRORS,ValidationError

class UserForm(forms.Form):

user = forms.CharField(max_length=32,

error_messages={"required":"用户名你都不写注册个屁"},

label="用户名",

widget=widgets.TextInput(attrs={"class": "form-control"})

)

pwd = forms.CharField(max_length=32,

error_messages={"required": "你不写密码你觉得你很吊?"},

label="密码",

widget=widgets.PasswordInput(attrs={"class": "form-control"})

)

re_pwd = forms.CharField(max_length=32,

error_messages={"required": "让你重复一下密码有那么难?"},

label="重复密码",

widget=widgets.PasswordInput(attrs={"class": "form-control"})

)

email = forms.EmailField(max_length=32,

error_messages={"required": "你不会穷的连QQ邮箱都没有吧"},

label="邮箱",

widget=widgets.EmailInput(attrs={"class": "form-control"})

)

def clean_user(self):

val = self.cleaned_data.get("user")

user = UserInfo.objects.filter(username=val).first()

if not user:

return val

else:

raise ValidationError("该用户已经注册,你来晚啦")

def clean(self):

pwd = self.cleaned_data.get("pwd")

re_pwd = self.cleaned_data.get("re_pwd")

print(pwd,re_pwd)

if pwd and re_pwd:

if pwd == re_pwd:

return self.cleaned_data

else:

raise ValidationError("两次密码不一致")

 

 

在视图中:

from blog.my_forms import UserForm

def register(request):

response = {"user": None, "msg": None}

if request.is_ajax():

form = UserForm(request.POST)

print(request.POST.get("user"))

response = {"user": None, "msg": None}

if form.is_valid():

response["user"] = request.POST.get("user")

user = form.cleaned_data.get("user")

pwd = form.cleaned_data.get("pwd")

email = form.cleaned_data.get("email")

avatar_obj = request.FILES.get("avatar")

extra = {}

if avatar_obj:

extra["avatar"] = avatar_obj

UserInfo.objects.create_user(username=user, password=pwd, email=email, **extra)

else:

response["msg"] = form.errors

return JsonResponse(response)

form = UserForm()

return render(request, "register.html", {"form": form})

-------------------------------------------------------------------------

如果想打印mysql语句 需要在setting配置

LOGGING = {

'version': 1,

'disable_existing_loggers': False,

'handlers': {

'console':{

'level':'DEBUG',

'class':'logging.StreamHandler',

},

},

'loggers': {

'django.db.backends': {

'handlers': ['console'],

'propagate': True,

'level':'DEBUG',

},

}

}

-------------------------------------------------------------------------

# 单表::::::::::::::

#增删改查:

## 添加数据

# 添加数据方法一(不推荐使用):

book_obj = models.Book(title="a",price=1,publishDate=datetime.datetime.strptime("2014-11-1","%Y-%M-%d"),publish_id=2)

book_obj.save()

#添加数据方法二:推荐使用

book_obj = models.Book.objects.create(title="a",price=1,publishDate=datetime.datetime.strptime("2014-11-1","%Y-%M-%d"),publish_id=2)

print("插入成功")

# 查询数据

arr = models.Book.objects.all()

arr = models.Book.objects.filter(title="a")

book_obj = models.Book.objects.first()

book_obj = models.Book.objects.get(nid=1)

book_obj = models.Book.objects.last()

book_obj = models.Book.objects.count()

arr = models.Book.objects.exclude(nid=7)

book_obj = models.Book.objects.filter(nid=100).exists()

arr = models.Book.objects.values("nid","title")

arr = models.Book.objects.values_list("nid","title")

arr = models.Book.objects.values("title").distinct()

# 基于双下划线的模糊查询 gt,gte,lt,lte

models.Book.objects.filter(price__in=[100, 200, 300])

models.Book.objects.filter(price__gt=100)

models.Book.objects.filter(price__lt=100)

models.Book.objects.filter(price__range=[100, 200])

models.Book.objects.filter(title__contains="python") 区分大小写

models.Book.objects.filter(title__icontains="python") 不区分大小写

models.Book.objects.filter(title__startswith="py")

models.Book.objects.filter(pub_date__year=2012)

# 删除数据

count = models.Book.objects.filter(title="a").delete()

# 更新数据

book_obj = models.Book.objects.filter(title="撒打算").update(title="书籍C")

-------------------------------------------------------------------------

# 多表操作

# # 一对多:方式一

# models.Publish.objects.create(name="人民出版社",email="2096@qq.com",city="人民战斗机第")

# models.Book.objects.create(title="西游记",price=100,publishDate="2014-1-1",publish_id=3)

# # 一对多 方式二

# p = models.Publish.objects.create(name="人民出版社", email="2096@qq.com", city="人民战斗机第")

# models.Book.objects.create(title="西游记", price=100, publishDate="2014-1-1", publish=p)

#多对多添加数据

book_obj = models.Book.objects.filter(title="书籍C").first()

book_obj.authors.add(2,3) ##nid的值

book_obj.authors.add(author1,author2)

# 解除多对多关系

book_obj.authors.remove(3,5) ##nid的值

book_obj.authors.clear()

多对多反向操作:

author_obj = models.Author.objects.filter(name="作者C").first()

author_obj.book_set.add(4,5)

author_obj.book_set.remove(4, 5)

author_obj.book_set.clear()

 

-------------------------------------------------------------------------

# ====================跨表查询==============

# 第一种:基于对象的查询 第二种:基于双划线的查询

# 第三种:聚合 和 分组 查询 第四种:F与Q查询

-------------------------------------------------------------------------

第一种:基于对象的查询

# 一对一 正向

author_obj = models.Author.objects.first()

print(author_obj.authorDetail.birthday)

# 一对一 反向

authordetail_obj = models.AuthorDetail.objects.last()

print(authordetail_obj.author.name)

#一对多 正向 书和出版社

book_obj = models.Book.objects.first()

print(book_obj.publish)

# 一对多 反向 书和出版社

publish_obj = models.Publish.objects.filter(nid=2).first()

print(publish_obj.book_set.all())

#多对多 正向 数和作者

book_obj = models.Book.objects.get(nid=2)

print(book_obj.authors)

# 多对多 反向 书和作者

publish_obj = models.Publish.objects.get(nid=2)

print(publish_obj.book_set.all())

-------------------------------------------------------------------------

第二种:基于双划线的查询

# 一对一 正向查询 作者和作者详情表

author_arr = models.Author.objects.all().values("authorDetail__birthday")

print(author_arr)

# 一对一 反向查询 作者和作者详情表

author_arr = models.Author.objects.filter(authorDetail_id=2)

print(author_arr)

# 一对多 正向 书和出版社

book_obj = models.Book.objects.all().values("publish__name")

print(book_obj)

# 一对多 反向 书和出版社

publish_obj = models.Publish.objects.filter(book__title="书籍C")

print(publish_obj)

# 多对多 正向 数和作者

book_obj = models.Book.objects.all().values("authors__name")

print(book_obj)

# 多对多 反向 书和作者

publish_obj = models.Publish.objects.filter(book__title="书籍C")

print(publish_obj)

 

-------------------------------------------------------------------------

第三种:聚合 和 分组 查询

from django.db.models import Avg, Count, Max, Min

# 书和出版社 通过书的id分组

arr = models.Publish.objects.values("nid").annotate(c=Count("book__nid")).values("name","c")

print(arr)

-------------------------------------------------------------------------

第四种:F与Q查询

from django.db.models import F,Q

arr = models.Book.objects.values(money=F("price")+100)

Book.objects.update(price=F("price")+100)

b1 = Book.objects.filter(comment_num__gt=F("read_num"))

b2 = Book.objects.filter(Q(comment_num=30)&Q(read_num=21))

-------------------------------------------------------------------------

django 查询 排序 orderby

# orderby 升序和降序

arr = models.Book.objects.order_by("nid")

arr = models.Book.objects.order_by("-nid")

-------------------------------------------------------------------------

# 批量插入数据

# book_list = []

# for i in range(100):

# book = Book(title=f"book_{i}",price=i,publishDate="2014-10-11",publish_id=1)

# book_list.append(book)

# Book.objects.bulk_create(book_list)

-------------------------------------------------------------------------

ContentType指的是请求体的编码类型,常见的类型共有3种:

1 application/x-www-form-urlencoded

2 multipart/form-data

3 application/json

-------------------------------------------------------------------------

Ajax与文件上传

HTML:

<input type="file" id="file">

<button class="btn" id="btn_sendfile">文件上传</button>

script:

$("#btn_sendfile").click(function (){

var formdata=new FormData();

formdata.append("user","wusen");

formdata.append("file",$("#file")[0].files[0]);

$.ajax({

url:"",

type:"post",

data: formdata,

processData: false , // 不处理数据

contentType: false, // 不设置内容类型

success:function (data){

console.log("成功")

}

})

})

视图:

if request.is_ajax():

with open("D://a.png","wb") as f:

for line in request.FILES.get("file"):

f.write(line)

-------------------------------------------------------------------------

说一下客户端的头像:

HTMl:

<label for="b" id="a">

<img src="D://a.jpg" id="c">

</label>

<input type="file" name="" id="b">

script:

$("#b").change(function(){

var file_obj = $(this)[0].files[0]

var reader = new FileReader()

reader.readAsDataURL(file_obj)

reader.onload=function(){

$("#c").attr("src",reader.result)

console.log(reader.result)

console.log("结束")

}

})

-------------------------------------------------------------------------

分页器:

# 有一个小知识点 # 不存在的情况下,默认值为11

# request.GET.get("page",11)

from django.core.paginator import Paginator

from django.core.paginator import PageNotAnInteger

from django.core.paginator import EmptyPage

arr = models.Publish.objects.all()

paginator = Paginator(arr,5)

print(paginator.count) # 一共多少条数据

print(paginator.num_pages) # 一共多少条数据

print(paginator.page_range) # 一共多少条数据

arr = paginator.get_page(3)

print(arr.next_page_number())

print(arr.has_next())

print(arr.previous_page_number())

print(arr.has_previous())

-------------------------------------------------------------------------

forms组件

 

from app1.models import UserInfo

from django import forms

from django.forms import widgets

from django.core.exceptions import NON_FIELD_ERRORS,ValidationError

class UserForm(forms.Form):

user = forms.CharField(max_length=32,

error_messages={"required":"用户名你都不写注册个屁"},

label="用户名",

widget=widgets.TextInput(attrs={"class": "form-control"})

)

pwd = forms.CharField(max_length=32,

error_messages={"required": "你不写密码你觉得你很吊?"},

label="密码",

widget=widgets.PasswordInput(attrs={"class": "form-control"})

)

re_pwd = forms.CharField(max_length=32,

error_messages={"required": "让你重复一下密码有那么难?"},

label="重复密码",

widget=widgets.PasswordInput(attrs={"class": "form-control"})

)

email = forms.EmailField(max_length=32,

error_messages={"required": "你不会穷的连QQ邮箱都没有吧"},

label="邮箱",

widget=widgets.EmailInput(attrs={"class": "form-control"})

)

def clean_user(self): 局部钩子

val = self.cleaned_data.get("user")

user = UserInfo.objects.filter(username=val).first()

if not user:

return val

else:

raise ValidationError("该用户已经注册,你来晚啦")

def clean(self): 全局钩子

pwd = self.cleaned_data.get("pwd")

re_pwd = self.cleaned_data.get("re_pwd")

print(pwd,re_pwd)

if pwd and re_pwd:

if pwd == re_pwd:

return self.cleaned_data

else:

raise ValidationError("两次密码不一致")

 

-------------------

if request.method == "POST":

form = UserForm(request.POST)

if form.is_valid():

print("此时所有的都通过了校验",form.cleaned_data) # 所有干净的字段以及对应的值

else:

clean_error = form.errors.get("__all__")

print("错误字段",form.errors)

response["msg"] = form.errors

return JsonResponse(response)

form = UserForm()

 

<div class="container" >

<form id="forms">

{% for f in form %}

<p>{{ f.label }}</p>

<p>{{ f }}

<span class="pull-right"></span>

</p>

{% endfor %}

<button class="btn btn-danger btn_register">提交</button>

</form>

</div>

$(".btn_register").click(function (){

var formdata = new FormData()

var requestData = $("#forms").serializeArray()

$.each(requestData,function (index,data){

console.log(data.name,data.value)

formdata.append(data.name,data.value)

})

$.ajax({

url: "",

data:formdata,

type: "post",

contentType: false,

processData: false,

success:function (data){

$.each(data.msg,function (key,value){

$("#id_"+key).parent().addClass("has-error")

$("#id_"+key).next().text(value)

})

}

})

})

</script>

综上所述:forms组件是用来帮助校验用的,一般用于注册校验。

首先自己写forms组件,定义一个py文件,自己写(此时只用到forms组件)

然后在视图中实例化forms类,你可以直接用,在前端用for标签渲染

用Ajax往这边传数据的时候,如果想传不被序列化的数据时,一定要加上参数

contentType: false,processData: false,

然后视图中分两步:一种是全部通过校验is_valid

否则,干净数据和脏数据分开。

其余有局部钩子和全局钩子。

他会先把forms校验完毕,再去校验全部和局部钩子

局部钩子和全局钩子写功能的时候就可能会用到你的model里面的表喽。

-------------------------------------------------------------------------

cookie和session:

1、cookie 和session的区别是bai:cookie数据保存在客户端,session数据保存在服务器端。

2、两个都可以用来存私密的东西,同样也都有有效期的说法,区别在于session是放在服务器上的,过期与否取决于服务期的设定,cookie是存在客户端的,过去与否可以在cookie生成的时候设置进去。  

(1)、cookie数据存放在客户的浏览器上,session数据放在服务器上 ;

(2)、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,如果主要考虑到安全应当使用session ;

(3)、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,如果主要考虑到减轻服务器性能方面,应当使用COOKIE ;

(4)、单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K;

(5)、所以将登陆信息等重要信息存放为SESSION;其他信息如果需要保留,可以放在COOKIE中。

3、cookie和session的共同之处在于:cookie和session都是用来跟踪浏览器用户身份的会话方式。

4、cookie 是一种发送到客户浏览器的文本串句柄,并保存在客户机硬盘上,可以用来在某个WEB站点会话间持久的保持数据。

 

怎么用COOKIES

response = HttpResponse()

response = render()

response = redirect()

response.set_cookie("a","aa")

下面这个不是加密,客户端的人会看不懂,相当于加密

response.set_signed_cookie("b","bb")

return response

获取cookie:

request.COOKIES

删除cookie:

response.delete_cookie("cookie_key")

 

源码:

class HttpResponseBase:

def set_cookie(self, key, 键

            value='', 值

            max_age=None, 超长时间

                             cookie需要延续的时间(以秒为单位)

                             如果参数是\ None`` ,这个cookie会延续到浏览器关闭为止。

            expires=None, 超长时间

                         expires默认None ,cookie失效的实际日期/时间。

                         

            path='/', Cookie生效的路径,

浏览器只会把cookie回传给带有该路径的页面,这样可以避免将

cookie传给站点中的其他的应用。

/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问

         

domain=None, Cookie生效的域名

你可用这个参数来构造一个跨站cookie。

如, domain=".example.com"

所构造的cookie对下面这些站点都是可读的:

www.example.com 、 www2.example.com

                        和an.other.sub.domain.example.com 。

如果该参数设置为 None ,cookie只能由设置它的站点读取。

            secure=False, 如果设置为 True ,浏览器将通过HTTPS来回传cookie。

            httponly=False 只能http协议传输,无法被JavaScript获取

(不是绝对,底层抓包可以获取到也可以被覆盖)

         ): pass

 

 

 

SESSION:

第一步需要配置在setting

SESSION_ENGINE = 'django.contrib.sessions.backends.db' # 引擎(默认)

SESSION_COOKIE_NAME = "sessionid" # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)

SESSION_COOKIE_PATH = "/" # Session的cookie保存的路径(默认)

SESSION_COOKIE_DOMAIN = None # Session的cookie保存的域名(默认)

SESSION_COOKIE_SECURE = False # 是否Https传输cookie(默认)

SESSION_COOKIE_HTTPONLY = True # 是否Session的cookie只支持http传输(默认)

SESSION_COOKIE_AGE = 1209600 # Session的cookie失效日期(2周)(默认)

SESSION_EXPIRE_AT_BROWSER_CLOSE = False # 是否关闭浏览器使得Session过期(默认)

SESSION_SAVE_EVERY_REQUEST = False # 是否每次请求都保存Session,默认修改之后才保存(默认)

 

session怎么用呢。。。

django中session语法

1、设置Sessions值

request.session['session_name'] ="admin"

2、获取Sessions值

session_name = request.session["session_name"]

3、删除Sessions值

del request.session["session_name"]

4、flush()

删除当前的会话数据并删除会话的Cookie。

这用于确保前面的会话数据不可以再次被用户的浏览器访问

5、get(key, default=None)

fav_color = request.session.get('fav_color', 'red')

6、pop(key)

fav_color = request.session.pop('fav_color')

7、keys()

8、items()

9、setdefault()

10 用户session的随机字符串

request.session.session_key

# 将所有Session失效日期小于当前日期的数据删除

request.session.clear_expired()

# 检查 用户session的随机字符串 在数据库中是否

request.session.exists("session_key")

# 删除当前用户的所有Session数据

request.session.delete("session_key")

request.session.set_expiry(value)

* 如果value是个整数,session会在些秒数后失效。

* 如果value是个datatime或timedelta,session就会在这个时间后失效。

* 如果value是0,用户关闭浏览器session就会失效。

* 如果value是None,session会依赖全局session失效策略。

-------------------------------------------------------------------------

用户认证组件(这个就是django帮我们封装的,原理是session)

auth_user这个表是django帮我们提供的

from django.contrib import auth

此时只是帮你校验是否存在User。此时用request.user是没有值的

user = authenticate(username='someone',password='somepassword')

此时request.user是全局变量

auth.login()

注销功能

auth.logout()

我们需要功能验证用户是否登录:

from django.contrib.auth.decorators import login_required

1.request.user.is_authenticated 只要不执行login()就是False

2.@login_required 装饰器哦

若用户没有登录,则会跳转到django默认的 登录URL '/accounts/login/ ' (这个值可以在settings文件中配置LOGIN_URL="/login/")。并传递 当前访问url的绝对路径 (登陆成功后,会重定向到该路径)。

创建用户:

from django.contrib.auth.models import User

user = User.objects.create_user(username='',password='',email='')

就是用这个表去操作

修改密码:但是如果用表去更新数据呢!到时候再说

user = User.objects.get(username='')

user.set_password(password='')

user.save  

-------------------------------------------------------------------------

中间键:

中间件顾名思义,是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。因为改变的是全局,所以需要谨慎实用,用不好会影响到性能。

process_request 默认返回值就是return None

process_view

process_exception

process_response

浏览器请求-wsgrief-中间键123-路由控制-数据库-模板-中间键321-wsgrief-浏览器

如果中间键1的request你给返回值,那么他会

浏览器请求-wsgrief-中间键1-中间键1-wsgrief-浏览器

浏览器请求-wsgrief-process_request123-路由控制-process_view123-数据库-模板-process_response321-wsgrief-浏览器

视图报错会触发process_exception

 

第一步:在setting配置

MIDDLEWARE = [

'django.middleware.security.SecurityMiddleware',

'django.contrib.sessions.middleware.SessionMiddleware',

'django.middleware.common.CommonMiddleware',

'django.middleware.csrf.CsrfViewMiddleware',

'django.contrib.auth.middleware.AuthenticationMiddleware',

'django.contrib.messages.middleware.MessageMiddleware',

'django.middleware.clickjacking.XFrameOptionsMiddleware',

]

第二步:自己写一个py文件中间键,并且把路径加到setting里面

第三步:没了

from django.utils.deprecation import MiddlewareMixin

class Md1(MiddlewareMixin):

def process_request(self,request):

print("Md1请求")

def process_response(self,request,response):

print("Md1返回")

return response

 

作为延伸扩展内容,有余力的同学可以尝试着读一下以下两个自带的中间件:

'django.contrib.sessions.middleware.SessionMiddleware',

'django.contrib.auth.middleware.AuthenticationMiddleware',

应用:

1、做IP访问频率限制(我觉得用session和cookie做比较好)

某些IP访问服务器的频率过高,进行拦截,比如限制每分钟不能超过20次。

2、URL访问过滤

-------------------------------------------------------------------------

 

补充:ORM嵌套查询, 每个出版社,最便宜的书籍以及名字

querymin = models.Publish.objects.values("nid").annotate(min_price=Min("book__price")).values("min_price")

ret = models.Publish.objects.filter(book__price__in=querymin).values("nid","book__title","book__price")

print(ret)


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
6月前
|
SQL 前端开发 JavaScript
Django零基础-快速了解基本框架笔记-附案例
Django零基础-快速了解基本框架笔记-附案例
70 0
|
6月前
|
JSON 前端开发 JavaScript
前端知识笔记(三十七)———Django与Ajax
前端知识笔记(三十七)———Django与Ajax
51 0
|
6月前
|
JSON 前端开发 JavaScript
前端知识笔记(二)———Django与Ajax
前端知识笔记(二)———Django与Ajax
60 0
|
存储 Web App开发 前端开发
Django知识点笔记(4)
Django知识点笔记(4)
Django知识点笔记(4)
|
SQL XML 缓存
Django知识点笔记(3)
Django知识点笔记(3)
Django知识点笔记(3)
|
SQL 数据可视化 前端开发
Django知识点笔记(2)
Django知识点笔记(2)
Django知识点笔记(2)
|
设计模式 JSON 前端开发
Django知识点笔记(1)
Django知识点笔记(1)
Django知识点笔记(1)
|
前端开发 Python
Django入门笔记:第十三章、用户登录
Django入门笔记:第十三章、用户登录
111 0
|
关系型数据库 MySQL Shell
Django实践笔记
Django实战笔记
2089 0
|
弹性计算 Python
阿里云ECS服务器使用笔记(一)搭建Django
经验之谈的笔记,有问题留言。 经验: 1.服务器在年中6月或者年尾租,有优惠。 2.Django搭建尽量用virtualenv,这样在里面随便折腾,搞错了,直接删掉重新来就可以了。
2704 0