Django

安装

直接使用命令安装

pip  install  Django
conda install Django
#这样输命令会直接安装当前最新版
#需要较低版本的话,可以在后面加入版本号
pip  install  Django==2.1
conda install Django==2.15

建立项目

#创建一个项目,XXX是你建立的项目文件夹名
django-admin startproject  XXX
#然后可以进入项目文件夹,运行一下,测试环境是否可用
python  manage.py  runserver
python  manage.py  runserver 8000(端口号)
#建立一个新的app,XXX表示app名字
python  manage.py startapp XXX
#建立app之后需要将app名添加到setting.py中INSTALLED_APPS中

APP使用

app的使用主要是修改appName/views.py和projectName/urls两个文件

定义视图函数

通过编写不同的函数来实现不同的功能,函数第一个参数是request请求,后面的参数可以在url.py

文件中使用,return返回render函数,第一个参数依然是request,后面是返回的页面。

页面存储的位置是appName/templates/XXX,前端文件的位置是固定的。文件夹templates是自己创建的。

'''
定义视图函数
'''
def test(req):
    return render(req,"test.html")

def page(req,pagename):
    return render(req,pagename)

def login(req):
    username = req.GET.get("username",None)
    password = req.GET.get("password",None)
    if username == "test" and password == "test":
        print("success!")
        return render(req,"test.html")
    else:
        return render(req,"login.html")

绑定链接地址

链接地址就是你访问时的url地址,可以使用变量,但是格式是固定的,<str:pagename>

注意需要使用import,将app文件引入

from myapp import views as myviews

urlpatterns = [
    path('admin/', admin.site.urls),
    path('test/',myviews.test),
    path('page/<str:pagename>',myviews.page),
    path('login/',myviews.login),
]

请求方式

get

get请求接受参数不用多余的设置,默认就是可以的

username = req.GET.get("username",None)
password = req.GET.get("password",None)

post

post一般需要一些设置,根据版本不同,设置也不太一样

首先需要设置setting.py 中 APPEND_SLASH=False,如何没有的话需要加上这一句。

另外在请求是需要加上跨域请求。

<form action="/login/" method="post">
			{% csrf_token %} #必须加上这一句
			login: &nbsp; &nbsp; &nbsp; 
			<input type="text" id="username" name="username" /> <br>
			password:
			<input type="password" name="password" /> <br>
			<input type="submit" value="login"/>
</form>

接受参数基本和get相同

 username = req.POST.get("username",None)
 password = req.POST.get("password",None)

响应重定向

响应重定向使用需要引入相应的库文件,redirect中写的是一个URL,而render中参数是req,和templates中的文件。

from django.shortcuts import render,redirect

def testredirect(req):
    return redirect("http://baidu.com")

传递参数时可以采用?name=XXX&pass=XXX这种形式

数据传递

#接受来自前端的数据,分为get和post两种方法
def login(req):
    # username = req.GET.get("username",None)
    # password = req.GET.get("password",None)
    username = req.POST.get("username",None)
    password = req.POST.get("password",None)
    if username == "test" and password == "test":
        print("success!")
        return render(req,"test.html")
    else:
        return render(req,"login.html")

#向前端界面传递参数
def testdata(req):
    context = dict()
    context["name"] = "user"
    context["pass"] = "pass"
    return render(req,"testdata.html",context=context)
#前端接受,采用{{XX}}的方式
{{name}}
{{pass}}

session

session的使用依赖表,所以使用的话需要建立一个表

python manage.py makemigration  #如何已经存在表,则先使用该命令更新
python manage.py migrate  #没有的话可以直接执行这个,建立表

使用session需要的步骤

#添加表,用来支持session
python manage.py migrate

#添加session
def login(req):
    username = req.POST.get("username",None)
    password = req.POST.get("password",None)
    if username == "test" and password == "test":
        req.session['name'] = username   #session对象中存储数据
        print("success!")
        return render(req,"test.html")
    else:
        return render(req,"login.html")
    
#前端获得session
{{request.session.name}}

#在后端获得session
request.session.get("name")

在setting.py中可以修改相应的参数(直接添加到setting)

