Django模型(數據庫)及Django Query經常使用方法

###目錄:html

Django模型(數據庫)及Django Query經常使用方法python

Django 模型是與數據庫相關的,與數據庫相關的代碼通常寫在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等數據庫,只須要在settings.py中配置便可,不用更改models.py中的代碼,豐富的API極大的方便了使用。 新建項目和應用react

django-admin.py startproject learn_models # 新建一個項目
cd learn_models # 進入到該項目的文件夾
django-admin.py startapp people # 新建一個 people 應用(app)
複製代碼

補充:新建app也能夠用 python manage.py startapp people, 須要指出的是,django-admin.py 是安裝Django後多出的一個命令,並非運行的當前目錄下的django-admin.py(當前目錄下也沒有),但建立項目會生成一個 manage.py 文件。 那project和app什麼關係呢? 一個項目通常包含多個應用,一個應用也能夠用在多個項目中。正則表達式

添加應用 將咱們新建的應用(people)添加到 settings.py 中的 INSTALLED_APPS中,也就是告訴Django有這麼一個應用。sql

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
 
    'people',
)
複製代碼

修改models.py 咱們打開 people/models.py 文件,修改其中的代碼以下:shell

from django.db import models
 
 
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
複製代碼

咱們新建了一個Person類,繼承自models.Model, 一我的有姓名和年齡。 這裏用到了兩種Field,更多Field類型能夠參考教程最後的連接。 建立數據表 咱們來同步一下數據庫(咱們使用默認的數據庫 SQLite3,無需配置)數據庫

cd 進入 manage.py 所在的那個文件夾下,輸入下面的命令
 
# Django 1.6.x 及如下
python manage.py syncdb
 
# Django 1.7 及以上的版本須要用如下命令
python manage.py makemigrations
python manage.py migrate
複製代碼

咱們會看到,Django生成了一系列的表,也生成了咱們新建的people_person這個表,那麼如何使用這個表呢?django

使用 Django 提供的 QuerySet API Django提供了豐富的API, 下面演示如何使用它。bash

$ python manage.py shell
 
>>> from people.models import Person
>>> Person.objects.create(name="Tom", age=24)
<Person: Person object>
>>>
複製代碼

咱們新建了一個用戶WeizhongTu 那麼如何從數據庫是查詢到它呢?session

>>> Person.objects.get(name="Tom")
<Person: Person object>
>>>
複製代碼

