Django之Model

到目前爲止,當咱們的程序涉及到數據庫相關操做時,咱們通常都會這麼搞:html

  • 建立數據庫,設計表結構和字段
  • 使用 MySQLdb 來鏈接數據庫,並編寫數據訪問層代碼
  • 業務邏輯層去調用數據訪問層執行數據庫操做
import MySQLdb
 
def GetList(sql):
    db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')
    cursor = db.cursor()
    cursor.execute(sql)
    data = cursor.fetchall()
    db.close()
    return data
 
def GetSingle(sql):
    db = MySQLdb.connect(user='root', db='wupeiqidb', passwd='1234', host='localhost')
    cursor = db.cursor()
    cursor.execute(sql)
    data = cursor.fetchone()
    db.close()
    return data
View Code

django爲使用一種新的方式,即:關係對象映射(Object Relational Mapping,簡稱ORM)。前端

  PHP:activerecordpython

  Java:Hibernate mysql

    C#:Entity Frameworkjquery

django中遵循 Code Frist 的原則,即:根據代碼中定義的類來自動生成數據庫表。git

使用Django鏈接數據庫,首先要在文件中進行相關配置:ajax

pymysql配置:正則表達式

import pymysql
pymysql.install_as_MySQLdb()
__init__.py

 

路由映射配置:sql

from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index', views.index),
]
urls.py

 

1、建立表數據庫

 一、基本結構

from django.db import models

# Create your models here.

class UserInfo(models.Model):
    user = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
    pwd = models.CharField(max_length=64)
    user_type = models.ForeignKey("UserType")

class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=16)
一、models.AutoField  自增列 = int(11)
  若是沒有的話,默認會生成一個名稱爲 id 的列,若是要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。
2、models.CharField  字符串字段
  必須 max_length 參數
三、models.BooleanField  布爾類型=tinyint(1)
  不能爲空,Blank=True
四、models.ComaSeparatedIntegerField  用逗號分割的數字=varchar
  繼承CharField,因此必須 max_lenght 參數
5、models.DateField  日期類型 date
  對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次建立添加,以後的更新再也不改變。
6、models.DateTimeField  日期類型 datetime
  同DateField的參數
七、models.Decimal  十進制小數類型 = decimal
  必須指定整數位max_digits和小數位decimal_places
八、models.EmailField  字符串類型(正則表達式郵箱) =varchar
  對字符串進行正則表達式
九、models.FloatField  浮點類型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  長整形
  integer_field_ranges = {
    'SmallIntegerField': (-32768, 32767),
    'IntegerField': (-2147483648, 2147483647),
    'BigIntegerField': (-9223372036854775808, 9223372036854775807),
    'PositiveSmallIntegerField': (0, 32767),
    'PositiveIntegerField': (0, 2147483647),
  }
12、models.IPAddressField  字符串類型(ip4正則表達式)
13、models.GenericIPAddressField  字符串類型(ip4和ip6是可選的)
  參數protocol能夠是:both、ipv四、ipv6
  驗證時,會根據設置報錯
14、models.NullBooleanField  容許爲空的布爾類型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  減號、下劃線、字母、數字
18、models.SmallIntegerField  數字
  數據庫中的字段有:tinyint、smallint、int、bigint
1九、models.TextField  字符串=longtext
20、models.TimeField  時間 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正則表達式
22、models.BinaryField  二進制
23、models.ImageField   圖片
2四、models.FilePathField 文件
更多字段
一、null=True
  數據庫中字段是否能夠爲空
二、blank=True
  django的 Admin 中添加數據時是否可容許空值
三、primary_key = False
  主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自動建立---不管添加或修改,都是當前操做的時間
  auto_now_add  自動建立---永遠是建立時的時間