SESSION_COOKIE_AGE=60*30  #30分钟
SESSION_EXPIRE_AT_BROWSER_CLOSE=TRUE  #浏览器关闭时session失效

模板

### for标签
#列表、集合、元组的循环
{% for us in info %}
{{us}}
{% endfor %}
#字典的循环
{% for key, value in info_dict.items %}
    {{ key }}: {{ value }}
{% endfor %}
##当列表中可能为空值时用 for  empty
{% for athlete in athlete_list %}
    <li>{{ athlete.name }}</li>
{% empty %}
    <li>抱歉,列表为空</li>
{% endfor %}

### 注释
{#  注释  #}

###if标签
{% if var >= 90 %}
成绩优秀,自强学堂你没少去吧!学得不错
{% elif var >= 80 %}
成绩良好
{% elif var >= 70 %}
成绩一般
{% elif var >= 60 %}
需要努力
{% else %}
不及格啊,大哥!多去自强学堂学习啊!
{% endif %}

model

使用

model是用来使用数据库的,要使用需要以下几个步骤

、首先需要我们下载安装数据库,安装数据库相关模块,可以使用命令

pip3 install pymysql
pip3 install mysqlclient

,需要在setting文件中配置数据库

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'PORT':3306,
        'HOST':'127.0.0.1',
        'USER':'ROOT',
        'PASSWORD':'pass',
        'NAME': 'dhango',
    }
}

、需要我们写模型对象

from django.db import models

# Create your models here.
#定义模型对象
class Userinfo(models.Model):
    userid = models.BigIntegerField(primary_key=True)
    name = models.CharField(max_length=50,unique=True)
    password = models.CharField(max_length=30)

    class Meta:
        db_table = 'userinfo'

class orderinfo(models.Model):
    orderID = models.BigIntegerField(primary_key=True)
    orderData = models.DateField(auto_now=True)  #添加数据时,时间默认为系统当前时间 
    orderMon = models.FloatField()
    Userinfo = models.ForeignKey(Userinfo,on_delete=models.CASCADE)  #设置外键关联

    class Meta:
        db_table = 'orderinfo'        


四、创建注册模型对象

python3 manage.py makemigrations

五、创建表

python3 manage.py migrate

创建好之后就应该是这样的

UTOOLS1586764158092.png

常用参数

1、CharField:字符串类型,映射到数据库中会转换成varchar类型,使用时必须传入max_length属性以定义该字符串的最大长度,如果超过254个字符,就不建议使用CharField了,此时建议使用TextField。

2、EmailField:在数据库底层也是一个varchar类型,默认最大长度是254个字符,当然也可以自己传递max_length参数,这个Field在数据库层面不会限制一定要传递符合email条件的字符串,只是以后在使用ModelForm表单验证时,会起作用

3、URLField:类似于CharField,在数据库底层也是一个varchar类型,只不过只能用来存储url格式的字符串。并且默认的max_length是200,同EmailField

4、FloatField:浮点数类型,映射到数据库中会变成double类型

5、IntegerField:整数类型,映射到数据库中会变成11位的int类型

6、BigIntegerField:大整形。值的区间是-9223372036854775808——9223372036854775807

7、PositiveIntegerField:正整形。值的区间是0——2147483647

8、SmallIntegerField:小整形。值的区间是-32768——32767

9、PositiveSmallIntegerField:正小整形。值的区间是0——32767

10、BooleanField:布尔类型(True/False),映射到数据库中会变成长度只有1位的tinyint类型,这个Field不接受null参数,要想使用可以为null的布尔类型的字段,就要使用NullBooleanField

11、AutoField:自增长类型,映射到数据库中是11位的整数,使用此字段时,必须传递primary_key=True,否则在生成迁移脚本文件时,就会报错,一个模型不能有两个自增长字段。一般情况下我们用不到这个字段,如果不定义主键,django会自动的为我们生成id字段作为主键

12、BigAutoField:自增长类型,用法同AutoField。映射到数据库中会成为20位的bigint类型

