一对一,多对多,数据表类型mysql和orm的区别,django-admin ,内置分页,自定义分页

表对表的一对一多对一关系

1. 一对一
        models.py
            oneTooneField
        views.py:
			##### 从母表查询子表的数据
			### 反向查询
			res.子表表名小写.子表的字段名
						
			#### 从子表查询母表的数据
			### 正向查询
			res.关联字段.母表的字段名
      
2. 多对多:  
   models.py:
      class Boy(models.Model):
         bname = models.CharField(max_length=32)
      
      class Girl(models.MOdel):
         gname = models.CharField(max_length=32)
         
      class b2g(models.MOdel):
         b  = models.ForeignKey("Boy", null=True)
         g  = models.ForeignKey("Girl", null=True)
   
   views.py:
      bulk_create()      
      添加数据的时候, 两种方式:
         bobj = models.Boy.objects.filter(bname='雷俊').first()
         gobj = models.Girl.objects.filter(gname='乔碧萝').first()

         # models.Boy2Girl.objects.create(b_id=bobj.id, g_id=gobj.id)
         models.Boy2Girl.objects.create(b=bobj, g=gobj)
      
      
         1. 自己写第三张表
      查询:
          查询和雷俊约会的姑娘
         #### 需求: 查找一下和雷俊约会的姑娘
         #### 1.
         # res = models.Boy.objects.filter(bname='雷俊').first()
         # love_list = res.boy2girl_set.all()
         # for love in love_list:
         #     print(love.g.gname)
         #
         ##### 2.
         # res = models.Boy2Girl.objects.filter(b__bname='雷俊').all()
         # print(res) ### [obj, obj,....]
         # for love in res:
         #     print(love.g.gname)
         #
         ##### 3.
         # res = models.Boy2Girl.objects.filter(b__bname='雷俊').values('g__gname').all()
         # print(res) ### [{}]
         
         2. 不写第三张表, 使用manytomanyfield
         
            models.py:
               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)
            
            views.py:
                   res = models.Boy.objects.filter(bname='雷俊').first()
                  ### 添加
                  # res.g.add(1)
                  # res.g.add(2,3)
                  ### 删除
                  # res.g.remove(3)

                  ### 查询
                  # res = models.Boy.objects.filter(bname='雷俊').first()
                  # print(res.g.all())  ####

                  ### 清除
                  res.g.clear() ### 清空所有的记录
         
         推荐:
            第一种
            
            因为第二种方式, 字段只能生成两个, 将来扩展的时候, 很不方便,需要重新打破字段

            因此还是使用第一种方式,自定义创建第三张表
   

数据表类型

数字 mysql orm
tinyint 不存在
smallint SmallIntegerField
mediumint 不存在
int(unsigned) IntegerField PositiveIntegerField
bigint BigIntegerField PositiveIntegerField
decimal DecimalField
float FloatField
字符串 char 不存在
varchar Charfield
text TextField
时间 Date DateField
Datetime(2019-8-16 12:23:34 DatetimeField

参数

      null : 是否为null
      default: 默认值
      primary_key: 是否为主键
      db_index: 普通索引
      unique: 唯一索引
      db_column: 列名
      
   class Meta:
      ### 联合唯一索引
      unique_together = [
         ("b", 'g')
      ]
      ### 联合索引:
      index_together = [
         ('b', 'g')
      ]
      

Django-admin:

首先先在里面添加内容:(在terminal >>>createsuperuser --用户名--密码)

from django.contrib import admin
# Register your models here.
from classes import models
admin.site.register(models.Test)

- django admin 数据类型中:(不是重点)
            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   上传图片的宽度保存的数据库字段名(字符串)

      
      - django admin 参数: 
           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'), ]
                              )
         
  1. 分页:

    • 内置分页
      res = Paginator(要分页的数据列表,每页显示的数据)

      users = res.page(当前页码) #### 当前页码的所有数据和属性

      缺点:
      只能将所有的页码循环的展示

views.py:
    def test2(request):
    # for i in range(296):
    #     name='root'+str(i)
    #     models.UserInfo.objects.create(name=name,age=20)
    cur_page = request.GET.get('cur_page')  ### 1


    userlist = models.UserInfo.objects.all()

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

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

index.html:

<ul>
    {% for user in users.object_list %}
        <li>{{ user.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>


  • 自定义分页:
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='/custom/?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='/custom/?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='/custom/?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='/custom/?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 custom(request):

    cur_page = request.GET.get('cur_page')
    cur_page = int(cur_page)

    '''
    mysql:
       seelct * from userinfo limit 0, 10 
       seelct * from userinfo limit 10, 10 
       
       cur_page    start   show_page
          1          0     10
          2          10    10
          3          20    10
          n         (n-1)*10, 10
    limit (cur_page - 1) * show_page 
    '''
    # total = models.UserInfo.objects.count()
    total = models.UserInfo.objects.filter(id__lte=44).count()
    page = PageInfo(cur_page, total)
    start = page.get_start()
    end =  page.get_end()

    ### cur_page = 1   start = 0   end = 10
    ### cur_page = 2   start = 10  end = 20
    ### cur_page = 3   start  =20  end = 30
    # user_list = models.UserInfo.objects.all()[start:end]
    user_list = models.UserInfo.objects.filter(id__lte=44)[start:end]
    return render(request, "custom.html", {"user_list":user_list, "page":page})




custom.html:
    
    
    <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Title</title>
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
    <ul>
        {% for user in user_list %}
            <li>{{ user.name }}</li>
        {% endfor %}
    </ul>


    <nav aria-label="Page navigation">
      <ul class="pagination">
          {{ page.get_page | safe}}
      </ul>
    </nav>
</body>
</html>
posted @ 2019-08-16 17:21  enazede  阅读(272)  评论(0编辑  收藏  举报