django基础1

一. 框架
django为全栈框架
tornado,flask为非全栈框架
 
内容型网站(cms)一般选用django框架,对于接口类的网站可以用flask
 
 
二. django-amdin.py  和 manage.py
 
django-admin.py是Django的一个用于管理任务的命令行工具;manage.py是对django-admin.py的简单包装,它包含django-admin.py的所有命令,每个Django project里面都会包含一个manage.py
 
1. 语法:
django-admin.py 子命令 
manage.py 子命令
 
where django-admin.py   查看django-admin.py的位置
 
 
 
2. django-admin.py help   查看帮助信息
常见子命令:
startproject:创建一个项目
startapp:创建一个app
runserver:运行开发服务器
shell:进入django shell
compilemessages:编译语言文件
makemessages:创建语言文件
makemigrations:生成数据库同步脚本
migrate:同步数据库
showmigrations:查看生成的数据库同步脚本
sqlflush:查看生成清空数据库的脚本
sqlmigrate:查看数据库同步的sql语句
dumpdata:导出数据
loaddata:导入数据
 
django-admin.py help startproject  查看命令简要说明
 
 
3. manage.py特有的一些子命令
 
manage.py help :查看帮助信息
 
比如: 
manage.py runserver  开启服务
manage.py createsuperuser:创建超级管理员
manage.py changepassword 账号名:  用户修改指定用户名密码
 
 
思考点:
默认runserver的端口是8000,如果想用其他端口,在后面加上端口即可,如下
python manage.py runserver 8080
 
 
三.  建立一个简单网页的注意点
 
1. 编辑应用程序中的view.py
from django.shortcuts import render
 
def hello(request): 
    return render(request, 'table.html')
 
注意
1) hello()中request参数是必须的,否则请求不到信息
2) render()中的2个参数,table.html为请求的网页
 
 
查找用户信息需要在view.py中引入模型如下,这个是有实际的层级目录的
from django.contrib.auth.models import User
 
课后思考
1. 目前模板和静态文件都是放在app的目录下的,并且文件夹名必须是static和templates;
如果想把模板目录和静态文件放在项目根目录怎么做?
这需要在settings.py中进行配置
对于static目录,需要在末尾写上STATICFILES_DIRS=(os.path.join(BASE_DIR, 'static'),  #末尾的逗号不能少,表示一个元组
)
对于templates目录,需要在setting.py中的TEMPLATES部分中添加目录名,如下
'DIRS': ['templates'], 原先中括号里是空的
 
 
 
 
四.  MTV开发模式
 
M代表模型:负责业务对象和数据库的关系映射
T代表模板:负责如何把页面展示给用户
V代表视图:负责业务逻辑,并在适当时候调用model和template
 
除了上面的3层之外,还需要一个URL分发器,就是url.py文件,它的作用是将一个个URL页面分发给不同的view处理,view再调用相应的model和template 
 
 
 
五. url.py
 
1. 基本用法
from django.conf.urls import url
from hello import views
 
urlpatterns = [
    url(r'^hello/$', views.hello)
]
 
2. URL模式
urlpatterns = [
    url(正则表达式,view函数,参数,别名,前缀)
]
 
例如url(r'^hello/$', view.hello, {'a': '123'}) #这种写法参数是固定的
 
此时在view.py的hello函数中必须有参数a
def hello(request, a):
    print(a) #可打印出123
 
别名用于方便调用此url
前缀用的不多,可写app的名字
 
 
3. URL常见写法示例,正则表达式
 
例子1:url (r'^test/(?P<id>\d{2})/$', views.test)
 
其中P表示分组
<id>表定义了一个可变参数,名为id,需要在view.py中的test函数中加入这个参数id,   
def test(request, id):
    print(id)
 
例子2:多个参数
url(r'^test/(?P<id>\d{2})/(?P<key>\w+)/$', views.test)
2个参数,一个参数名为2位数的id,另一个参数名为至少一个字符的key,实际访问方式例子为localhost:8000/test/23/ab/
 
同样在view.py中修改test的参数为
def test(request, id, key):
    print(id)
    print(key)
 
 
 
六. view.py
 
1. http请求中产生的两个核心对象
http请求:HttpdRequest
http响应:HttpResponse 
 
所在位置:django.http
也就是可写成 from django.http import HttpRequest, HttpResponse
 
其实在views.py中定义的函数,其参数request就属于HttpRequest
 
判断方法:
def hello(request, a):
    print(isinstance(request, HttpRequest))会返回true
 
 