13、DateTimeField:日期时间类型,在python中对应的是datetime.datetime类型,在映射到数据库中也是datetime类型。使用这个Field可以传递以下几个参数:
    auto_now=True:在每次这个数据保存的时候,都使用当前的时间。比如作为一个记录修改日期的字段
    auto_now_add=True:在每条数据第一次被添加进去的时候,都使用当前的时间。比如作为一个记录第一次入库的字段
    注意:如果在setting.py中配置了USE_TZ=True,那么上两个默认值都来自于django.utils.timezone.now所转化来的值

    在模板中将一个UTC时间转换成本地时间:
    首先模板HTML文件的开头导入tz:
      {% load tz %}
    在传递过来的时间变量utc_time中使用localtime过滤器:
      {{utc_time | localtime}}
    其实,django知道我们的想法,已经为我们做好了配置,我们并不需要配置其他的东西就可以直接使用{{utc_time}},此时只要我们在setting.py文件中设置  USE_TZ=True,TIME_ZONE='Asia/Shanghai',UTC时间变量在渲染到模板上的时候会自动的为我们加载成TIME_ZONE中所设置的时区的时间。

14、DateField:日期类型,用法同DateTimeField,在python中对应的是datetime.date类型,在映射到数据库中是date类型

15、TimeField:时间类型,用法同DateTimeField,在python中对应的是datetime.time类型,在映射到数据库中是time类型

16、FileField:用来存储文件的

17、ImageField:用来存储图片文件的

18、TextField:大量的文本类型

19、**DecimalField**: 一个固定精度的十进制数类型,使用时必须要传递两个参数,max_digits数字的最大总长度(不含小数点),decimal_places小数部分的长度

Field的常用参数:
1、null:标识是否可以为空,默认是为False。在使用字符串相关的Field(CharField/TextField/URLField/EmailField)的时候,官方推荐尽量不要使用这个参数,也就是保持默认值False。因为Django在处理字符串相关的Field的时候,即使这个Field的null=False,如果你没有给这个Field传递任何值,那么Django也会使用一个空的字符串""来作为默认值存储进去。因此如果再使用null=True,Django会产生两种空值的情形(NULL或者空字符串)。如果想要在表单验证的时候允许这个字符串为空,那么建议使用blank=True。如果你的Field是BooleanField,由于BooleanField不接受null参数,因此你如果想要设置这个字段可以为空的bool类型,那么对应的可空的bool类型字段则为NullBooleanField。

2、blank:标识这个字段在表单验证的时候是否可以为空,默认是False。这个和null是有区别的,null是一个纯数据库级别的。而blank是表单验证级别的。

3、db_column:这个字段在数据库中的名字。如果没有设置这个参数,那么将会使用模型中属性的名字。

4、db_index:标识这个字段是否为索引字段。

5、default:默认值。可以为一个值,或者是一个函数,但是不支持lambda表达式。并且不支持列表/字典/集合等可变的数据结构。在用函数作为值传递给default时,只能传递函数名,不需要加括号。

6、primary_key:是否为主键,与AutoField/BigAutoField连用,默认是False。

7、unique:在表中这个字段的值是否唯一,在数据库中就是唯一约束,一般是设置手机号码/邮箱等。

8、choices:在一个范围内选择出一项,注意这个选项与ForeignKey的区别
    作用:1、django admin中显示下拉框;2、避免连表查询

    TYPE_CHOICES = (   #数据库只保存内部元祖的第一个值,后面的值保存在内存中
      (0, '---'),
      (1, '第一类'),
      (2, '第二类'),
      (3, '第三类'),
    )
    type = models.IntegerField(default=0,choices=TYPE_CHOICES)

数据库操作

创建项目

django-admin startproject django_model

创建应用

python manage.py startapp model

  • 配置应用 model, 编辑 django_model/settings.py 文件:
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'model',
]
  • 配置Mysql数据库:编辑 django_model/settings.py 文件, 内容如下:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # mysql数据库引擎
        'NAME': 'my_model',  # 数据库名字
        'USER': 'root',  # 用户名
        'PASSWORD': 'fe_cow',  # 密码
        'HOST': 'localhost',  # 主机
        'PORT': '3306'  # 端口
    }
}
  • 创建应用所需数据库表, 首先我们创建数据库:

    create dababase my_model charset = utf8;

  • 注意: 使用PyMysql数据库驱动,需要在 djangomodel/init_.py 中增加如下代码:(python2不需要配置这项)

    import pymysql
    pymysql.install_as_MySQLdb()

