博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django
阅读量:5147 次
发布时间:2019-06-13

本文共 34757 字,大约阅读时间需要 115 分钟。

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

 

基本配置

 

一、创建django程序

  • 终端命令:django-admin startproject sitename
  • IDE创建Django程序时,本质上都是自动执行上述命令

其他常用命令:

  python manage.py runserver 0.0.0.0  //运行服务

  python manage.py startapp appname  //创建app实例
  python manage.py syncdb      // 会创建在settings 下的INSTALL_APPS所有app,创建其对应的数据表到指定的数据库,但只创建 不存在的表
  python manage.py makemigrations  //在migrations文件夹创建对应的表数据,但没有在数据库中创建相应数据。
  python manage.py migrate      //将migrations文件夹创建的表数据迁移到数据库并创建相应字段等。

  python manage.py createsuperuser  //创建admin用户

 

配置数据库:

 

DATABASES
=
{
    
'default'
: {
    
'ENGINE'
:
'django.db.backends.mysql'
,
    
'NAME'
:
'dbname'
,
    
'USER'
:
'root'
,
    
'PASSWORD'
:
'xxx'
,
    
'HOST'
: '',
    
'PORT'
: '',
    
}
}
 
模板:
TEMPLATE_DIRS
=
(
        
os.path.join(BASE_DIR,
'templates'
),
    
)
 
静态文件:
STATICFILES_DIRS
=
(
        
os.path.join(BASE_DIR,
'static'
),
    
)

 

路由系统

1、单一路由对应

  url(r'^index$', views.index),

 

2、基于正则的路由

  url(r
'^index/(\d*)'
, views.index),
  url(r
'^manage/(?P<name>\w*)/(?P<id>\d*)'
, views.manage),
 
3、添加额外的参数
  
url(r
'^manage/(?P<name>\w*)'
, views.manage,{
'id'
:
333
}),
 
4、为路由映射设置名称
  url(r
'^home'
, views.home, name
=
'h1'
),
  url(r
'^index/(\d*)'
, views.index, name
=
'h2'
),
 
5、根据app对路由规则进行分类
  url(r
'^web/'
,include(
'web.urls'
)),
 
6、命名空间
  a. project.urls.py    
    from
django.conf.urls
import
url,include
 
    urlpatterns
=
[
        
url(r
'^a/'
, include(
'app01.urls'
, namespace
=
'author-polls'
)),
        
url(r
'^b/'
, include(
'app01.urls'
, namespace
=
'publisher-polls'
)),
    ]
b. app01.urls.py
  from
django.conf.urls
import
url
  from
app01
import
views
 
  app_name
=
'app01'
  urlpatterns
=
[
      
url(r
'^(?P<pk>\d+)/$'
, views.detail, name
=
'detail'
)
  ]
 
c. app01.views.py
  def
detail(request, pk):
    
print
(request.resolver_match)
    
return
HttpResponse(pk)
 

以上定义带命名空间的url之后,使用name生成URL时候,应该如下:

  • v = reverse('app01:detail', kwargs={'pk':11})
  • {% url 'app01:detail' pk=12 pp=99 %}

django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

自定义simple_tag

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py

1 #!/usr/bin/env python 2 #coding:utf-8 3 from django import template 4 from django.utils.safestring import mark_safe 5     6 register = template.Library() 7     8 @register.simple_tag 9 def my_simple_time(v1,v2,v3):10     return  v1 + v2 + v311    12 @register.simple_tag13 def my_input(id,arg):14     result = "" %(id,arg,)15     return mark_safe(result)
View Code

c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名

  {
%
load xx
%
}
d、使用simple_tag
  {
%
my_simple_time
1
2
3
%
}
  {
%
my_input
'id_username'
'hide'
%
}
 
e、在settings中配置当前app,不然django无法找到自定义的simple_tag
 

中间件

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

中间件中可以定义四个方法,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_template_response(self,request,response)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

自定义中间件

1、创建中间件类

class
RequestExeute(
object
):
      
    
def
process_request(
self
,request):
        
pass
    
def
process_view(
self
, request, callback, callback_args, callback_kwargs):
        
i
=
1
        
pass
    
def
process_exception(
self
, request, exception):
        
pass
      
    
def
process_response(
self
, request, response):
        
return
response
2、注册中间件
MIDDLEWARE_CLASSES
=
(
    
'django.contrib.sessions.middleware.SessionMiddleware'
,
    
'django.middleware.common.CommonMiddleware'
,
    
'django.middleware.csrf.CsrfViewMiddleware'
,
    
'django.contrib.auth.middleware.AuthenticationMiddleware'
,
    
'django.contrib.auth.middleware.SessionAuthenticationMiddleware'
,
    
'django.contrib.messages.middleware.MessageMiddleware'
,
    
'django.middleware.clickjacking.XFrameOptionsMiddleware'
,
    
'wupeiqi.middleware.auth.RequestExeute'
,
)
 

