Django入门-5:模型的基本使用2-字段

25 篇文章 1 订阅
24 篇文章 0 订阅

定义属性

  1. 定义属性时,需要字段类型
  2. 字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models
  3. 使用方式
  4. 导入from django.db import models
  5. 通过models.Field创建字段类型的对象,赋值给属性
  6. 对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False

字段类型

  1. AutoField:一个根据实际ID自动增长的IntegerField,通常不指定
  2. 如果不指定,一个主键字段将自动添加到模型中
  3. BooleanFieldtrue/false 字段,此字段的默认表单控制是CheckboxInput
  4. NullBooleanField:支持nulltruefalse三种值
  5. CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
  6. TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
  7. IntegerField:整数
  8. DecimalField(max_digits=None, decimal_places=None):使用pythonDecimal实例表示的十进制浮点数
  9. DecimalField.max_digits:位数总数
  10. DecimalField.decimal_places:小数点后的数字位数
  11. FloatField:用Pythonfloat实例来表示的浮点数
  12. TimeField:使用Python的datetime.time实例表示的时间,参数同DateField
  13. DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
  14. FileField:一个上传文件的字段
  15. ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image
  16. DateField[auto_now=False, auto_now_add=False]):使用Pythondatetime.date实例表示的日期
  • 参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,
  • 它总是使用当前日期,默认为false
  •  
  • 参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,
  • 它总是使用当前日期,默认为false
  •  
  • 该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,
  • 包含了一个额外的invalid_date错误消息键
  •  
  • auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果

字段选项

  • 通过字段选项,可以实现对字段的约束
  • 在字段对象时通过关键字参数指定
  1. db_column:字段的名称,如果未指定,则使用属性的名称
  2. db_index:若值为 True, 则在表中会为此字段创建索引
  3. default:默认值
  4. primary_key:若为 True, 则该字段会成为模型的主键字段
  5. unique如果为 True, 这个字段在表中必须有唯一值
  6. max_length:字段最大的长度
  7. null:如果为TrueDjango 将空值以NULL 存储到数据库中,默认值是 False
  8. blank:如果为True,则该字段允许为空白,默认值是 False

对比null是数据库范畴的概念,blank是表单验证证范畴的

 

关系

关系的类型包括

ForeignKey:一对多,将字段定义在多的端中

ManyToManyField:多对多,将字段定义在两端中

OneToOneField:一对一,将字段定义在任意一端中

可以维护递归的关联关系,使用'self'指定,详见“自关联”

#示例

from django.db import models


# Create your models here.


class BookInfo(models.Model):

btitle = models.CharField(max_length=20)

bpub_date = models.DateTimeField()

def __str__(self):

return "%d" % self.pk



class HeroInfo(models.Model):

hname = models.CharField(max_length=20)

hgender = models.BooleanField()

hcontent = models.CharField(max_length=100)

hBook = models.ForeignKey('BookInfo')

def __str__(self):

return "%d" % self.pk

  • 用一访问多:对象.模型类小写_set

bookinfo.heroinfo_set

  • 用一访问一:对象.模型类小写

heroinfo.bookinfo

  • 访问id:对象.属性_id

heroinfo.book_id

元选项

  • 在模型类中定义类Meta,用于设置元信息
  • 元信息db_table:定义数据表名称,推荐使用小写字母,数据表的默认名称

<app_name>_<model_name>

  • ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表

class BookInfo(models.Model):

...

class Meta():

ordering = ['id']

  • 字符串前加-表示倒序,不加-表示正序

class BookInfo(models.Model):

...

class Meta():

ordering = ['-id']

  • 排序会增加数据库的开销

示例演示

创建test2项目,并创建booktest应用,使用mysql数据库

  • 定义图书模型
class BookInfo(models.Model):

btitle = models.CharField(max_length=20)

bpub_date = models.DateTimeField()

bread = models.IntegerField(default=0)

bcommet = models.IntegerField(default=0)