5、choices
GENDER_CHOICE = (
        (u'M', u'Male'),
        (u'F', u'Female'),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默認值
8、verbose_name  Admin中字段的顯示名稱
九、name|db_column  數據庫中的字段名稱
十、unique=True  不容許重複
十一、db_index = True  數據庫索引
十二、editable=True  在Admin裏是否可編輯
1三、error_messages=None  錯誤提示
1四、auto_created=False  自動建立
15、help_text  在Admin中提示幫助信息
1六、validators=[]
1七、upload-to
更多參數

二、連表結構

  • 一對多:models.ForeignKey(其餘表)
  • 多對多:models.ManyToManyField(其餘表)
  • 一對一:models.OneToOneField(其餘表)

應用場景:

  • 一對多:當一張表中建立一行數據時,有一個單選的下拉框(能夠被重複選擇)
    例如:建立用戶信息時候,須要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等。
  • 多對多:在某表中建立一行數據是,有一個能夠多選的下拉框
    例如:建立用戶信息,須要爲用戶指定多個愛好
  • 一對一:在某表中建立一行數據時,有一個單選的下拉框(下拉框中的內容被用過一次就消失了
    例如:原有含10列數據的一張表保存相關信息,通過一段時間以後,10列沒法知足需求,須要爲原來的表再添加5列數據

 

2、操做表

一、基本操做

 #
    #
    # models.Tb1.objects.create(c1='xx', c2='oo')  增長一條數據,能夠接受字典類型數據 **kwargs

    # obj = models.Tb1(c1='xx', c2='oo')
    # obj.save()

    #
    #
    # models.Tb1.objects.get(id=123)         # 獲取單條數據,不存在則報錯(不建議)
    # models.Tb1.objects.all()               # 獲取所有
    # models.Tb1.objects.filter(name='seven') # 獲取指定條件的數據

    #
    #
    # models.Tb1.objects.filter(name='seven').delete() # 刪除指定條件的數據

    #
    # models.Tb1.objects.filter(name='seven').update(gender='0')  # 將指定條件的數據更新,均支持 **kwargs
    # obj = models.Tb1.objects.get(id=1)
    # obj.c1 = '111'
    # obj.save()                                                 # 修改單條數據
基本操做

實例:增

def index(requeset):
    增、刪、改、查
    return HttpResponse("ok")

 

    #save添加
    # obj = UserType(caption="管理員")
    # obj.save()

    # #create添加
    # UserType.objects.create(caption="普通用戶")

    # #字典添加
    # user_dict = {"caption":"超級管理員"}
    # UserType.objects.create(**user_dict)

這裏用到了字典添加,注意字典添加時要寫**

注:

    # 添加字典方法一
    user_info_dict1 = {
        "user": "alex",
        "email": "alex123@163.com",
        "pwd": 123,
        "user_type":UserType.objects.get(nid=1)
    }
    UserInfo.objects.create(**user_info_dict1)

    # 添加字典方法二
    user_info_dict2 = {
        "user": "eric",
        "email": "alex123@163.com",
        "pwd": 123,
        "user_type_id": 1
    }
    UserInfo.objects.create(**user_info_dict2)

注:

user_type是咱們自定義的列名,若是要添加,後面就要經過獲取對象來添加。

user_type_id是自動幫咱們建立以後生成的列名,因此能夠直接寫。

 

單標查詢:結果都是queryset

all():列表裏面是對象

    #單表查詢,結果都是queryset
    ret = UserType.objects.all()
    print(type(ret),ret,ret.query)  
    #type(ret)是QuerySet。ret是列表裏面封裝每一條數據的對象。 ret.query查看SQL語句
    for item in ret:
        print(item,item.nid,item.caption)  #item是對象

如圖:

 

all().values():列表裏面是字典

    ret1 = UserType.objects.all().values("nid")  #獲取UserType表中nid的值
    print(type(ret1),ret1,ret1.query)  #type(ret1)是QuerySet。ret1是列表裏面有字典
    for item in ret1:
        print(item,type(item))  #item是字典
        print(item["nid"])  #獲取nid的值

 如圖:

 

 all().values_list():列表裏面是元組

    ret = UserType.objects.all().values_list("nid")
    print(type(ret),ret)  #用values_list獲取到的item是列表裏有元組

 如圖:

 

二、進階操做(了不得的雙下劃線)

利用雙下劃線將字段和對應的操做鏈接起來

# 獲取個數
    #
    # models.Tb1.objects.filter(name='seven').count()

    # 大於,小於
    #
    # models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值
    # models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值
    # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值

    # in
    #
    # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於十一、2二、33的數據
    # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in

    # contains
    #
    # models.Tb1.objects.filter(name__contains="ven")
    # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
    # models.Tb1.objects.exclude(name__icontains="ven")

    # range
    #
    # models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and

    # 其餘相似
    #
    # startswith,istartswith, endswith, iendswith,

    # order by
    #
    # models.Tb1.objects.filter(name='seven').order_by('id')    # asc
    # models.Tb1.objects.filter(name='seven').order_by('-id')   # desc

    # limit 、offset
    #
    # models.Tb1.objects.all()[10:20]

    # group by
    from django.db.models import Count, Min, Max, Sum
    # models.Tb1.objects.filter(c1=1).values('id').annotate(c=Count('num'))
    # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
進階操做

 注:.values().annotate()至關於MSQL裏面的group by

三、連表操做(了不得的雙下劃線)

利用雙下劃線和 _set 將表之間的操做鏈接起來

class UserProfile(models.Model):
    user_info = models.OneToOneField('UserInfo')
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)

    def __unicode__(self):
        return self.username


class UserInfo(models.Model):
    user_type_choice = (
        (0, u'普通用戶'),
        (1, u'高級用戶'),
    )
    user_type = models.IntegerField(choices=user_type_choice)
    name = models.CharField(max_length=32)
    email = models.CharField(max_length=32)
    address = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name


class UserGroup(models.Model):

    caption = models.CharField(max_length=64)

    user_info = models.ManyToManyField('UserInfo')

    def __unicode__(self):
        return self.caption


class Host(models.Model):
    hostname = models.CharField(max_length=64)
    ip = models.GenericIPAddressField()
    user_group = models.ForeignKey('UserGroup')

    def __unicode__(self):
        return self.hostname
表結構實例
user_info_obj = models.UserInfo.objects.filter(id=1).first()
print user_info_obj.user_type
print user_info_obj.get_user_type_display()
print user_info_obj.userprofile.password
 
user_info_obj = models.UserInfo.objects.filter(id=1).values('email', 'userprofile__username').first()
print user_info_obj.keys()
print user_info_obj.values()
一對一操做
相似一對一
1、搜索條件使用 __ 鏈接
二、獲取值時使用 .    鏈接
一對多
user_info_obj = models.UserInfo.objects.get(name=u'武沛齊')
user_info_objs = models.UserInfo.objects.all()
 
group_obj = models.UserGroup.objects.get(caption='CEO')
group_objs = models.UserGroup.objects.all()
 
# 添加數據
#group_obj.user_info.add(user_info_obj)
#group_obj.user_info.add(*user_info_objs)
 
# 刪除數據
#group_obj.user_info.remove(user_info_obj)
#group_obj.user_info.remove(*user_info_objs)
 
# 添加數據
#user_info_obj.usergroup_set.add(group_obj)
#user_info_obj.usergroup_set.add(*group_objs)
 
# 刪除數據
#user_info_obj.usergroup_set.remove(group_obj)
#user_info_obj.usergroup_set.remove(*group_objs)
 
# 獲取數據
#print group_obj.user_info.all()
#print group_obj.user_info.all().filter(id=1)
 
# 獲取數據
#print user_info_obj.usergroup_set.all()
#print user_info_obj.usergroup_set.all().filter(caption='CEO')
#print user_info_obj.usergroup_set.all().filter(caption='DBA')
多對多操做

 

 

 

一對多:實例(表是建立表基本結構時候的UserInfo和UserType):

 經過查詢UserInfo表全部user,關聯UserType表中的caption,這裏直接用雙下劃線進行連表操做:

user_type__caption
    ret = UserInfo.objects.all().values("user","user_type__caption")
    print(ret)
#結果:<QuerySet [{'user': 'alex', 'user_type__caption': '管理員'}, {'user': 'eric', 'user_type__caption': '管理員'}]>
    
    print(ret.query)
#結果:SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`)

 

查找用戶類型是管理員的全部用戶

正向查找:

連表查找UserType表中caption=管理員,再取出user、user_type__caption

  ret = UserInfo.objects.filter(user_type__caption="管理員").values("user","user_type__caption")
    print(ret)
    #[{'user_type__caption': '管理員', 'user': 'alex'}, {'user_type__caption': '管理員', 'user': 'eric'}]

 反向查找:

    ret = UserType.objects.filter(caption="管理員").values("nid","userinfo__user")
    print(ret)
    #[{'nid': 1, 'userinfo__user': 'alex'}, {'nid': 1, 'userinfo__user': 'eric'}]

一對多總結:

外鍵查關聯表的主鍵是正向:表中有Foreignkey找另外一張關聯表的primarykey

主鍵查關聯表的外鍵是反向:表中有primarykey找另外一張關聯表的 Foreignkey

 

 

多對多實例:

建立表結構:

#方法一:
class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)