admin

  • 配置url
  • 注册和配置django admin后台管理页面

1、创建后台管理员

1
python manage.py createsuperuser

2、配置后台管理url

1
url(r
'^admin/'
, include(admin.site.urls))

3、注册和配置django admin 后台管理页面

a、在admin中执行如下配置

 

from
django.contrib
import
admin
  
from
app01
import 
models
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
 
b、设置数据表名称
class
UserType(models.Model):
    
name
=
models.CharField(max_length
=
50
)
  
    
class
Meta:
        
verbose_name
=
'用户类型'
        
verbose_name_plural
=
'用户类型'
 
c、打开表之后,设定默认显示,需要在model中作如下配置
class
UserType(models.Model):
    
name
=
models.CharField(max_length
=
50
)
  
    
def
__unicode__(
self
):
        
return
self
.name
 
---------------
from
django.contrib
import
admin
  
from
app01
import 
models
  
class
UserInfoAdmin(admin.ModelAdmin):
    
list_display
=
(
'username'
,
'password'
,
'email'
)
  
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
 
d、为数据表添加搜索功能  
1 from django.contrib import admin 2    3 from app01 import  models 4    5 class UserInfoAdmin(admin.ModelAdmin): 6     list_display = ('username', 'password', 'email') 7     search_fields = ('username', 'email') 8    9 admin.site.register(models.UserType)10 admin.site.register(models.UserInfo,UserInfoAdmin)11 admin.site.register(models.UserGroup)12 admin.site.register(models.Asset)
View Code

e、添加快速过滤

1 from django.contrib import admin 2    3 from app01 import  models 4    5 class UserInfoAdmin(admin.ModelAdmin): 6     list_display = ('username', 'password', 'email') 7     search_fields = ('username', 'email') 8     list_filter = ('username', 'email') 9       10   11   12 admin.site.register(models.UserType)13 admin.site.register(models.UserInfo,UserInfoAdmin)14 admin.site.register(models.UserGroup)15 admin.site.register(models.Asset)
View Code

 

 

Model

到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞:

  • 创建数据库,设计表结构和字段
  • 使用 MySQLdb 来连接数据库,并编写数据访问层代码
  • 业务逻辑层去调用数据访问层执行数据库操作
  • 1 import MySQLdb 2   3 def GetList(sql): 4     db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost') 5     cursor = db.cursor() 6     cursor.execute(sql) 7     data = cursor.fetchall() 8     db.close() 9     return data10  11 def GetSingle(sql):12     db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')13     cursor = db.cursor()14     cursor.execute(sql)15     data = cursor.fetchone()16     db.close()17     return data
    View Code

django为使用一种新的方式,即:关系对象映射(Object Relational Mapping,简称ORM)。

  PHP:activerecord

  Java:Hibernate 

    C#:Entity Framework

django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表。

 

一、创建表

1、基本结构

  