咱們用了一個 .objects.get() 方法查詢出來符合條件的對象,可是你們注意到了沒有,查詢結果中顯示<Person: Person object>,這裏並無顯示出與Tom的相關信息,若是用戶多了就沒法知道查詢出來的究竟是誰,查詢結果是否正確,咱們從新修改一下 people/models.py name 和 age 等字段中不能有 __(雙下劃線,由於在Django QuerySet API中有特殊含義(用於關係,包含,不區分大小寫,以什麼開頭或結尾,日期的大於小於,正則等) 也不能有Python中的關鍵字,name 是合法的,student_name 也合法,可是student__name不合法,try, class, continue 也不合法,由於它是Python的關鍵字( import keyword; print(keyword.kwlist) 能夠打出全部的關鍵字)

from django.db import models
 
 
class Person(models.Model):
    name = models.CharField(max_length=30)
    age = models.IntegerField()
     
    def __unicode__(self):
    # 在Python3中使用 def __str__(self):
        return self.name
複製代碼

按 CTRL + C 退出當前的 Python shell, 重複上面的操做,再來看看效果

新建一個對象的方法有如下幾種:

1. Person.objects.create(name=name,age=age)

2. p = Person(name="Tim", age=23)
p.save()

3. p = Person(name="Tony")
p.age = 23
p.save()

4. Person.objects.get_or_create(name="Rose", age=23)
複製代碼

這種方法是防止重複很好的方法,可是速度要相對慢些,返回一個元組,第一個爲Person對象,第二個爲True或False, 新建時返回的是True, 已經存在時返回False. 獲取對象有如下方法:

Person.objects.all()

Person.objects.all()[:10] 切片操做,獲取10我的,不支持負索引,切片能夠節約內存

Person.objects.get(name=name)
複製代碼

get是用來獲取一個對象的,若是須要獲取知足條件的一些人,就要用到filter

Person.objects.filter(name="abc")  
# 等於Person.objects.filter(name__exact="abc") 名稱嚴格等於 "abc" 的人

Person.objects.filter(name__iexact="abc") 
# 名稱爲 abc 可是不區分大小寫,能夠找到 ABC, Abc, aBC,這些都符合條件


Person.objects.filter(name__contains="abc")  # 名稱中包含 "abc"的人

Person.objects.filter(name__icontains="abc")  #名稱中包含 "abc",且abc不區分大小寫


Person.objects.filter(name__regex="^abc")  # 正則表達式查詢

Person.objects.filter(name__iregex="^abc")  # 正則表達式不區分大小寫
複製代碼

filter是找出知足條件的,固然也有排除符合某條件的

Person.objects.exclude(name__contains="WZ")  
# 排除包含 WZ 的Person對象

Person.objects.filter(name__contains="abc").exclude(age=23)  
# 找出名稱含有abc, 可是排除年齡是23歲的
複製代碼

從數據庫中查詢出來的結果通常是一個集合,這個集合叫作 QuerySet。

from django.db import models
 
 
class Blog(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()
 
    def __unicode__(self):  # __str__ on Python 3
        return self.name
 
class Author(models.Model):
    name = models.CharField(max_length=50)
    email = models.EmailField()
 
    def __unicode__(self):  # __str__ on Python 3
        return self.name
 
class Entry(models.Model):
    blog = models.ForeignKey(Blog)
    headline = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    n_comments = models.IntegerField()
    n_pingbacks = models.IntegerField()
    rating = models.IntegerField()
 
    def __unicode__(self):  # __str__ on Python 3
        return self.headline
複製代碼

QuerySet 建立對象的方法

>>> from blog.models import Blog
>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()
 
總之,一共有四種方法
# 方法 1
Author.objects.create(name="Tom", email="tom@163.com")
 
# 方法 2
twz = Author(name="Tom", email="tom@163.com")
twz.save()
 
# 方法 3
twz = Author()
twz.name="Tom"
twz.email="tom@163.com"
twz.save()
 
# 方法 4,首先嚐試獲取,不存在就建立,能夠防止重複
Author.objects.get_or_create(name="Tom", email="tom@163.com")
# 返回值(object, True/False)
複製代碼

備註:前三種方法返回的都是對應的 object,最後一種方法返回的是一個元組,(object, True/False),建立時返回 True, 已經存在時返回 False 當有一對多,多對一,或者多對多的關係的時候,先把相關的對象查詢出來

>>> from blog.models import Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
複製代碼

刪除符合條件的結果 和上面相似,獲得知足條件的結果,而後 delete 就能夠(危險操做,正式場合操做務必謹慎),好比:

Person.objects.filter(name__contains="abc").delete() # 刪除 名稱中包含 "abc"的人
 
若是寫成 
people = Person.objects.filter(name__contains="abc")
people.delete()
效果也是同樣的,Django實際只執行一條 SQL 語句。
複製代碼

更新某個內容 批量更新,適用於 .all()  .filter()  .exclude() 等後面 (危險操做,正式場合操做務必謹慎)

Person.objects.filter(name__contains="abc").update(name='xxx') # 名稱中包含 "abc"的人 都改爲 xxx
Person.objects.all().delete() # 刪除全部 Person 記錄
複製代碼

單個 object 更新,適合於 .get(), get_or_create(), update_or_create() 等獲得的 obj,和新建很相似。

aut = Author.objects.get(name="Sara")
aut.name="LiMing"
aut.email="Liming@163.com"
aut.save()  # 最後不要忘了保存!!!
複製代碼

QuerySet 是可迭代的,好比:

es = Entry.objects.all()
for e in es:
    print(e.headline)
複製代碼

Entry.objects.all() 或者 es 就是 QuerySet 是查詢全部的 Entry 條目。 注意事項: (1). 若是隻是檢查 Entry 中是否有對象,應該用 Entry.objects.all().exists() (2). QuerySet 支持切片 Entry.objects.all()[:10] 取出10條,能夠節省內存 (3). 用 len(es) 能夠獲得Entry的數量,可是推薦用 Entry.objects.count()來查詢數量,後者用的是SQL:SELECT COUNT(*) (4). list(es) 能夠強行將 QuerySet 變成 列表 QuerySet 查詢結果排序 做者按照名稱排序

Author.objects.all().order_by('name')
Author.objects.all().order_by('-name') # 在 column name 前加一個負號,能夠實現倒序
複製代碼

QuerySet 支持鏈式查詢

Author.objects.filter(name__contains="Tom").filter(email="tom@163.com")
Author.objects.filter(name__contains="Tom").exclude(email="tom@163.com")
 
# 找出名稱含有abc, 可是排除年齡是23歲的
Person.objects.filter(name__contains="abc").exclude(age=23)
複製代碼

QuerySet 不支持負索引

Person.objects.all()[:10] 切片操做,前10條
Person.objects.all()[-10:] 會報錯!!!
 
# 1. 使用 reverse() 解決
Person.objects.all().reverse()[:2] # 最後兩條
Person.objects.all().reverse()[0] # 最後一條
 
# 2. 使用 order_by,在欄目名(column name)前加一個負號
Author.objects.order_by('-id')[:20] # id最大的20條
複製代碼

擴展:QuerySet 重複的問題,使用 .distinct() 去重複 通常的狀況下,QuerySet 中不會出來重複的,重複是很罕見的,可是當跨越多張表進行檢索後,結果併到一塊兒,能夠會出來重複的值

qs1 = Pathway.objects.filter(label__name='x')
qs2 = Pathway.objects.filter(reaction__name='A + B >> C')
qs3 = Pathway.objects.filter(inputer__name='WeizhongTu')
 
# 合併到一塊兒
qs = qs1 | qs2 | qs3
這個時候就有可能出現重複的
 
# 去重方法
qs = qs.distinct()
複製代碼

##實例代碼操做 需求一:編寫登陸和註冊

編寫註冊功能,用戶名不能已經存在,若是存在須要提示從新輸入 註冊後能夠登陸,成功後能夠跳轉到成功登陸界面

文件樹形圖顯示

代碼操做:

  • register.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>註冊頁面</title>
</head>
<body>
    <form action="" method="post">
        {% csrf_token %}
        用戶名:{{form.userName}}{{error}}<br>
        密  碼:{{form.password}}<br>
        確認密碼:{{form.repassword}}<br>{{form.non_field_errors}}<br>

    <input type="submit" value="註冊">
    <a href="{% url 'login' %}">已有帳號,去登陸</a>

        </form>
</body>
</html>
複製代碼
  • login.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陸</title>
</head>
<body>
    <form action="" method="POST">
        {% csrf_token %}

        <a href="{% url 'register' %}">沒有帳號?去註冊</a><br>


        用戶名:{{form.userName}}<br>
        密  碼:{{form.password}}<br>{{error}}<br>

        <input type="submit" value="登陸">


    </form>


</body>
</html>
複製代碼
  • loginsuc.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登陸成功</title>
</head>
<body>
    登錄成功了,開不開心,意不意外。怎麼還有一個網頁?哈哈哈哈哈哈~<br>
        用戶ID:{{ request.session.id }}<br>
        用戶名:{{ request.session.username }}


</body>
</html>
複製代碼
  • weekForm.py
# -*- coding:utf-8 -*-
from django.forms import Form,widgets,fields,ValidationError




class register(Form):
    userName = fields.CharField(max_length=10)
    password = fields.CharField(max_length=10,widget=widgets.PasswordInput)
    repassword = fields.CharField(max_length=10,widget=widgets.PasswordInput)

    def  clean(self):
        userName = self.cleaned_data['userName']
        password = self.cleaned_data['password']
        repassword = self.cleaned_data['repassword']
        if not password == repassword:
            myerror = '兩次密碼不一致,請從新輸入'
            raise ValidationError(myerror)

        return self.cleaned_data


class login(Form):
    userName = fields.CharField(max_length=10)
    password = fields.CharField(max_length=10,widget=widgets.PasswordInput)

複製代碼
  • models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
class UserModel(models.Model):
    userName = models.CharField(max_length=10)
    password = models.CharField(max_length=10)
複製代碼
  • views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render,redirect
from weekForms import weekForm
from models import UserModel
from django.http import HttpResponse
from . import models

# Create your views here.
def register(request):
    if request.method == 'GET':
        form = weekForm.register()
        return render(request,'register.html',{'form':form})
    elif request.method == 'POST':
        form = weekForm.register(request.POST)
        if form.is_valid():
            temp = models.UserModel.objects.filter(userName=form.cleaned_data['userName']).exists()

            if temp == False:
                userModel = UserModel()
                userModel.userName = form.cleaned_data['userName']
                userModel.password = form.cleaned_data['password']

                userModel.save()
                return HttpResponse('數據提交成功!您能夠登陸了.')
            else:
                error = '用戶名已經存在!'
                return render(request,'register.html',{'form':form,'error':error})

        else:
            return render(request,'register.html',{'form':form})


def login(request):
    if request.method == 'GET':
        loginform = weekForm.login()
        return render(request,'login.html',{'form':loginform})
    elif request.method == 'POST':
        loginform = weekForm.login(request.POST)
        if loginform.is_valid():
            userName = loginform.cleaned_data['userName']
            password = loginform.cleaned_data['password']

            user = UserModel.objects.filter(userName=userName,password=password)
            if user:

                obj = UserModel.objects.get(userName = userName)
                request.session['id'] = obj.id
                request.session['username'] = obj.userName
                return render(request,'loginsuc.html')


            #若是想直接顯示能夠在setting中加SESSION_SERIALIZER='django.contrib.sessions.serializers.PickleSerializer'


            else:
                error = '用戶名或者密碼輸入有誤.'
                return render(request,'login.html',{'form':loginform,'error':error})
        else:
            return render(request,'login.html',{'form':loginform})
    else:
        return redirect('https://www.zhihu.com/')


複製代碼
  • urls.py
from django.conf.urls import url
from . import views

urlpatterns=[
    url(r'^register/$',views.register,name='register'),
    url(r'^login/$',views.login,name='login')
]
複製代碼

效果展現:

需求二:編寫寵物管理系統

寵物系統文件樹形圖

  • petForm.py
# -*- coding: utf-8 -*-
from django.forms import Form,widgets,fields

class petInfo(Form):
    petName = fields.CharField(max_length=10,)
    petId = fields.CharField(max_length=4)
    gender = fields.CharField(initial = '雄性',
    widget = widgets.Select(choices=(('雄性','雄性'),('雌性','雌性'))))
    year = fields.IntegerField(max_value=25,min_value=0)
    kind = fields.CharField(max_length=10)


class PetInfo(Form):
    petName = fields.CharField(max_length=10,)
    petId = fields.CharField(max_length=4)
    gender = fields.CharField(initial = '雄性',widget = widgets.Select(choices=(('雄性','雄性'),('雌性','雌性'))))
    year = fields.IntegerField(max_value=25,min_value=0)
    kind = fields.CharField(max_length=10)

複製代碼
  • html
  • petlist.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>寵物管理系統</title>
</head>
<body>
    <table>
        <tr>
            <td>寵物名</td>
            <td>寵物編號</td>
            <td>寵物性別</td>
            <td>寵物年齡</td>
            <td>種類</td>

        </tr>

        {% for pet in pets %}
        <tr>
            <td>{{pet.petName}}{{disable}}</td>
            <td>{{pet.petId}}</td>
            <td>{{pet.gender}}</td>
            <td>{{pet.year}}</td>
            <td>{{pet.kind}}</td>

            <td><a href="">刪除</a></td>
            <td><a href="{% url 'editpet' %}?id={{ pet.id }}">修改</a></td>

        </tr>
        {% empty %}

        沒有寵物信息

        {% endfor %}
    </table>

    <a href="{% url 'addPet' %}">添加新寵物</a>


</body>
</html>
複製代碼
  • html
  • addpet.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>添加寵物信息</title>
</head>
<body>

    <form action="" method="POST">
            {% csrf_token %}
             <input type="hidden" name="id" value="{{ id }}">
            寵物名:{{form.petName}}<br>
            寵物編號:{{form.petId}}<br>
            寵物性別:{{form.gender}}<br>
            年 齡:{{form.year}}<br>
            種類:{{form.kind}}<br>

            <input type="submit" value="增長寵物">


</body>
</html>
複製代碼
  • html
  • editpet.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>修改寵物信息</title>
</head>
<body>
        <form action="" method="POST">
            {% csrf_token %}
             <input type="hidden" name="id" value="{{ id }}">
            寵物名:{{pet.petName}}<br>
            寵物編號:{{pet.petId}}<br>
            寵物性別:{{pet.gender}}<br>
            年 齡:{{pet.year}}<br>
            種類:{{pet.kind}}<br>

            <input type="submit" value="修改">


        </form>



</body>
</html>
複製代碼
  • models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models

# Create your models here.
class pet(models.Model):
    petName = models.CharField(max_length=10)
    petId = models.CharField(max_length=4)
    gender = models.CharField(max_length=1)
    year = models.IntegerField()
    kind = models.CharField(max_length=10)
複製代碼
  • views.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render
from models import pet
from django.http import HttpResponse
from petForms import petForm
from . import models


from django.core.urlresolvers import reverse
from django.shortcuts import redirect

# Create your views here.
def petlist(request):
    pets = models.pet.objects.all().filter(isDelete=True)
    return render(request,'petlist.html',{'pets':pets})

def addPet(request):
    if request.method == 'GET':
        petform = petForm.PetInfo()
        return render(request,'addpet.html',{'form':petform})
    elif request.method == 'POST':
        petform = petForm.PetInfo(request.POST)
        if petform.is_valid():
            data = petform.cleaned_data
            newPet = pet()
            newPet.petName = data['petName']
            newPet.petId = data['petId']
            newPet.gender = data['gender']
            newPet.year = data['year']
            newPet.kind = data['kind']
            newPet.save()
            return redirect(reverse('petlist'))
        else:
            return render(request,'addpet.html',{'form':petform})


def editPet(request):
    if request.method == 'GET':
        id = request.GET.get('id',0)
        pets = models.pet.objects.get(pk=int(id))
        petform = petForm.petInfo(
            initial={
                'petName':pets.petName,
                'petId':pets.petId,
                'gender':pets.gender,
                'year':pets.year,
                'kind':pets.kind,
            }             #給須要修改的寵物添加初始屬性
        )
        return render(request,'editpet.html',{'pet':petform,'id':id})

    elif request.method == 'POST':
        petform = petForm.petInfo(request.POST)
        id = request.POST['id']
        if petform.is_valid():
            data = petform.cleaned_data
            oldPet = models.pet.objects.get(pk=int(id))
            # oldPet.petName = models.Pet.objects.get(pk=int(id))['petName']
            oldPet.petName = data['petName']
            oldPet.petId = data['petId']
            oldPet.gender = data['gender']
            oldPet.year = data['year']
            oldPet.kind = data['kind']
            oldPet.save()
            return redirect(reverse('petlist'))  #重定向
        else:
            pet = models.pet.objects.get(pk=int(id))
            return render(request,'editpet.html',{'pet':petform,'id':id})


def petsin(request):
    Pets = pet.objects.all()
    id = request.GET['id']
    new = models.pet.objects.get(pk=int(id))
    values = {
        'petName':new.petName,
        'petId':new.petId,
        'gender':new.gender,
        'year':new.year,
        'kind':new.kind,

    }
    return render(request,'pet.html',{'values':values,})

def delpet(request):
    if request.method == 'GET':
        id = request.GET.get('id',0)
        pets = models.pet.objects.get(pk=int(id))
        pets.isDelete=0
        pets.save()
        pets = models.pet.objects.all().filter(isDelete = True)
        return render(request, 'petlist.html', {'pets': pets})
複製代碼
  • urls.py
from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'addPet/$',views.addPet,name='addPet'),
    url(r'petlist/$',views.petlist,name='petlist'),
    url(r'editpet/$',views.editPet,name='editpet'),
]
複製代碼

效果展現:

####功能完善中,未完待續...

相關文章
相關標籤/搜索