2. HttpRequest对象的属性
 
1)path
def hello(request,a):
    print(request.path)
请求页面的全路径,不包括域名,比如"/music/bands/"
 
2)method
返回请求类型,返回值全大写表示,例如
def hello(request,a):
    print(request.method)
 
if request.method == 'GET':
    do something()
elif request.method == 'POST':
    do something_else()
 
3)request.POST和request.GET
 
views.py中定义函数如下
def hello(request, a):
    print(request.POST.get('key'))  #用POST方式来接收模板文件中提供的数据。这里的POST也可改成GET,此时表单中也需改为get
 
使用post提交的时候,需要用到模板中的表单,(当然get方式也能用表单来获取数据)定义如下
<form method="post" action="/hello/">
{% csrf_token %} #post方式必须加这行,get方式不需要
<input type="text" value="" name="key">
<input type="submit" value="提交">
 
当使用get方式时,可以直接在网页中输入localhost:8000/hello/?name=12345,这样在view.py中如下写,就能打印出name的值:12345
def hello(request,a):
    print(request.GET.get('name')
 
 
4)user
user是一个django.contrib.auth.models.User对象,代表当前登陆的用户,如果访问用户当前没有登陆,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的is_authenticated()方法来辨别用户是否登陆;
if request.user.is_authenticated():
    #do something for logged-in users
else:
    #do something for anoymouse users
只有激活Django中的AuthenticationMiddleware时该属性才可用
 
5)session
唯一可读写的属性,代表当前会话的字典对象,只有激活Django中的session支持时该属性才可用
 
 
3. HttpRequest对象的方法(部分),
get_full_path()  返回包含查询字符串的完整请求路径,包含?后面的参数,使用方法:request.get_full_path(), 返回结果类似于“/music/bands/?print=true"。
对比其path属性,request.path返回的结果不包含后面的参数
 
 
4. 在HttpResponse对象上扩展的常用方法
 
1)render, render_to_response, redirect
render 其实是返回一个HttpResponse对象的快捷方式
redirect也是response对象
详见https://docs.djangoproject.com/en/1.9/topics/http/shortcuts
 
例子
from django.shortcuts import render,render_to_response,redirect
from django.contrib.auth.models import User
 
def hello(request, a):
    user_list = User.objects.all()
    return render(request,'table.html', {'user_list' : user_list})
    上面一行等价于
    return render_to_response('table.html', {'user_list': user_list})
    return redirect('http://www.baidu.com')  
 
2)对于HttpRequest对象来说,是由Django自动创建,但是HttpResponse对象就必须我们自己创建。 每个view中的request请求处理的方法必须返回一个HttpResponse对象。
 
 
HttpResponse类在django.http.HttpResponse
 
构造HttpResponse
response =  HttpResponse("here is your site")
response = HttpResponse("text only", mimetype="text/plain") #指定返回类型
 
3)HttpResponse的子类
 
HttpResponseRedirect
构造函数接收单个参数:重定向到的URL。可以是全URL,例如http://www.baidu.com或者相对URL,例如/search.
注意这将返回HTTP状态码302,表示临时跳转
 
HttpResponsePermanentRedirect
同HttpResponseRedirect一样,但是返回永久重定向(HTTP状态码301)
 
HttpResponseNotFound  返回404
 
JsonResponse  返回Json字符串
 
更详细的有关request和response对象的介绍
 
5. 其他常用方法
locals() :可直接将函数中的所有变量全部传给模板,变量包括系统变量和自定义的变量
return render_to_response('table.html', locals()) 这个命令和上面1)中例子的效果一样,算是一种简写的方式
 
 
 
 
七. 数据库的配置
 
1. mysql驱动程序
PyMySQL : https://pypi.python.org/pypi/PyMySQL  纯python的驱动,支持python3, 推荐用这个,支持pip安装,pip install pymysql
 
2. 在setting中配置
mysql引擎名称:django.db.backends.mysql
 
DATABASES = {
    ‘default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'hello', 数据库名
            'USER': 'root',
            'PASSWORD': '1234',
            # 'HOST': '',
            # 'PORT': '',
  }
}
 
3,在项目settings.py目录里的init.py加入
import pymysql
pymysql.install_as_MySQLdb()
 
 
 
八. ORM机制讲解
 
1. 定义
对象关系映射:object relational mapping, 简称ORM,用于实现面向对象编程语言里不同类型系统间的数据转换,也就是说用面向对象的方式去操作数据库的创建表,增加,删除,查询等操作
 