1 from django.db import models2    3 class userinfo(models.Model):4     name = models.CharField(max_length=30)5     email = models.EmailField()6     memo = models.TextField()
1 AutoField(Field)  2         - int自增列,必须填入参数 primary_key=True  3   4     BigAutoField(AutoField)  5         - bigint自增列,必须填入参数 primary_key=True  6   7         注:当model中如果没有自增列,则自动会创建一个列名为id的列  8         from django.db import models  9  10         class UserInfo(models.Model): 11             # 自动创建一个列名为id的且为自增的整数列 12             username = models.CharField(max_length=32) 13  14         class Group(models.Model): 15             # 自定义自增列 16             nid = models.AutoField(primary_key=True) 17             name = models.CharField(max_length=32) 18  19     SmallIntegerField(IntegerField): 20         - 小整数 -32768 ~ 32767 21  22     PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 23         - 正小整数 0 ~ 32767 24     IntegerField(Field) 25         - 整数列(有符号的) -2147483648 ~ 2147483647 26  27     PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) 28         - 正整数 0 ~ 2147483647 29  30     BigIntegerField(IntegerField): 31         - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807 32  33     自定义无符号整数字段 34  35         class UnsignedIntegerField(models.IntegerField): 36             def db_type(self, connection): 37                 return 'integer UNSIGNED' 38  39         PS: 返回值为字段在数据库中的属性,Django字段默认的值为: 40             'AutoField': 'integer AUTO_INCREMENT', 41             'BigAutoField': 'bigint AUTO_INCREMENT', 42             'BinaryField': 'longblob', 43             'BooleanField': 'bool', 44             'CharField': 'varchar(%(max_length)s)', 45             'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 46             'DateField': 'date', 47             'DateTimeField': 'datetime', 48             'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 49             'DurationField': 'bigint', 50             'FileField': 'varchar(%(max_length)s)', 51             'FilePathField': 'varchar(%(max_length)s)', 52             'FloatField': 'double precision', 53             'IntegerField': 'integer', 54             'BigIntegerField': 'bigint', 55             'IPAddressField': 'char(15)', 56             'GenericIPAddressField': 'char(39)', 57             'NullBooleanField': 'bool', 58             'OneToOneField': 'integer', 59             'PositiveIntegerField': 'integer UNSIGNED', 60             'PositiveSmallIntegerField': 'smallint UNSIGNED', 61             'SlugField': 'varchar(%(max_length)s)', 62             'SmallIntegerField': 'smallint', 63             'TextField': 'longtext', 64             'TimeField': 'time', 65             'UUIDField': 'char(32)', 66  67     BooleanField(Field) 68         - 布尔值类型 69  70     NullBooleanField(Field): 71         - 可以为空的布尔值 72  73     CharField(Field) 74         - 字符类型 75         - 必须提供max_length参数, max_length表示字符长度 76  77     TextField(Field) 78         - 文本类型 79  80     EmailField(CharField): 81         - 字符串类型,Django Admin以及ModelForm中提供验证机制 82  83     IPAddressField(Field) 84         - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制 85  86     GenericIPAddressField(Field) 87         - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6 88         - 参数: 89             protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6" 90             unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both" 91  92     URLField(CharField) 93         - 字符串类型,Django Admin以及ModelForm中提供验证 URL 94  95     SlugField(CharField) 96         - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号) 97  98     CommaSeparatedIntegerField(CharField) 99         - 字符串类型,格式必须为逗号分割的数字100 101     UUIDField(Field)102         - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证103 104     FilePathField(Field)105         - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能106         - 参数:107                 path,                      文件夹路径108                 match=None,                正则匹配109                 recursive=False,           递归下面的文件夹110                 allow_files=True,          允许文件111                 allow_folders=False,       允许文件夹112 113     FileField(Field)114         - 字符串,路径保存在数据库,文件上传到指定目录115         - 参数:116             upload_to = ""      上传文件的保存路径117             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage118 119     ImageField(FileField)120         - 字符串,路径保存在数据库,文件上传到指定目录121         - 参数:122             upload_to = ""      上传文件的保存路径123             storage = None      存储组件,默认django.core.files.storage.FileSystemStorage124             width_field=None,   上传图片的高度保存的数据库字段名(字符串)125             height_field=None   上传图片的宽度保存的数据库字段名(字符串)126 127     DateTimeField(DateField)128         - 日期+时间格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]129 130     DateField(DateTimeCheckMixin, Field)131         - 日期格式      YYYY-MM-DD132 133     TimeField(DateTimeCheckMixin, Field)134         - 时间格式      HH:MM[:ss[.uuuuuu]]135 136     DurationField(Field)137         - 长整数,时间间隔,数据库中按照bigint存储,ORM中获取的值为datetime.timedelta类型138 139     FloatField(Field)140         - 浮点型141 142     DecimalField(Field)143         - 10进制小数144         - 参数:145             max_digits,小数总长度146             decimal_places,小数位长度147 148     BinaryField(Field)149         - 二进制类型150 151 字段
字段
1 null                数据库中字段是否可以为空 2     db_column           数据库中字段的列名 3     db_tablespace 4     default             数据库中字段的默认值 5     primary_key         数据库中字段是否为主键 6     db_index            数据库中字段是否可以建立索引 7     unique              数据库中字段是否可以建立唯一索引 8     unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引 9     unique_for_month    数据库中字段【月】部分是否可以建立唯一索引10     unique_for_year     数据库中字段【年】部分是否可以建立唯一索引11 12     verbose_name        Admin中显示的字段名称13     blank               Admin中是否允许用户输入为空14     editable            Admin中是否可以编辑15     help_text           Admin中该字段的提示信息16     choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作17                         如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)18 19     error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;20                         字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date21                         如:{
'null': "不能为空.", 'invalid': '格式错误'}22 23 validators 自定义错误验证(列表类型),从而定制想要的验证规则24 from django.core.validators import RegexValidator25 from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\26 MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator27 如:28 test = models.CharField(29 max_length=32,30 error_messages={31 'c1': '优先错信息1',32 'c2': '优先错信息2',33 'c3': '优先错信息3',34 },35 validators=[36 RegexValidator(regex='root_\d+', message='错误了', code='c1'),37 RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),38 EmailValidator(message='又错误了', code='c3'), ]39 )40 41 参数
参数
1 class UserInfo(models.Model): 2         nid = models.AutoField(primary_key=True) 3         username = models.CharField(max_length=32) 4         class Meta: 5             # 数据库中生成的表名称 默认 app名称 + 下划线 + 类名 6             db_table = "table_name" 7  8             # 联合索引 9             index_together = [10                 ("pub_date", "deadline"),11             ]12 13             # 联合唯一索引14             unique_together = (("driver", "restaurant"),)15 16             # admin中显示的表名称17             verbose_name18 19             # verbose_name加s20             verbose_name_plural21         22     更多:https://docs.djangoproject.com/en/1.10/ref/models/options/23 24 元信息
元信息
1 1.触发Model中的验证和错误提示有两种方式: 2         a. Django Admin中的错误信息会优先根据Admiin内部的ModelForm错误信息提示,如果都成功,才来检查Model的字段并显示指定错误信息 3         b. 调用Model对象的 clean_fields 方法,如: 4             # models.py 5             class UserInfo(models.Model): 6                 nid = models.AutoField(primary_key=True) 7                 username = models.CharField(max_length=32) 8  9                 email = models.EmailField(error_messages={
'invalid': '格式错了.'})10 11 # views.py12 def index(request):13 obj = models.UserInfo(username='11234', email='uu')14 try:15 print(obj.clean_fields())16 except Exception as e:17 print(e)18 return HttpResponse('ok')19 20 # Model的clean方法是一个钩子,可用于定制操作,如:上述的异常处理。21 22 2.Admin中修改错误提示23 # admin.py24 from django.contrib import admin25 from model_club import models26 from django import forms27 28 29 class UserInfoForm(forms.ModelForm):30 username = forms.CharField(error_messages={
'required': '用户名不能为空.'})31 email = forms.EmailField(error_messages={
'invalid': '邮箱格式错误.'})32 age = forms.IntegerField(initial=1, error_messages={
'required': '请输入数值.', 'invalid': '年龄必须为数值.'})33 34 class Meta:35 model = models.UserInfo36 # fields = ('username',)37 fields = "__all__"38 39 40 class UserInfoAdmin(admin.ModelAdmin):41 form = UserInfoForm42 43 44 admin.site.register(models.UserInfo, UserInfoAdmin)45 46 拓展知识
拓展

 