class Group(models.Model):
    gid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)

    h2g = models.ManyToManyField(Host)

#方法二:
class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)
h2g
= models.ManyToManyField("Group") class Group(models.Model): gid = models.AutoField(primary_key=True) name = models.CharField(max_length=16)

h2g = models.ManyToManyField()會自動生成第三張表

自定義第三張表:

 

#方法三
class HostToGroup(models.Model):
    hgid = models.AutoField(primary_key=True)
    host_id = models.ForeignKey("Host")
    group_id = models.ForeignKey("Group")
    status = models.IntegerField()  #自定義第三張表能夠添加字段

class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)

class Group(models.Model):
    gid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)

    h2g = models.ManyToManyField(Host,through="HostToGroup")

 

咱們使用方法一建立並添加數據:

    # #Host插入數據
    Host.objects.create(hostname="c1",ip="1.1.1.1")
    Host.objects.create(hostname="c2",ip="1.1.1.2")
    Host.objects.create(hostname="c3",ip="1.1.1.3")
    Host.objects.create(hostname="c4",ip="1.1.1.4")
    Host.objects.create(hostname="c5",ip="1.1.1.5")

    #Group插入數據
    Group.objects.create(name="財務部")
    Group.objects.create(name="人事部")
    Group.objects.create(name="公關部")
    Group.objects.create(name="技術部")
    Group.objects.create(name="運營部")
    Group.objects.create(name="銷售部")
    Group.objects.create(name="客服部")