2. mysql查询
 
1)query属性
例子
def hello(request, a):
    user_list = User.objects.all()
    print (user_list.query)  #会打印出select查询语句
 
2)配置django日志的详细使用详解
 
在setting.py末尾加入如下代码, 就可在控制台显示由ORM生成的mysql代码
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
    'console': {
          'level': 'DEBUG',
          'class': 'logging.StreamHandler',
},
},
'loggers': {
   'django.db.backends': {
      'handlers': ['console'],
      'level': 'DEBUG',
      'propagate': True,
},
},
}
 
 
3)使用开发工具django_debug_toolbar
 
 
 
 
九. models.py
 
1.创建数据模型
作者:有名字
作者详情:性别,年龄,email等,和作者是1对1
出版商:名称,地址,所在城市,省,国家,网站
书籍:有书名和出版日期,一本书可有多个作者,一个作者也可写多本书,一本书由一个出版商出版,所以出版商和书籍是一对多的关系(one to many),也被称为外键
 
from django.db import models
 
class Publisher(models.Model):
    name=models.CharField(max_length=30)
    address=models.CharField(max_length=50) 
    website = models.URLField()
 
class Author(models.Model):
    name = models.CharField(max_length=30)
 
class AuthorDetail(models.Model):
    sex = models.BooleanField(max_lenght=1, choices((0,'男'),(1,'女'),))
    email = models.EmailField()
    birthday = models.DateField()
    author = model.OneToOneField(Author)
 
class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToMany(Author)
    publisher = models.ForeighKey(Publisher)
    publication_date =  models.DateField()
 
说明:
1. 每个数据模型都是django.db.models.Model的子类。它的父类Model包含了所有必要的和数据库交互的方法,并提供了一个简洁漂亮的定义数据库字段的语法
 
2. 每个模型相当于单个数据库表(这条规则的例外情况是多对对关系,此时会多生成一个关系表),每个属性名就是这个表的一个字段名
 
 
2. 模型常用的字段选项
 null (null=True|False)
数据库字段的设置是否可以为空(数据库进行验证)
blank(null=True|False)
字段是否为空django会进行验证(表单进行验证)
choices 配置字段可选属性的定义
default 字段的默认值
help_text 字段文字帮助
primary_key 是否主键,如果没显示指定,django会自动增加一个默认主键,id = models.AutoField(primary_key=True)
unique  是否唯一,对于数据表而言
verbose_name 字段的详细名称,如果不指定属性,默认使用字段的属性名称
例如name = models.CharField(max_length=30, verbose_name="名称")
也可简写成
name = models.CharField("名称", max_length=30) #此时名称参数必须写在前面
 
字段类型和字段选项的设置详解
 
 
3. 定义数据模型的扩展属性
通过内部类Meta给数据模型类增加扩展属性, 比如会影响后台显示的名称
class Meta:
    verbose_name = '名称'
    verbose_name_plural = '名称复数形式'
    ordering = ['排序字段']
 
更多详见https://docs.djangoproject.com/en/1.9/ref/models/options/
 
 
4. 定义模型的方法
用处:比如新建了一个书名,在后台显示的新条目名为book_object, 如果想改变这个名字,就可用定义模型方法
 
定义模型方法可将当前对应的数据,组装成具体的业务逻辑
 
例子,定义__unicode__()让对象有个自定义的名字
在python2中用__unicode__(), python3里用__str__()
def __str__(self):
    return self.name
 
 
5. 数据库同步操作技巧
 
1. 创建应用程序后,app目录下会生成一个migrations目录,作用是存放通过makemigrations命令生成的数据库脚本。
migrations目录下必须有__init__.py才能正常的使用数据库同步的功能
 
2. 一张数据表django_migrations,记录数据库脚本的使用情况。
表中的字段:
app: app名字
name: 脚本的文件名称
applied:脚本的执行时间
 
3. 数据库相关的命令
flush: 清空数据库,恢复数据库到最初状态;没记录日志,生产环境下很危险。
python manage.py flush
 
makemigrations: 生成数据库同步脚本
python manage.py makemigrations会生成所有app的数据库脚本;也可指定单个app,比如python manage.py makemigration hello
 
migrate:执行同步脚本,来同步数据库;同样可指定单个app
 
showmigrations:查看生成的数据库同步脚本
sqlflush: 查看生成清空数据库的脚本
 