表操作:

1 # 增 2     # 3     # models.Tb1.objects.create(c1='xx', c2='oo')  增加一条数据,可以接受字典类型数据 **kwargs 4  5     # obj = models.Tb1(c1='xx', c2='oo') 6     # obj.save() 7  8     # 查 9     #10     # models.Tb1.objects.get(id=123)         # 获取单条数据,不存在则报错(不建议)11     # models.Tb1.objects.all()               # 获取全部12     # models.Tb1.objects.filter(name='seven') # 获取指定条件的数据13 14     # 删15     #16     # models.Tb1.objects.filter(name='seven').delete() # 删除指定条件的数据17 18     # 改19     # models.Tb1.objects.filter(name='seven').update(gender='0')  # 将指定条件的数据更新,均支持 **kwargs20     # obj = models.Tb1.objects.get(id=1)21     # obj.c1 = '111'22     # obj.save()                                                 # 修改单条数据23 24 基本操作
View Code

进阶操作(了不起的双下划线)

利用双下划线将字段和对应的操作连接起来

# 获取个数        #        # models.Tb1.objects.filter(name='seven').count()        # 大于,小于        #        # models.Tb1.objects.filter(id__gt=1)              # 获取id大于1的值        # models.Tb1.objects.filter(id__gte=1)              # 获取id大于等于1的值        # models.Tb1.objects.filter(id__lt=10)             # 获取id小于10的值        # models.Tb1.objects.filter(id__lte=10)             # 获取id小于10的值        # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值        # in        #        # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据        # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in        # isnull        # Entry.objects.filter(pub_date__isnull=True)        # contains        #        # models.Tb1.objects.filter(name__contains="ven")        # models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感        # models.Tb1.objects.exclude(name__icontains="ven")        # range        #        # models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and        # 其他类似        #        # startswith,istartswith, endswith, iendswith,        # order by        #        # models.Tb1.objects.filter(name='seven').order_by('id')    # asc        # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc        # group by        #        # from django.db.models import Count, Min, Max, Sum        # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))        # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"        # limit 、offset        #        # models.Tb1.objects.all()[10:20]        # regex正则匹配,iregex 不区分大小写        #        # Entry.objects.get(title__regex=r'^(An?|The) +')        # Entry.objects.get(title__iregex=r'^(an?|the) +')        # date        #        # Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))        # Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))        # year        #        # Entry.objects.filter(pub_date__year=2005)        # Entry.objects.filter(pub_date__year__gte=2005)        # month        #        # Entry.objects.filter(pub_date__month=12)        # Entry.objects.filter(pub_date__month__gte=6)        # day        #        # Entry.objects.filter(pub_date__day=3)        # Entry.objects.filter(pub_date__day__gte=3)        # week_day        #        # Entry.objects.filter(pub_date__week_day=2)        # Entry.objects.filter(pub_date__week_day__gte=2)        # hour        #        # Event.objects.filter(timestamp__hour=23)        # Event.objects.filter(time__hour=5)        # Event.objects.filter(timestamp__hour__gte=12)        # minute        #        # Event.objects.filter(timestamp__minute=29)        # Event.objects.filter(time__minute=46)        # Event.objects.filter(timestamp__minute__gte=29)        # second        #        # Event.objects.filter(timestamp__second=31)        # Event.objects.filter(time__second=2)        # Event.objects.filter(timestamp__second__gte=31)进阶操作
View Code

