django之关系及查询,数据类型,约束,分页

关系

1. 一对一(水平分表)
母表:
  UserInfo
  id     name     age
子表:
  private
  id     salary   sp

创建模型语句:

class UserInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.IntegerField(null=True)


class Private(models.Model):
salary = models.CharField(max_length=32, null=True)
sp = models.OneToOneField("UserInfo", null=True)

# OneToOneField  一对一

创建数据:

models.UserInfo.objects.create(name="潘立府",age="18")
# 注意字段sp_id才是Private表的真实字段。sp则是一个对象
models.Private.objects.create(salary='50000',sp_id='1')

需求:从母表中查询子表中的数据(查询一下name='xxxx'的salary)

res = models.UserInfo.objects.filter(name='plf').first()

# 语法: res.子表表名小写.子表字段名
print(res.private.salary)

需求:从子表中查询母表中的数据(查询一下salary=xxxx的姓名和年龄)

# 从子表查询母表中的数据
res = models.Private.objects.filter(salary=5000).first()

# 语法: 对象.关联的字段.母表的字段
print(res.sp.name,res.sp.age)
2. 多对多
相亲的模型
  Boy:
id        name

Girl:
  id      name
1     真真
2     连连
3     爱爱
4     凤姐
5     乔碧萝

boy2girl(bid和gid应该是联合唯一)
  id      bid     gid
1     1       1
2     1       2
3     1       3
4     2       2
5     2       4
6     2       5

建表语句:

# 第一种创建方式
"""
class Boy(models.Model):
bname = models.CharField(max_length=32,null=True)

class Girl(models.Model):
gname = models.CharField(max_length=32,null=True)

class Boy2Girl(models.Model):
b = models.ForeignKey("Boy",null=True)
g = models.ForeignKey("Girl",null=True)


# 联合唯一索引
class Meta:
unique_together = [
   ('b','g')
]

# 联合索引
#class Meta:
#  index_together = [
#  ('b','g')
#  ]
"""


# 第二种创建方式
"""
class UserInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.IntegerField(null=True)

class Private(models.Model):
salary = models.CharField(max_length=32, null=True)
sp = models.OneToOneField("UserInfo", null=True)

class Boy(models.Model):
bname = models.CharField(max_length=32,null=True)
g = models.ManyToManyField('Girl',null=True)

class Girl(models.Model):
gname = models.CharField(max_length=32,null=True)

"""



# 两种方式的区别
'''
  第一种方式比较的灵活,自己可以添加任意的字段
  
  第二种方式比较死板,只能生成两个字段。如果将来业务扩展,就需要重新打破重来
  
  因此,推荐使用第一种方式。
'''

创建数据:

boyinfo = [
models.Boy(bname='雷俊'),
models.Boy(bname='雷鸣'),
models.Boy(bname='雷震子'),
models.Boy(bname='雷锋'),
models.Boy(bname='雷军'),

]
models.Boy.objects.bulk_create(boyinfo)


girlinfo = [
models.Girl(gname="真真"),
models.Girl(gname="练练"),
models.Girl(gname="爱爱"),
models.Girl(gname="凤姐"),
models.Girl(gname="乔碧萝"),

]
models.Girl.objects.bulk_create(girlinfo)



b2ginfo  = [
models.Boy2Girl(b_id=1,g_id=1),
models.Boy2Girl(b_id=1,g_id=2),
models.Boy2Girl(b_id=1,g_id=3),
models.Boy2Girl(b_id=2,g_id=4),
models.Boy2Girl(b_id=2,g_id=5),
models.Boy2Girl(b_id=1,g_id=5),
]
models.Boy2Girl.objects.bulk_create(b2ginfo)


# 另类的创建数据的方式
bobj = models.Boy.objects.filter(bname='雷俊').first()
gobj = models.Boy.objects.filter(bname='乔碧萝').first()

# 第一种
models.Boy2Girl.objects.create(b=bobj,g=gobj)

# 第二种
models.Boy2Girl.objects.create(b_id=bobj.id,g_id=gobj.id)

需求:查找一下和雷俊约会的姑娘

# 第一种方式:从Boy表中开始查询
res = models.Boy.objects.filter(bname='雷俊').first()
# res 是一个对象: Boy object
res = res.boy2girl_set.all()
for i in res:
# i对象是 Boy2Girl 的对象
# i.g 是一个对象。然后直接使用.获取gname
print(i.g.gname)
print(res)


# 第二种方式:从Boy2Girl表开始查询
res = models.Boy2Girl.objects.filter(b__bname='雷俊').all()
print(res)
for love in res:
print(love.g.gname)

# 第三种方式:在第二种方式的基础上进行改进    
res = models.Boy2Girl.objects.filter(b__bname='雷俊').values('g__gname')
print(res)
'''
<QuerySet [{'g__gname': '真真'}, {'g__gname': '练练'}, {'g__gname': '爱爱'}, {'g__gname': '乔碧萝'}]>
'''