isDelete = models.BooleanField(default=False)
  • 英雄模型
    class HeroInfo(models.Model):
    
    hname = models.CharField(max_length=20)
    
    hgender = models.BooleanField(default=True)
    
    isDelete = models.BooleanField(default=False)
    
    hcontent = models.CharField(max_length=100)
    
    hbook = models.ForeignKey('BookInfo')

     

  • 定义index、detail视图
# Create your views here.

from django.http import HttpResponse

from django.http import HttpResponseRedirect

from django.template import loader

from django.urls import reverse



from booktest.models import BookInfo





def index(request):

# return HttpResponse("欢迎来到 Django首页!")

booklist = BookInfo.objects.all()

template = loader.get_template('booktest/index.html')

# context = RequestContext(request, {'booklist': booklist})

context = {'booklist': booklist}

return HttpResponse(template.render(context))





def detail(request, id):

# return HttpResponse("DETAIL %s" % id)

book = BookInfo.objects.get(pk=id)

template = loader.get_template('booktest/detail.html')

# context = RequestContext(request, {'book': book})

context = {'book': book}

return HttpResponse(template.render(context))





def add(request):

a = request.GET['a']

b = request.GET['b']

c = int(a) + int(b)

return HttpResponse(str(c))





def add2(request, a, b):

c = int(a) + int(b)

return HttpResponse(str(c))



from django.http import HttpResponseRedirect

from django.core.urlresolvers import reverse # django 1.4.x - django 1.10.x

# from django.urls import reverse # new in django 1.10.x



def old_detail(request, a, ):

return HttpResponseRedirect(

reverse('detail', args=(a))

)
  • index.html、detail.html模板
<!DOCTYPE html>

<html>

<head>

<title>首页</title>

</head>

<body>

<h1>图书列表</h1>

<ul>

{% for book in booklist %}

<li>