连表操作(了不起的双下划线)

利用双下划线和 _set 将表之间的操作连接起来

1 class UserProfile(models.Model): 2     user_info = models.OneToOneField('UserInfo') 3     username = models.CharField(max_length=64) 4     password = models.CharField(max_length=64) 5  6     def __unicode__(self): 7         return self.username 8  9 10 class UserInfo(models.Model):11     user_type_choice = (12         (0, u'普通用户'),13         (1, u'高级用户'),14     )15     user_type = models.IntegerField(choices=user_type_choice)16     name = models.CharField(max_length=32)17     email = models.CharField(max_length=32)18     address = models.CharField(max_length=128)19 20     def __unicode__(self):21         return self.name22 23 24 class UserGroup(models.Model):25 26     caption = models.CharField(max_length=64)27 28     user_info = models.ManyToManyField('UserInfo')29 30     def __unicode__(self):31         return self.caption32 33 34 class Host(models.Model):35     hostname = models.CharField(max_length=64)36     ip = models.GenericIPAddressField()37     user_group = models.ForeignKey('UserGroup')38 39     def __unicode__(self):40         return self.hostname41 42 表结构实例
View Code

 

模型的常用字段类型以及参数:

1 # AutoField  2 # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自动主键字段)  3 # BooleanField  4 # A true/false field. admin 用 checkbox 来表示此类字段.  5 # CharField  6 # 字符串字段, 用于较短的字符串.  7 #   8 # 如果要保存大量文本, 使用 TextField.  9 #  10 # admin 用一个  来表示此类字段 (单行输入). 11 #  12 # CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数. 13 #  14 # CommaSeparatedIntegerField 15 # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有 maxlength 参数. 16 # DateField 17 # 一个日期字段. 共有下列额外的可选参数: 18 #  19 # Argument    描述 20 # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳. 21 # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间. 22 # admin 用一个文本框  来表示该字段数据(附带一个 JavaScript 日历和一个"Today"快键. 23 #  24 # DateTimeField 25 #  一个日期时间字段. 类似 DateField 支持同样的附加选项. 26 # admin 用两上文本框  表示该字段顺序(附带JavaScript shortcuts).  27 #  28 # EmailField 29 # 一个带有检查 Email 合法性的 CharField,不接受 maxlength 参数. 30 # FileField 31 # 一个文件上传字段. 32 #  33 # 要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime formatting, 该格式将被上载文件的 date/time 替换(so that uploaded files don't fill up the given directory). 34 #  35 # admin 用一个````部件表示该字段保存的数据(一个文件上传部件) . 36 #  37 # 在一个 model 中使用 FileField 或 ImageField 需要以下步骤: 38 #  39 # 在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. (出于性能考虑,这些文件并不保存到数据库.) 定义 MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 WEB 服务器用户帐号是可写的. 40 # 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django 使用 MEDIA_ROOT 的哪个子目录保存上传文件. 41 # 你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 出于习惯你一定很想使用 Django 提供的 get_
_url 函数.举例来说,如果你的 ImageField 叫作 mug_shot, 你就可以在模板中以 {
{ object.get_mug_shot_url }} 这样的方式得到图像的绝对路径. 42 # FilePathField 43 # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的. 44 # 45 # 参数 描述 46 # path 必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. Example: "/home/images". 47 # match 可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名. 注意这个正则表达式只会应用到 base filename 而不是路径全名. Example: "foo.*\.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif. 48 # recursive 可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录. 49 # 这三个参数可以同时使用. 50 # 51 # 我已经告诉过你 match 仅应用于 base filename, 而不是路径全名. 那么,这个例子: 52 # 53 # FilePathField(path="/home/images", match="foo.*", recursive=True) 54 # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif 55 # 56 # FloatField 57 # 一个浮点数. 必须 提供两个 参数: 58 # 59 # 参数 描述 60 # max_digits 总位数(不包括小数点和符号) 61 # decimal_places 小数位数 62 # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段: 63 # 64 # models.FloatField(..., max_digits=5, decimal_places=2) 65 # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义: 66 # 67 # models.FloatField(..., max_digits=19, decimal_places=10) 68 # admin 用一个文本框(
)表示该字段保存的数据. 69 # 70 # ImageField 71 # 类似 FileField, 不过要校验上传对象是否是一个合法图片.它有两个可选参数:height_field 和 width_field,如果提供这两个参数,则图片将按提供的高度和宽度规格保存. 72 # 73 # 该字段要求 Python Imaging Library. 74 # 75 # IntegerField 76 # 用于保存一个整数. 77 # 78 # admin 用一个``
``表示该字段保存的数据(一个单行编辑框) 79 # 80 # IPAddressField 81 # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30"). 82 # 83 # admin 用一个``
``表示该字段保存的数据(一个单行编辑框) 84 # 85 # NullBooleanField 86 # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项. 87 # 88 # admin 用一个选择框
``表示 SlugField 字段数据(一个单行编辑框) 109 # 110 # SmallIntegerField111 # 类似 IntegerField, 不过只允许某个取值范围内的整数.(依赖数据库)112 # 113 # TextField114 # 一个容量很大的文本字段.115 # 116 # admin 用一个
文本框表示该字段保存的数据(附加一些JavaScript shortcuts).122 # 123 # URLField124 # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在(即URL是否被有效装入且没有返回404响应).125 # 126 # admin 用一个
文本框表示该字段保存的数据(一个单行编辑框)127 # 128 # USStateField129 # 一个两字母的美国州名缩写.130 # 131 # admin 用一个
文本框表示该字段保存的数据(一个单行编辑框)132 # 133 # XMLField134 # 一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema 的文件系统路径.
View Code