# 第四种方式:
res = models.Boy.objects.filter(bname='雷俊').values('boy2girl__g__gname')
print(res)

数据列类型

数字类型(重点)

mysqlorm
tinyint不存在
smallintSmallIntegerField
mediumint不存在
int(unsigned)IntegerField(PositiveIntegerField)
bigint(unsigned)BigIntegerField(PositiveBigIntegerField)
decimalDecimalField
floatFloatField
double不存在

字符串

mysqlorm
char不存在
varcharCharField
textTextField

时间

mysqlorm
dateDateField
datetimeDateTimeField

orm中数据类型:

EmailField(CharField):
        - 字符串类型,Django Admin以及ModelForm中提供验证机制
    IPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 IPV4 机制
    GenericIPAddressField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供验证 Ipv4和Ipv6
        - 参数:
            protocol,用于指定Ipv4或Ipv6, 'both',"ipv4","ipv6"
            unpack_ipv4, 如果指定为True,则输入::ffff:192.0.2.1时候,可解析为192.0.2.1,开启刺功能,需要protocol="both"
    URLField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证 URL
    SlugField(CharField)
        - 字符串类型,Django Admin以及ModelForm中提供验证支持 字母、数字、下划线、连接符(减号)
    CommaSeparatedIntegerField(CharField)
        - 字符串类型,格式必须为逗号分割的数字
    UUIDField(Field)
        - 字符串类型,Django Admin以及ModelForm中提供对UUID格式的验证
    FilePathField(Field)
        - 字符串,Django Admin以及ModelForm中提供读取文件夹下文件的功能
        - 参数:
                path,                      文件夹路径
                match=None,                正则匹配
                recursive=False,           递归下面的文件夹
                allow_files=True,          允许文件
                allow_folders=False,       允许文件夹
    FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
    ImageField(FileField)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage
            width_field=None,   上传图片的高度保存的数据库字段名(字符串)
            height_field=None   上传图片的宽度保存的数据库字段名(字符串)

数据类型的约束

参数

mysql约束

null              数据库中字段是否可以为空
db_column           数据库中字段的列名
default             数据库中字段的默认值
primary_key         数据库中字段是否为主键
db_index            数据库中字段是否可以建立索引
unique              数据库中字段是否可以建立唯一索引
unique_for_date     数据库中字段【日期】部分是否可以建立唯一索引
unique_for_month    数据库中字段【月】部分是否可以建立唯一索引
unique_for_year     数据库中字段【年】部分是否可以建立唯一索引

orm约束

verbose_name        Admin中显示的字段名称
blank               Admin中是否允许用户输入为空
editable            Admin中是否可以编辑
help_text           Admin中该字段的提示信息
choices             Admin中显示选择框的内容,用不变动的数据放在内存中从而避免跨表操作
                    如:gf = models.IntegerField(choices=[(0, '何穗'),(1, '大表姐'),],default=1)
error_messages      自定义错误信息(字典类型),从而定制想要显示的错误信息;
                    字典健:null, blank, invalid, invalid_choice, unique, and unique_for_date
                    如:{'null': "不能为空.", 'invalid': '格式错误'}
validators          自定义错误验证(列表类型),从而定制想要的验证规则
                    from django.core.validators import RegexValidator
                    from django.core.validators import EmailValidator,URLValidator,DecimalValidator,\
                    MaxLengthValidator,MinLengthValidator,MaxValueValidator,MinValueValidator
                    如:
                        test = models.CharField(
                            max_length=32,
                            error_messages={
                                'c1': '优先错信息1',
                                'c2': '优先错信息2',
                                'c3': '优先错信息3',
                            },
                            validators=[
                                RegexValidator(regex='root_\d+', message='错误了', code='c1'),
                                RegexValidator(regex='root_112233\d+', message='又错误了', code='c2'),
                                EmailValidator(message='又错误了', code='c3'), ]
   )

分页

一:django内置分页

urls.py

urlpatterns = [
 url(r'^test2/', views.test2),
]

views.py

def test2(request):

 cur_page = request.GET.get('cur_page')
 print(cur_page,type(cur_page))
 cur_page = int(cur_page)
 userlist = models.UserInfo.objects.all()
 from  django.core.paginator import Paginator
 paginator = Paginator(userlist,10)
 users = paginator.page(cur_page)

 return  render(request,'index.html',{'users':users})


# paginator拥有的属性
    # per_page  :每页显示的条目的数量
    # count     :数据总个数
    # num_pages :总页数
    # page_range:总页数的索引范围   如:(1,10),(1,200)
    # page      :page对象
    
# users拥有的属性
    # has_next              是否有下一页
    # next_page_number      下一页页码
    # has_previous          是否有上一页
    # previous_page_number  上一页页码
    # object_list           分页之后的数据列表
    # number                当前页
    # paginator             paginator对象