sqlmigrate: 查看数据库同步的sql语句
例如:python manage.py sqlmigrate hello 0001_initial
 
终极大招
在开发过程中,数据库同步误操作后,难免会遇到后面不能同步成功的情况。怎么搞?两种方法如下
1. 生产环境下,分析生成的数据库脚本和django_migrations的同步记录是否匹配
2. 开发环境下,把migration目录下的脚本(除__init__.py)全部删除,再把整个数据库删掉之后创建一个新数据库,数据库同步操作再来一遍
 
 
 
 
十. ORM常见操作
首先进入shell界面,python manage.py shell
 
1. 增加
create和save方法
1)增加一个作者记录
from hello.models import *
Author.objects.create(name="lilei")
AuthorDetail.objects.create(sex=False,email='[email protected]', address='beijing',author_id=1)
 
注意最后的author_id=1, 其中author_id是authordetail表中自动生成的字段名,1的值是通过在Author表中插入作者记录后自动生成的id号。
主外键的插入方式有两种,第一种是通过id的方式,这里就是通过id方式;第二种是通过对象的方式,在下面的例子中会说明
 
 
2)增加一个出版社
pub = Publisher()
pub.name = '电子工业出版社'
pub.address = '华阳'
pub.city = '四川'
pub.save()
 
3)增加一个书籍
Book.objects.create(title='python实现', publisher=pub.publication_date='2009-05-06')
 
增加多对多关系
book=Book.objects.get(id=1)
auther = Author.object.get(id=1)
book.authors.add(author)
 
小结:
1)objects是model默认管理器,它提供一系列方法来管理数据,比如create是objects的方法
2)插入主外键关系的时候,可以用对象的方式,也可直接用关联id的方式
3)插入多对多关系的时候要分步操作
4)save()是model对象的方法
 
2. 修改
update和save方法
实例
1)修改id为1的作者的名字为jack,性别为女
author=Author.objects.get(id=1)
author.name='jack'
author.save()
 
2)修改名为"电子工业出版社"的出版社地址为中和,城市为成都
Publisher.objects.filter(id=1).update(city='成都', address=
'中和') 
 
注意:
update是QuerySet对象的方法,而filter()的返回类型为QuerySet
 
 
3. 查询
1)查询所有出版社信息
Publisher.objects.all()
 
可用type(Publlisher.objects.all())查看返回类型
 
注意:
1)ORM中的查询是惰性查询,比如Publisher.objects.all()只是返回了一个QuerySet(查询结果集对象),并不会马上执行sql,而是调用QuerySet的时候才执行
简单说就是print(Publisher.objects.all())会执行sql,显示出查询结果;不加print()就不执行
 
2)在django shell中不是惰性查询
 
 
4. 删除
delete方法
1)删除id为1的书籍信息, 会删除所有表中的书籍信息
Book.objects.filter(id=1).delete()
 
2)删除city为成都的出版社
Publisher.objects.filter(city='成都').delete()
 
注意:
1)django中的删除默认是级联删除
2)delete方法也是 QuerySet对象的方法
 
 
 
5. 查询常用的API,使用Queryset
 
API使用详解官方文档
 
例下
from hello.models import *
pub_list = Publisher.objects.all()
type(pub_list) #返回类型为Qeuryset
 
QuerySet的特点
1)可遍历,
for pub in pub_list:
    print(pub)     
2)可切片
pub_list[:1]
 
 
常见的查询相关的API
1)get(**kwargs):返回于所有筛选条件相匹配的对象,返回结果只有一个。如果符合条件的对象超过一个,就抛出MultipleObjectsReturn异常,如果没找到符合条件的对象,抛出DoesNotExist异常。
 
注意它返回的不是QuerySet对象,而是models的对象,比如pub=Publisher.object.get(id=1)
type(pub)返回结果为class 'hello.models.Publisher'
 