模型类的定义(二)    

一  定义数据模型的扩展属性

     通过内部类Meta给数据模型类增加扩展属性:

     class Meta:

             verbose_name='名称'      #表名由英文转换成中文了

             verbose_name_plural='名称复数形式'

             ordering='排序字段'  

 

二  定义模型方法

    定义模型方法和定义普通python类方法没有太大的差别,定义模型方法可以将当前对应的数据组装成具体的业务逻辑。

     示例:定义__str__()让对象有一个名字

     def __str__(self):

           return self.name

 

4.3 ORM常用操作

4.3.1 增加

    create和save方法

实例:

 

1 >>> from app01.models import * 2 >>> Author.objects.create(name='Alvin') 3 
4 >>> AuthorDetail.objects.create(sex=False,email='916852314@qq.com',address='bejing',birthday='1995-3-16',author_id=1) 5
6 >>> pub=Publisher() 7 >>> pub.name='河大出版社' 8 >>> pub.address='保定' 9 >>> pub.city='保定'10 >>> pub.state_province='河北'11 >>> pub.country='China'12 >>> pub.website='http://www.beida.com'13 >>> pub.save()
View Code

 

注意:如果每次创建一个对象,想显示对应的raw sql,需要在settings加上日志记录部分:

1 LOGGING = { 2 #     'version': 1, 3 #     'disable_existing_loggers': False, 4 #     'handlers': {
5 # 'console':{
6 # 'level':'DEBUG', 7 # 'class':'logging.StreamHandler', 8 # }, 9 # },10 # 'loggers': {
11 # 'django.db.backends': {
12 # 'handlers': ['console'],13 # 'propagate': True,14 # 'level':'DEBUG',15 # },16 # }17 # }
View Code

那么如何插入存在外键和多对多关系的一本书的信息呢?

1 >>> Book.objects.create(title='php',publisher=pub,publication_date='2017-7-7')2 
3 >>> author1=Author.objects.get(id=1)4 >>> author2=Author.objects.get(name='alvin')5 >>> book=Book.objects.get(id=1)6 >>> book.authors.add(author1,author1)7 >>> book.authors.add(author1,author2)8 9 对应代码
View Code

        

     

     

     

 总结:

      1   objects:   model默认管理器。

      2   插入主外键关系的时候,可以用对象的方式,也可以用关联id的方式。

      3   插入多对多关系的时候要分步操作。

      4   create是管理器objects的方法

           save是model对象的方法

 

4.3.2 修改

    update和save方法

实例:

>>> author=Author.objects.get(id=2)>>> author.name='tenglan'>>> author.save()>>> Publisher.objects.filter(id=2).update(name='American publisher')

注意:<1>不能用get的原因是:update是QuerySet对象的方法,get返回的是一个model对象,它没有update方法,而filter返回的是一个QuerySet对象。

         <2>  filter:

1
2
>>> Publisher.objects.
filter
(name__contains
=
"press"
)
[   <Publisher: Apress>]

 在 name 和 contains 之间有双下划线。和Python一样,Django也使用双下划线来表明会进行一些魔术般的操作。这里,contains部分会被Django翻译成LIKE语句:

1
2
3
SELECT
id
, name, address, city, state_province, country, website
FROM books_publisher
WHERE name LIKE
'%press%'
;

其他的一些查找类型有:icontains(大小写不敏感的LIKE),startswithendswith, 还有range     

     <3> 在“插入和更新数据”小节中,我们有提到模型的save()方法,这个方法会更新一行里的所有列。 而某些情况下,我们只需要更新行里的某几列。例如说我们现在想要将Apress Publisher的名称由原来的”Apress”更改为”Apress Publishing”。若使用save()方法,如:

1
2
3
>>> p
=
Publisher.objects.get(name
=
'Apress'
)
>>> p.name
=
'Apress Publishing'
>>> p.save()

  这等同于如下SQL语句:

1
2
3
4
5
6
7
8
9
10
11
12
SELECT
id
, name, address, city, state_province, country, website
FROM books_publisher
WHERE name
=
'Apress'
;
  
UPDATE books_publisher
SET
    
name
=
'Apress Publishing'
,
    
address
=
'2855 Telegraph Ave.'
,
    
city
=
'Berkeley'
,
    
state_province
=
'CA'
,
    
country
=
'U.S.A.'
,
    
website
=
'http://www.apress.com'
WHERE
id
=
52
;

  注意在这里我们假设Apress的ID为52)

