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)

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

# 第一种方式:从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)

数据列类型

数字类型(重点)

mysql orm
tinyint 不存在
smallint SmallIntegerField
mediumint 不存在
int(unsigned) IntegerField(PositiveIntegerField)
bigint(unsigned) BigIntegerField(PositiveBigIntegerField)
decimal DecimalField
float FloatField
double 不存在

字符串

mysql orm
char 不存在
varchar CharField
text TextField

时间

mysql orm
date DateField
datetime DateTimeField

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})

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>

猜你喜欢

转载自www.cnblogs.com/plf-Jack/p/11361199.html