index.html

<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>

<ul>

 {% for foo in users.object_list %}
     <li>{{ foo.name }}</li>
 {% endfor %}


 {% if users.has_previous %}
     <a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a>
 {% endif %}


 {% for num in users.paginator.page_range %}
     <a href="/test2/?cur_page={{ num }}">{{ num }}</a>
 {% endfor %}


 {% if users.has_next %}
     <a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a>
 {% endif %}

</ul>


</body>
</html>

二:自定义分页

urls.py

urlpatterns = [
 url(r'^test3/', views.test3),
]

views.py

class PageInfo():
 def __init__(self,cur_page,total,per_page=10,show_page=11):
     self.cur_page = cur_page        # 当前页
     self.per_page = per_page        # 一页显示多少行数据
     self.total = total              # 总数据有多少行
     self.show_page = show_page      # 页面显示多少索引

     a,b = divmod(self.total,self.per_page)

     if b:
         a = a + 1
     self.total_page = a         # 总页数


 def get_start(self):
     start = (self.cur_page - 1) * self.per_page
     return start


 def get_end(self):
     return self.cur_page * self.per_page


 def get_page(self):
     half = (self.show_page - 1) // 2

     #### taotal_page = 5 < show_page = 11
     if self.total_page < self.show_page:
         begin = 1
         end = self.total_page
     else:
         #### 左边极值判断
         if self.cur_page - half <= 0:
             begin = 1
             # end = self.cur_page + half
             end = self.show_page
         #### 右边极值的判断
         elif self.cur_page + half > self.total_page:
             # begin =  self.cur_page - half
             begin = self.total_page - self.show_page + 1
             end = self.total_page  ### 31
         #### 正常页码判断
         else:
             begin = self.cur_page - half
             end = self.cur_page + half

     page_list = []
     if self.cur_page == 1:
         astr = "<li><a href='#' aria-label='Previous'><span aria-hidden='true'>&laquo;</span></a></li>"
     else:
         astr = "<li><a href='/test3/?cur_page=%s' aria-label='Previous'><span aria-hidden='true'>&laquo;</span></a></li>" % (
                     self.cur_page - 1)
     page_list.append(astr)

     for i in range(begin, end + 1):
         if self.cur_page == i:
             # astr = "<a style='display:inline-block; padding:5px;margin:5px;background-color:red;' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
             astr = "<li class='active'><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i)
         else:
             # astr = "<a style='display:inline-block; padding:5px;margin:5px' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
             astr = "<li><a href='/test3/?cur_page=%s'>%s</a></li>" % (i, i)
         page_list.append(astr)

     if self.cur_page == self.total_page:
         astr = "<li><a href='#' aria-label='Next'><span aria-hidden='true'>&raquo;</span></a></li>"
     else:
         astr = "<li><a href='/test3/?cur_page=%s' aria-label='Next'><span aria-hidden='true'>&raquo;</span></a></li>" % (
                     self.cur_page + 1)
     page_list.append(astr)

     s = " ".join(page_list)

     return s

def test3(request):

 # mysql中limit的分页公式
 '''
 cur_page:   当前页
 show_page_num:   显示多少页
 start_page:     起始页

 limit 起始位置a, 显示多少页b
 a = ( cur_page - 1 ) * show_page_num
 b = show_page_num
 '''


 # 在django中的分页公式(models.UserInfo.objects.filter(id__lte=44)[start:end])
 """
 show_page_num = 10
 cur_page = 1   start = 0   end = 10
 cur_page = 2   start = 10  end = 20
 cur_page = 3   start  =20  end = 30
 
 start = (cur_page - 1) * show_page_num
 end = cur_page * show_page_num
 """
 cur_page = request.GET.get("cur_page")
 cur_page = int(cur_page)

 total = models.UserInfo.objects.count()

 obj = PageInfo(cur_page,total)

 start = obj.get_start()
 end = obj.get_end()

 # 获取总数据
 user_list = models.UserInfo.objects.all()[start:end]

 return render(request,'custom.html',{"user_list":user_list,"page":obj})

custom.html

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>

<ul>

 {% for foo in users.object_list %}
     <li>{{ foo.name }}</li>
 {% endfor %}


 {% if users.has_previous %}
     <a href="/test2/?cur_page={{ users.previous_page_number }}">上一页</a>
 {% endif %}


 {% for num in users.paginator.page_range %}
     <a href="/test2/?cur_page={{ num }}">{{ num }}</a>
 {% endfor %}


 {% if users.has_next %}
     <a href="/test2/?cur_page={{ users.next_page_number }}">下一页</a>
 {% endif %}

</ul>


</body>
</html>

转载于:https://www.cnblogs.com/plf-Jack/p/11361199.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值