在这个例子里我们可以看到Django的save()方法更新了不仅仅是name列的值,还有更新了所有的列。 若name以外的列有可能会被其他的进程所改动的情况下,只更改name列显然是更加明智的。 更改某一指定的列,我们可以调用结果集(QuerySet)对象的update()方法: 示例如下:

1
>>> Publisher.objects.
filter
(
id
=
52
).update(name
=
'Apress Publishing'
)

  与之等同的SQL语句变得更高效,并且不会引起竞态条件。

1
2
3
UPDATE books_publisher
SET
name
=
'Apress Publishing'
WHERE
id
=
52
;

  update()方法对于任何结果集(QuerySet)均有效,这意味着你可以同时更新多条记录。 以下示例演示如何将所有Publisher的country字段值由’U.S.A’更改为’USA’:

1
2
>>> Publisher.objects.
all
().update(country
=
'USA'
)
2

  update()方法会返回一个整型数值,表示受影响的记录条数。 在上面的例子中,这个值是2。

 

4.3.3  查询 

>>> Publisher.objects.all()

[<Publisher: 中国机械出版社>, <Publisher: American publisher>]

注意:

这相当于这个SQL语句:

1
2
SELECT
id
, name, address, city, state_province, country, website
FROM books_publisher;

注意到Django在选择所有数据时并没有使用 SELECT* ,而是显式列出了所有字段。

惰性机制:

所谓惰性机制:Publisher.objects.all()只是返回了一个QuerySet(查询结果集对象),并不会马上执行sql,而是当调用QuerySet的时候才执行。

QuerySet特点:

       1   可迭代的

       2   可切片

一  查询相关API:

 <1>get(**kwargs):        返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。

 <2>all():                       查询所有结果

 <3>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象

 <4>exclude(**kwargs):  它包含了与所给筛选条件不匹配的对象

 <5>order_by(*field):      对查询结果排序

 <6>reverse():                对查询结果反向排序

 <7>distinct():                从返回结果中剔除重复纪录

 <8>values(*field):         返回一个ValueQuerySet——一个特殊的QuerySet,运行后得到的并不是一

                                     系列 model的实例化对象,而是一个可迭代的字典序列

 <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列

 <10>count():                返回数据库中匹配查询(QuerySet)的对象数量。

<11>first():                   返回第一条记录,等价于[:1][0]

<12>last():                   返回最后一条记录,等价于[::1][0]

 <13>exists():               如果QuerySet包含数据,就返回True,否则返回False。

实例:

      1   查询id为2的书籍信息,并只显示书籍名称和出版日期          

>>> Book.objects.filter(id=2).values("title","publication_date")        [{
'title': 'python Gone', 'publication_date': datetime.date(2019, 5, 24)}]

 

       2   查询所有的出版信息,并按id降序排列,并尝试使用reverse方法进行反向排序。     