{# {% comment %}<a href="{{ book.id }}">{% endcomment %}#}

<a href="{% url 'detail' book.id %}">

{{ book.btitle }}

</a>

</li>

{% endfor %}

</ul>

</body>

</html>

<!DOCTYPE html>

<html>

<head>

<title>详细页</title>

</head>

<body>

<h1>{{ book.btitle }}</h1>

<ul>

{% for hero in book.heroinfo_set.all %}

<li>{{ hero.hname }}---{{ hero.hcontent }}</li>

{% endfor %}

</ul>

</body>

</html>
  • 配置url,能够完成图书及英雄的展示
from django.conf.urls import url, include

from django.contrib import admin



from booktest import views



urlpatterns = [

url(r'^add/$', views.add, name='add'),

url(r'^add/(\d+)/(\d+)/$', views.add2, name='add2'),

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

url(r'^([0-9]+)/$', views.old_detail),

url(r'^book/([0-9]+)/$', views.detail, name="detail"),

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

]

测试数据

  • 模型BookInfo的测试数据
insert into booktest_bookinfo(btitle,bpub_date,bread,bcommet,isDelete) values

('射雕英雄传','1980-5-1',12,34,0),

('天龙八部','1986-7-24',36,40,0),

('笑傲江湖','1995-12-24',20,80,0),

('雪山飞狐','1987-11-11',58,24,0)
  • 模型HeroInfo的测试数据

     

insert into booktest_heroinfo(hname,hgender,hbook_id,hcontent,isDelete) values

('郭靖',1,1,'降龙十八掌',0),

('黄蓉',0,1,'打狗棍法',0),

('黄药师',1,1,'弹指神通',0),

('欧阳锋',1,1,'蛤蟆功',0),

('梅超风',0,1,'九阴白骨爪',0),

('乔峰',1,2,'降龙十八掌',0),

('段誉',1,2,'六脉神剑',0),

('虚竹',1,2,'天山六阳掌',0),

('王语嫣',0,2,'神仙姐姐',0),

('令狐冲',1,3,'独孤九剑',0),

('任盈盈',0,3,'弹琴',0),

('岳不群',1,3,'华山剑法',0),

('东方不败',0,3,'葵花宝典',0),

('胡斐',1,4,'胡家刀法',0),

('苗若兰',0,4,'黄衣',0),

('程灵素',0,4,'医术',0),

('袁紫衣',0,4,'六合拳',0)

自定义Field

Django 的官方提供了很多的 Field,但是有时候还是不能满足我们的需求,不过Django提供了自定义 Field 的方法:

来一个简单的例子吧。

1. 减少文本的长度,保存数据的时候压缩,读取的时候解压缩,如果发现压缩后更长,就用原文本直接存储:

Django 1.7 以下

from django.db import models



class CompressedTextField(models.TextField):

""" model Fields for storing text in a compressed format (bz2 by default) """

__metaclass__ = models.SubfieldBase



def to_python(self, value):

if not value:

return value



try:

return value.decode('base64').decode('bz2').decode('utf-8')

except Exception:

return value



def get_prep_value(self, value):

if not value:

return value



try:

value.decode('base64')

return value

except Exception:

try:

tmp = value.encode('utf-8').encode('bz2').encode('base64')

except Exception:

return value

else:

if len(tmp) > len(value):

return value



return tmp

 

  •  to_python 函数用于转化数据库中的字符到 Python的变量,
  •  get_prep_value 用于将Python变量处理后(此处为压缩)保存到数据库,
  • 使用和Django自带的 Field 一样。

Django 1.8 以上版本,可以用

#coding:utf-8

from django.db import models





class CompressedTextField(models.TextField):

"""

model Fields for storing text in a compressed format (bz2 by default)

"""



def from_db_value(self, value, expression, connection, context):

if not value:

return value

try:

return value.decode('base64').decode('bz2').decode('utf-8')

except Exception:

return value



def to_python(self, value):

if not value:

return value

try:

return value.decode('base64').decode('bz2').decode('utf-8')

except Exception:

return value



def get_prep_value(self, value):

if not value:

return value

try:

value.decode('base64')

return value

except Exception:

try:

return value.encode('utf-8').encode('bz2').encode('base64')

except Exception:

return value

Django 1.8及以上版本中,from_db_value 函数用于转化数据库中的字符到 Python的变量

 

2. 比如我们想保存一个 列表到数据库中,在读取用的时候要是 Python的列表的形式,我们来自己写一个 ListField

这个ListField继承自 TextField,代码如下:

from django.db import models

import ast



class ListField(models.TextField):

__metaclass__ = models.SubfieldBase

description = "Stores a python list"



def __init__(self, *args, **kwargs):

super(ListField, self).__init__(*args, **kwargs)



def to_python(self, value):

if not value:

value = []



if isinstance(value, list):

return value



return ast.literal_eval(value)



def get_prep_value(self, value):

if value is None:

return value



return unicode(value) # use str(value) in Python 3



def value_to_string(self, obj):

value = self._get_val_from_obj(obj)

return self.get_db_prep_value(value)

使用它很简单,首先导入 ListField,像自带的 Field 一样使用:

class Article(models.Model):
labels = ListField()

在终端上尝试(运行 python manage.py shell 进入):

  1. >>> from app.models import Article
  2. >>> d = Article()
  3. >>> d.labels
  4. []
  5. >>> d.labels = ["Python", "Django"]
  6. >>> d.labels
  7. ["Python", "Django"]
  1. >>> from blog.models import Article
  2.  
  3. >>> a = Article()
  4. >>> a.labels.append('Django')
  5. >>> a.labels.append('custom fields')
  6.  
  7. >>> a.labels
  8. ['Django', 'custom fields']
  9.  
  10. >>> type(a.labels)
  11. <type 'list'>
  12.  
  13. >>> a.content = u'我正在写一篇关于自定义Django Fields的教程'
  14. >>> a.save()

参考来源:http://code.ziqiangxuetang.com/django/django-custom-field.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琦彦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值