插入數據

向關係表中添加數據: 

注:h2g在Group裏面,經過Group能夠查看第三張表數據

    obj = Group.objects.get(gid=1)
    ret = obj.h2g.all()  #第三張表的全部數據
    print(ret)
#由於如今第三張表中尚未插入數據,因此ret是空列表

正向操做:將多臺機器分配給一組:財務組

    obj = Group.objects.get(gid=1)
    #方法一
    h1 = Host.objects.get(hid=1)
    obj.h2g.add(h1)
    #方法二
    h = Host.objects.filter(hid__gt=3)
    obj.h2g.add(*h)

反向操做:將一臺機器,分給多個組:_set

    #方法一
    # h = Host.objects.get(hid=1)
    # obj = Group.objects.get(gid=1)
    # obj.h2g.add(h)

    #方法二:基於Host表中隱含有group_set
    # h = Host.objects.get(hid=1)
    # h.group_set.add(*Group.objects.filter(gid__gt=2))

補充:

    # Django默認建立第三張表時,添加方法補充
    h = Host.objects.get(hid=1)
    # h.group_set.add(Group.objects.get(gid=1))
    h.group_set.add(1)
    # h.group_set.add(*Group.objects.filter(gid__gt=1))
    h.group_set.add(*[2,3])

 

多對多總結:

正向添加操做:經過表中有m2m操做:(*對象)。注:加*是由於後面獲取到的是列表

反向添加操做:經過表中沒有m2m操做:表名_set

 

remove:只刪除關係表中的數據

    h = Host.objects.get(hid=1)
    h.group_set.remove(*Group.objects.filter(gid__gt=3))

delete:既刪除關係表中的數據,也刪除基礎表(Group表)中的數據。注:all()是Queryset,裏面有delete方法

    h = Host.objects.get(hid=1)
    h.group_set.all().delete()

 