定义模型

  • 定义模型其实就是定义一个python类;一个模型类代表数据库中一张表,一个模型类的实例代表这个数据库表中的一条特定的记录
from django.db import models

class Publisher(models.Model):
    """出版社"""
    name = models.CharField(max_length=30)
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=60)
    country = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name


class Author(models.Model):
    """作家"""
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=40)
    email = models.EmailField()

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)


class Book(models.Model):
    """书"""
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author) # 书和作者是多对多的关系
    publisher = models.ForeignKey(Publisher) # 书和出版者是多对一的关系
    publication_date = models.DateField()

    def __unicode__(self):
        return self.title

  • 定义完模型后,要执行数据库迁移操作:

    先执行python manage.py makemigrations 在执行:python manage.py migrate

  • 一张表中定义了多对多的关系,ORM会自动创建实现多对多关系的第三张表。

数据库的操作

  • 通过python shell 来演示数据库的操作。在终端切换到项目根目录下,输入命令python manage.py shell 进入shell操作环境。

增删改查

1 创建记录

方法一:实例化(调用save()方法之前,Django不会访问数据库;save()方法没有返回值)

>>> from apps.models import Author
>>> author = Author(last_name='fe_cow')
>>> author.save()
>>> print author
 fe_cow

方法二:create() (只用一条语句创建并保存一个对象,使用create()方法。)

>>> Author.objects.create(first_name='fe',last_name='cow', email='280773872@qq.com')

方法三:get_or_create(), 这种方法可以防止重复(速度稍慢,因为会先查数据库), 它返回一个元组。创建成功返回True,失败的话False,不执行创建。

>>> author = Author.objects.get_or_create(last_name='fe_cow')
>>> print author
(<Author:  fe_cow>, False)  # False:说明已经重复 创建失败
>>> author = Author.objects.get_or_create(last_name='cu_cow')
>>> print author
(<Author:  cu_cow>, True)  # True: 创建成功
2 查询记录

方法一:查询所有对象 (all()方法返回包含数据库中所有对象的一个查询集。)

>>> author = Author.objects.all()
>>> print author
<QuerySet [<Author:  fecow>, <Author:  fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author:  cu_cow>]>

方法二:过滤查询 (filter()返回一个新的查询集,它包含满足查询参数的对象。)

>>> author = Author.objects.filter(last_name='cu_cow')
>>> print author
<QuerySet [<Author:  cu_cow>]>

方法三:指定查询 (get查询只能返回一个对象,多了少了都会引发DoesNotExist 异常)

>>> author = Author.objects.get(id=1)
>>> print author
 fecow

方法四:双下划线查询____contains:包含;__icontains不区分大小写;__regex:正则查询;__lt:小于xxx;__lte:小于等于xxx;__gt:大于xxx;__gte:大于等于xxx;__startswith(): 以xxx开头,;__istartswith():不区分大小写以xxx开头, __endswith():以xxx结尾;__iendswith():以xxx结尾不区分大小写

  • 以上使用方法基本上都一致:对象.objects.filter(属性 __xxx) 例子如下:
>>> author = Author.objects.filter(id__gte=2)
>>> print author
<QuerySet [<Author:  fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author:  cu_cow>]>
  • 单独说一个特殊的__in 判断字段在列表内。通常用pk指主键,不限于id,适用更好。
>>> author_list = Author.objects.values_list('id', flat=True)
# 返回的是:<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
>>> Author.objects.filter(pk__in=author)
<QuerySet [<Author:  fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author:  cu_cow>]>

方法五:first(), last()获取查询结果中单个对象

>>> Author.objects.filter(id__gte=2)
# 返回结果:QuerySet集合
<QuerySet [<Author:  fe_cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author: fe cow>, <Author:  cu_cow>]>
>>> Author.objects.filter(id__gte=2).first()
# 返回结果:objects对象  而且返回第一个对象
<Author:  fe_cow>
>>> Author.objects.filter(id__gte=2).last()
<Author:  cu_cow>
# 返回结果:objects对象 而且返回的是最后一个对象