>>> Publisher.objects.all().order_by("id")        [
,
,
]>>> Publisher.objects.all().order_by("id").reverse() [
,
,
] >>> Publisher.objects.all().order_by("-id") [
,
,
]

  3    查询出版社所在的城市信息,城市信息不要重复      

>>> Publisher.objects.all().values("city").distinct()        [{
'city': '北京'}, {
'city': 'beijing'}]

4    查询城市是北京的出版社,尝试使用exclude方法  

>>> Publisher.objects.all().filter(city='beijing')        [
]

  5    查询男作者的数量       

>>> AuthorDetail.objects.filter(sex=0).count()       1

二 多表关联查询

           1   外键关联查询

                  >>> AuthorDetail.objects.all().values("author")

        [{'author': 1}]

>>> AuthorDetail.objects.all().values("author__name")
        [{'author__name': 'alex'}]

2  多对多关联查询

      >>> Book.objects.all().filter(title='python Gone').values("authors")

        [{'authors': 1}, {'authors': 2}]

>>> Book.objects.all().filter(title='python Gone').values("authors__name")
        [{'authors__name': 'alex'}, {'authors__name': 'alvin'}]

>>> Book.objects.all().filter(authors__name='alex').values('title')

        [{'title': 'python Gone'}]

多表查询技巧:

       __:两个下划线可以生成连接查询,查询关联的字段信息

      _set:提供了对象访问相关联表数据的方法。但是这种方法只能是相关类访问定义了关系的类(主键类访问外键类)

三 聚合查询和分组查询

    1  annotate(*args,**kwargs):可以为QuerySet每一个对象添加注解。可以通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或总和),用于分组查询

    2  aggregate(*args,**kwargs):通过对QuerySet进行计算,返回一个聚合值的字典。

aggregate()中每一个参数都指定一个包含在字典中的返回值。用于聚合查询。

聚合函数(Aggregation Functions)

所在位置:django.db.models

1 Avg:  返回所给字段的平均值

2 Count: 根据所给的关联字段返回被关联的model的数量

3 Max:返回所给字段的最大值

4 Sum:计算所给字段的总和

  为了演示实例,在这里我们给Book增加一个新的price字段:

 

  然后同步数据库:makemigrations, migrate就可以了,这也是django牛逼之处。

 

  另外,创建一些新的书:

 

        

 

  注意,在pycharm的database下创建新的对象,有个bug:

 

        

 

   我现在添入了第六条数据,可是,左上角的row仍然显示5,如果refresh:

 

       

 

   点击yes,添加的数据则会消失。

 

    解决方法:当你创建完一条数据后,点击+按钮,row变成6了,数据自动就提交了,然后再把新创建的空行删除(-)就可以了!

 

    Book对象添加完,还差一个字段:authors,绑定多对多的关系:

 

      

 

    插曲结束,转入正题:

 

           python manage.py shell(重新打开),因为添加了新的字段

 

      

 

           实例:

 

            1   查询中国邮电大学出版社出版了多少本书?           

 

       

 

            2   查询alex出的书总价格                   

 

       

 

            3   查询各个作者出的书的总价格

 

                         这里就涉及到分组了,分组条件是authors__name,

 

            

 

            4   查询各个出版社最便宜的书价是多少

 

       

 

4.3.4  删除

 

      >>> Book.objects.filter(id=1).delete()

 

       (3, {'app01.Book_authors': 2, 'app01.Book': 1})

 

       我们表面上删除了一条信息,实际却删除了三条,因为我们删除的这本书在Book_authors表中有两条相关信息,这种删除方式就是django默认的级联删除。

 

 

参考:

https://www.cnblogs.com/wupeiqi/articles/5237704.html

 

4.3.2 修改

    update和save方法

实例:

转载于:https://www.cnblogs.com/dontgiveup/p/9749162.html

你可能感兴趣的文章
document对象
查看>>
Java知识复习(二)
查看>>
MySQL日期数据类型、时间类型使用总结
查看>>
Linux下修改计算机名
查看>>
linux驱动: 如何向模块传递参数, module_param和module_param_array
查看>>
[转]使用 System.IO 和 Visual C# .NET 读取文本文件
查看>>
ASP.NET事件模型
查看>>
window 常用cmd 命令
查看>>
NSString类-字符串
查看>>
MySql 游标笔记
查看>>
vim 穿越时空
查看>>
如何管理Entity Framework中得事务
查看>>
solrcloud线上创建collection,修改默认配置
查看>>
制作ubuntu16.04 自动安装iso镜像
查看>>
数据清洗
查看>>
我是如何自学Android,资料分享(2015 版)
查看>>
[Application]Ctrl+C终止程序代码
查看>>
for循环小例题
查看>>
C++ Win32 遍历窗口
查看>>
8,16小感
查看>>