注:Django自動幫咱們在關係表中建立了聯合惟一索引,因此改數據時,不能有重複,否則會報錯

set:刪除、添加。

注:若是關係表中有要設置的數據,保留設置數據,若是有其餘數據,會將其餘數據刪除。

set設置filter數據列表,不用加*
    h = Host.objects.get(hid=1)
    g = Group.objects.filter(gid=10)
    h.group_set.set(g)
   #set設置filter數據列表,不用加*
    h = Host.objects.get(hid=1)
    g = Group.objects.filter(gid__gt=11)
    h.group_set.set(g)

 

get_or create 和 uptate_or create :若是關係表中有就不建立,基礎表也不建立;若是關係表中沒有就建立,基礎表也建立。二者同樣。

    h = Host.objects.get(hid=1)
    r = h.group_set.get_or_create(name="財務部")
    r = h.group_set.update_or_create(name="技術部")

 

經過方法三自定義建立關聯表,自定義關係表不能使用add,set,create命令,或者經過直接賦值方式來建立關係,能夠經過all,filter獲取

class HostToGroup(models.Model):
    hgid = models.AutoField(primary_key=True)
    host_id = models.ForeignKey("Host")
    group_id = models.ForeignKey("Group")
    status = models.IntegerField()  #自定義第三張表能夠添加字段
    class Meta:
        # index_together = ("host_id","group_id")  #建立惟一索引
        unique_together=[
            ("host_id","group_id")
        ]  #建立聯合索引

class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)

class Group(models.Model):
    gid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)

    h2g = models.ManyToManyField(Host,through='HostToGroup')
自定義關係表

注:聯合索引

數據庫:

 

總結:

直接使用M2M建立能夠操做的:

獲取值filter、all,add添加,remove刪除,filter.delete()刪除,set設置(刪除、添加),get_or_create和update_or_create建立。

補充:

自定義第三張關係表:

獲取值:filter、all

 

實例:Q

先將文件進行配置

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"static"),
)
settings.py之static

 

DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'Django003',
    'USER': 'root',
    'PASSWORD': '',
    'HOST': '',
    'PORT': '',
    }
}
settings.py之MySQL

 

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
settings之csrf註銷

 

import pymysql
pymysql.install_as_MySQLdb()
__init__.py

 

from django.db import models

# Create your models here.
class Author(models.Model):
    """
    做者
    """
    name = models.CharField(max_length=100)
    age = models.IntegerField()

class BookType(models.Model):
    """
    圖書類型
    """
    caption = models.CharField(max_length=64)

class Book(models.Model):
    """
    圖書
    """
    name = models.CharField(max_length=64)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=10,decimal_places=2)
    pubdate = models.DateField()

    authors = models.ManyToManyField(Author)
    book_type = models.ForeignKey(BookType)

    def __str__(self):
        return 'obj:%s-%s' %(self.name,self.price)
models.py

 

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^test', views.test),
    url(r'^index', views.index),
]
urls.py

 

from django.shortcuts import render,HttpResponse
from app01 import models
# Create your views here.

# def test(request):
#     #數據庫添加數據
#     models.BookType.objects.create(caption='技術')
#     models.BookType.objects.create(caption='文學')
#     models.BookType.objects.create(caption='動漫')
#     models.BookType.objects.create(caption='男人裝')
#
#     models.Book.objects.create(name='文藝復興',pages='100',price='40',pubdate='1992-11-2',book_type_id='1')
#     models.Book.objects.create(name='解密',pages='80',price='10', pubdate='2016-6-10',book_type_id='2')
#     models.Book.objects.create(name='刀鋒',pages='50',price='3', pubdate='2014-02-16',book_type_id='2')
#     models.Book.objects.create(name='查令十字路84號',pages='260',price='40',pubdate='1999-10-12',book_type_id='3')
#     models.Book.objects.create(name='紅樓',pages='1000',price='500', pubdate='1760-1-1',book_type_id='3')
#     models.Book.objects.create(name='將夜',pages='2000',price='300', pubdate='2010-3-3',book_type_id='1')
#     models.Book.objects.create(name='mysql從刪庫到跑路',pages='20',price='10',pubdate='1998-9-2',book_type_id='4')
#     models.Book.objects.create(name='馬克思主義',pages='50',price='100',pubdate='1937-3-3',book_type_id='2')
#
#     return HttpResponse('ok')

