django之關係及查詢,數據類型,約束,分頁

關係

1. 一對一(水平分表)

母表:
  UserInfo
  id     name     age
子表:
  private
  id     salary   sp

建立模型語句:python

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  一對一

建立數據:mysql

models.UserInfo.objects.create(name="潘立府",age="18")
# 注意字段sp_id纔是Private表的真實字段。sp則是一個對象
models.Private.objects.create(salary='50000',sp_id='1')

需求:從母表中查詢子表中的數據(查詢一下name='xxxx'的salary)sql

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

建表語句:django

# 第一種建立方式
"""
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)

"""



# 兩種方式的區別
'''
  第一種方式比較的靈活,本身能夠添加任意的字段
  
  第二種方式比較死板,只能生成兩個字段。若是未來業務擴展,就須要從新打破重來
  
  所以,推薦使用第一種方式。
'''

建立數據:app

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)

需求:查找一下和雷俊約會的姑娘url

# 第一種方式:從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)

數據列類型

數字類型(重點)spa

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

字符串code

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


# 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>
相關文章
相關標籤/搜索