2)all(): 查询所有结果
3)filter(**kwargs):包含与所筛选条件相匹配的对象,结果可有多个
4)exclude(**kwargs):包含那些与所选条件不匹配的对象,和filter相反
5)order_by(*fields):对查询结果排序
6)reverse():对查询结果反向排序
7)distinct():从返回结果中剔除重复记录
8)values(*fields):返回一个ValuesQuerySet, 一个特殊的QuerySet子类,运行后得到的是一个可迭代的字典序列
9)values_list(*fields): 与values()功能一样,只是返回结果是元组序列
10)count():返回数据库中匹配查询(QuerySet)的对象数量
11)first(): 返回第一条记录,等价于[:1][0]
例如Publisher.objects.all().first()
12) last(): 返回最后一个记录,等价于[::-1][0]
13) exists() :如果QuerySet包含数据,就返回True,否则返回False
例如:Publisher.objects.all().exists()
 
 
实例
1. 查询id为1的书籍信息,并只显示书籍名和作者
Book.objects.filter(id=1).value('title','author'), 返回的是字典
2. 查询所有的出版社信息,并按id降序排列,并尝试使用reverse方法进行反向排序
Publisher.objects.all().order_by('-id')或者
Publisher.objects.all().order_by('id').reverse()
3. 查询出版社所在的城市信息,城市信息不要重复
Publisher.objects.all().values('city').distinct()
4.查询城市是北京的出版社,尝试使用exclude方法
 Publisher.objects.filter(city='北京')
Publisher.objects.exclude(city='北京')
5. 查询男作者的数量
AhthorDetail.objects.filter(sex=0).count()
 
 
 
6. 多表查询
 
python manager.py shell
from hello.models import *
 
1)查询作者的所有完整信息
注意authordetail表中没有作者名字,名字在author表中
AuthorDetail.objects.value('sex','email','address','author__name')
author是authordetail表中的外键字段,在外键后面加2个下划线跟上author表中的name属性,就可输出author表中的名字
 
2)查询<<我的祖国>>这本书的作者名字,出版社名字
书和作者是多对多关系
Book.objects.filter(title='我的祖国').values('authors__name')
Book.objects.filter(title='我的祖国').values('publisher__name')
 
3)查询胡大海写了什么书
Book.objects.filter(authors__name='胡大海').values('title')
 
4)查询广东人民出版社出了什么书
Book.objects.filter(publisher__name='广东人民出版社').values('title')
 
5)查询广东人民出版社都有哪些作者出过书
Book.objects.filter(publisher__name='广东人民出版社').values('author__name')
 
 
多表查询技巧
1. 两个下划线可生成连接查询,查询关联的字段信息
2. _set提供了对象访问相关联表数据的方法,使用相关模型的小写名称,下划线和单词set。但是这种方法只能是关键类访问外键类
book = Book.objects.filter(publisher__name='广东人民出版社')
book.authors_set.all() 这种方法会报错
因为authors是Book类中的外键,这样操作行不通
 
正确方法如下,我们有模型Publisher和Book,而Book类中我们通过外键关联到了Publisher。
下面我们定义一个publisher对象表示一个出版社,就可以使用publisher.book_set的方法获取相关联的书籍信息了
 
publisher = Publisher.objects.get(name='广东人民出版社')
publisher.book_set.all().value
 
 
 
7. 聚集查询和分组查询
 
先看QuerySet里的两个函数
1. annotate(*args,**kwargs):可以为QuerySet中的每个对象添加注解。通过计算查询结果中的每个对象所关联的对象集合,得到总值(也可以是平均值等),用于分组查询
2. aggregate(*args, **kwargs): 通过对QuerySet进行计算,返回一个聚合值的字典。aggregate()中的每个参数指定一个包含在字典中的返回值。用于聚合查询
 
一些聚合函数所在位置:django.db.models,举例如下
1. Avg: 返回所给字段平均值
2. Count:根据所给的关联字段返回被关联model的数量
3. Max: 返回所给字段的最大值
4. Min:返回所给字段的最小值
5. Sum:计算所给字段值总和
 
实例
1. 在Book模型中增加一个price属性
price = models.DecimalField(max_digits=5, decimal_places=2, default=10)
 
2. 查询广东人民出版社出了多少本书
Publisher.objects.filter(name='广东人民出版社').count() #注意count是小写, 是QuerySet提供的一个方法
 
如果使用聚合函数,如下
from django.db.models import *
Publisher.objects.filter(name='广东人民出版社').aggregate(Count('name'))
可以自定义个别名
Publisher.objects.filter(name='广东人民出版社').aggregate(mycount = Count('name'))
 
3. 查询胡大海出的书的总价格是多少
Book.objects.filter(authors__name = '胡大海').aggregate(Sum('price'))
 
4. 查询各作者出书的总价格是多少, 需要进行分组
Book.objects.values('authors__name').annotate(Sum('price'))
其中values()可以当做分组条件,annotate()用于分组查询
 
5. 查询各出版社最便宜的书价
Book.objects.values('publisher__name').annotate(Min('price'))
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/regit/p/9243452.html
今日推荐