import json
from datetime import date
from datetime import datetime
from decimal import Decimal
#序列化類
class JsonCustomEncoder(json.JSONEncoder):

    def default(self, field):

        if isinstance(field, datetime):
            return field.strftime('%Y-%m-%d %H:%M:%S')
        elif isinstance(field, date):
            return field.strftime('%Y-%m-%d')
        elif isinstance(field, Decimal):
            return str(field)
        else:
            return json.JSONEncoder.default(self, field)

def index(request):
    if request.method == 'POST':  #判斷是不是post訪問,接收post請求
        ret = {'status': False, 'message': '', 'data':None}
        try:
            post_data = request.POST.get('post_data',None)  #獲取到前端發來的post_data,若是沒有默認None
            post_data_dict = json.loads(post_data)  #將post_data反序列化成字典
            print(post_data_dict)
            # {'name': ['11', 'sdf'],'price': ['11', 'sdf']}
            # 構造搜索條件     去數據庫進行搜索
            from django.db.models import Q
            con = Q()
            for k,v in post_data_dict.items():
                q = Q()
                q.connector = 'OR'  #建立或的關係
                for item in v:  #循環列表
                    q.children.append((k, item))  #循環出來的多個item是添加到或的關係
                con.add(q, 'AND')  #將或的關係添加到and的關係中
            """
            序列化
            ret = models.Book.objects.filter(con)
            print(ret) # ret是queryset,[對象]

            from django.core import serializers
            data = serializers.serialize("json", ret)
            print(type(data),data)  # 字符串
            """
            """
            #ret = models.Book.objects.filter(con).values('name','book_type__caption')
            ret = models.Book.objects.filter(con).values_list('name', 'book_type__caption')
            print(ret,type(ret))  #ret外面是queryset對象,裏面是字典
            li = list(ret)  #轉換成列表,裏面是字典
            data = json.dumps(li)
            print(data,type(data))
            """
            result = models.Book.objects.filter(con).values('name','price','pubdate','book_type__caption')
            # result = models.Book.objects.filter(con)是queryset對象
            li = list(result)  #轉換成列表,裏面是字典,values_list內部元素的列表
            ret['status'] = True
            ret['data'] = li  #將列表信息添加到ret字典
        except Exception as e:
            ret['message'] = str(e)
        ret_str = json.dumps(ret, cls=JsonCustomEncoder)  #將queryset轉換成字符串返回到前臺
        print(ret_str)
        return HttpResponse(ret_str)  #返回字符串
    return render(request, 'index.html')
views.py

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .left{
            float: left;
        }
        .clearfix:after{
            content: '.';
            clear: both;
            display: block;
            visibility: hidden;
            height: 0;
        }
    </style>