方法六:通过values查询

  • values('字段')用字典形式,返回的是指定字段的查询结果;
>>> Author.objects.values('last_name')
<QuerySet [{'last_name': u'fecow'}, {'last_name': u'fe_cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cow'}, {'last_name': u'cu_cow'}]>
# 返回字典列表;多个字段间以逗号分隔
  • values_list('字典'),返回的也是指定字段的查询结果
>>> Author.objects.values_list('last_name')
<QuerySet [(u'fecow',), (u'fe_cow',), (u'cow',), (u'cow',), (u'cow',), (u'cow',), (u'cu_cow',)]>
# 返回的是元组列表,多个字段也是用逗号分割
  • values_list('字段', flat=True) flat=True :之后返回的是值列表
>>> Author.objects.values_list('id', flat=True)
<QuerySet [1L, 2L, 3L, 4L, 5L, 6L, 7L]>
# 返回的是列表

方法六:exclude(**kwargs)反向过滤

>>> Author.objects.exclude(id__gt=2)
<QuerySet [<Author:  fecow>, <Author:  fe_cow>]>
# 取反

方法七:exists()

>>> Author.objects.filter(id=2).exists()
True
#  QuerySet包含数据返回True
>>> Author.objects.filter(last_name='Au_cow').exists()
False
#  QuerySet不包含数据返回False
3 修改记录

方法一:QuerySet.update('字段'='修改的值')

>>> Author.objects.filter(last_name='cu_cow').update(last_name='Ai_cow')
1L
# 修改的前提是先查找,然后调用update(field=val)方法,只有QuerySet集合对象才能调用该方法,也就是说通过get(), first(), last()获取的对象没有该方法。

方法二:对象赋值

>>> author_obj = Author.objects.filter(last_name='fe_cow').first()
>>> author_obj.last_name = 'Fe_cow'
>>> author_obj.save()
# 不推荐使用,效率低
4 删除记录

调用delete()方法 delete()方法支持QuerySet集合对象的删除,也支持单个对象的删除。

>>> Author.objects.filter(last_name='fe_cow').delete()
(1L, {u'apps.Book_authors': 0L, u'apps.Author': 1L})
# 默认就是级联删除,对应多对多的表也会删除

QuerySet

  • 通过名字我们也能想到从数据库查出来的结果一般是一个集合,哪怕只有一个对象,也叫集合。

QuerySet特性

  • 可以进行切片,也可以进行遍历。
>>> Author.objects.filter(id__gt=2)[:2]  # 使用切片来获取
# <QuerySet [<Author: fe cow>, <Author: fe cow>]>
>>> authors = Author.objects.filter(id__gt=2)  # 使用for循环来获取
>>> for author in authors:
...     print author 
# 打印结果如下
# fe cow 
# fe cow
# fe cow
# fe cow
  • 惰性机制: 只有使用QuerySet时,才会走数据库。像.all() filter()时,并不会真正执行数据库查询,只是翻译了SQL语句;当我们执行if xxx ,print xxx; for xxx in xxx:这些操作才会执行SQL语句,进行数据库查询。
  • 缓存机制:每次执行了数据库查询后,会将结果放在QuerySet的缓存中,下次在使用QuerySet时, 不会走数据库,直接从缓存中拿取数据。比如:
>>> author = Author.objects.all()  # 获取所有Author QuerySet中的 last_name
>>> for res in author:
...     print res.last_name  # Ai_cow  cow

>>> Author.objects.create(last_name='COW',first_name='FE')  # 接下来往数据库中插入一跳数据
>>>for res in author:
        print res.last_name  # Ai_cow  cow   # 发现,已经创建了新的数据,但是表里面没有这条数据
# 以上结果证明了QuerySet缓存的机制,新添加一条记录;打印结果没有发生改变,说明他不会重新走数据库,而是从缓存中获取数据。
>>> author = Author.objects.all()  # 获取所有Author QuerySet中的 last_name
>>> for res in author:
...     print res.last_name  # Ai_cow  cow COW1
posted @ 2020-04-15 21:06  tomyyyyy  阅读(142)  评论(0编辑  收藏  举报