</head>
<body>
    <div class="condition">
        <div class="item clearfix">
            <div class="icon left" onclick="AddCondition(this);">+</div>
            <div class="left">
                <select onchange="ChangeName(this);">
                    <option value="name">書名</option>
                    <option value="book_type__caption">圖書類型</option>
                    <option value="price">價格</option>
                    <option value="pages">頁數</option>
                </select>
            </div>
            <div class="left"><input type="text" name="name" /></div>
        </div>
    </div>
    <div>
        <input type="button" onclick="Search();" value="搜索" />
    </div>
    <div class="container"></div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function  AddCondition(ths) {
            var new_tag = $(ths).parent().clone();   //點加號時找到父級,克隆整個div
            new_tag.find('.icon').text('-');  //克隆的div將加號變成減號
            new_tag.find('.icon').attr('onclick', 'RemoveCondition(this);');  //將減號綁定事件

            $(ths).parent().parent().append(new_tag);  //將克隆的div添加到指定位置
        }
        function  RemoveCondition(ths) {  //減號綁定事件
            $(ths).parent().remove();  //點擊減號將會移除div
        }
        function ChangeName(ths) {  //下拉框綁定事件
            var v = $(ths).val();  //得到當前框的值:可得到name,book_type__caption,price,pages
            $(ths).parent().next().find('input').attr('name',v);  //找到當前框對應的input標籤的name屬性和賦值,如:name=name,name=book_type__caption
        }
        function Search() {  //將獲取的值提交後臺
            var post_data_dict = {};

            // 獲取全部input的內容,提交數據
            $('.condition input').each(function () {  //循環div裏面全部的input
                // console.log($(this)[0])
                var n = $(this).attr('name');  //獲取當前input的name
                var v = $(this).val();  //獲取當前input標籤裏面輸入的值
                var v_list = v.split('');  //將輸入的值用中文逗號進行分割
                post_data_dict[n] = v_list;  //將name和分割後的值添加到字典中
            });
{#            console.log(post_data_dict);#}
            var post_data_str = JSON.stringify(post_data_dict);  //將字典轉換成字符串
            $.ajax({
                url:"/index/",  //index後面必須加/
                type:"POST",
                data:{"post_data":post_data_str},
                dataType:"json",
                success:function (arg) {
                     //arg返回的是json對象,寫上dataType:"json",就能夠直接寫arg.status。
                    if(arg.status){ //後端返回來的status爲真
                        var table = document.createElement('table');  //建立table標籤
                        table.setAttribute('border',1);  //設置table邊框
                        // [{,name,pubdate,price,caption},]
                        $.each(arg.data, function(k,v){  //循環data列表,裏面是字典
                            console.log(k);  //k是data索引
                            console.log(v);  //v是data裏面的字典
                            //建立tr標籤
                            var tr = document.createElement('tr');
                            //根據後臺返回data裏面的數組建立td
                            var td1 = document.createElement('td');
                            td1.innerText = v['name'];
                            var td2 = document.createElement('td');
                            td2.innerText = v['price'];
                            var td3 = document.createElement('td');
                            td3.innerText = v['book_type__caption'];
                            var td4 = document.createElement('td');
                            td4.innerText = v['pubdate'];
                            //將全部td添加到tr
                            tr.appendChild(td1);
                            tr.appendChild(td2);
                            tr.appendChild(td3);
                            tr.appendChild(td4);
                            //將tr添加到table
                            table.appendChild(tr);
                        });
                        $('.container').empty();  //顯示table前將內容清空container
                        $('.container').append(table);  //將後臺返回數據放在table裏面添加到containerdiv顯示在前端
                    }else{
                        alert(arg.message);
                    }
                }
            })
        }
    </script>
</body>
</html>
HTML

 

 

HTML之重點

一、var new_tag = $(ths).parent().clone()獲取的是經過jquery方法得到的對象。

dom對象和jquery對象之間的轉換
#dom對象:
document.getElementsById("i1")

#jquery對象:
$("i1")

#dom對象轉換成jquery對象:
$(document.getElementsByTagName("div")[0])

#jquery對象轉換成dom對象
$("div").first()[0]

二、option的value屬性值要和建立表裏面的字段同樣,每次ChangeName時$(this).val(),能夠得到當前選中標籤的屬性,再找到後面的input,將獲取的屬性值設置成input的name屬性名。也就是option選圖書類型時,value是book_type__caption,後面的input框的name屬性就是book_type__caption。代碼結合註釋看會更加理解。

三、發ajax時注意,無論urls.py路由配置有沒有加/,發ajax請求時,url結尾都要加/,不加會出錯:APPEND_SLASH 。

四、403錯誤是須要註釋settings裏面的csrf。

五、data:{"post_data":post_data_str}裏面的post_data_str必須傳字符串,索引要轉換成字符串格式:var post_data_str = JSON.stringify(post_data_dict)

 

views.py之重點

一、json序列化時只能是python的數據結構:字典、列表等

二、.filter()或者.all()獲得的是queryset對象,用serializers.serialize實現序列化

三、JsonCustomEncoder是序列化類,字符串能夠直接dumps,時間和小數(pubdate、price)不能dumps,有了序列化類就能夠。

相關文章
相關標籤/搜索