Django-模板系統、session、web框架、內置分頁

模板系統

模版的建立過程,對於模版,其實就是讀取模版(其中嵌套着模版標籤),而後將 Model 中獲取的數據插入到模版中,最後將信息返回給用戶。html

模板中也有本身的語言,該語言能夠實現數據展現mysql

{{ item }}
{% for item in item_list %}  <a>{{ item }}</a>  {% endfor %}
  forloop.counter
  forloop.first
  forloop.last 
{% if ordered_warranty %}  {% else %} {% endif %}
母板:{% block title %}{% endblock %}
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}
幫助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}

自定義simple_tag:git

a、在app中建立templatetags模塊web

b、建立任意 .py 文件,如:xx.pyajax

from django import template
from django.utils.safestring import mark_safe
   
register = template.Library()

@register.filter()
def my_upper(val, args):
    return val + args

@register.simple_tag
def my_simple_time(v1,v2,v3):
    return  v1 + v2 + v3
   
@register.simple_tag
def my_input(id,arg):
    result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
    return mark_safe(result)

c、在使用自定義simple_tag的html文件中導入以前建立的 xx.py 文件名正則表達式

{% load xx %}

d. 使用simple_tagsql

{% my_simple_time 1 2 3%}
{% my_input 'id_username' 'hide'%}

e、在settings中配置當前app,否則django沒法找到自定義的simple_tag  數據庫

session

Django中默認支持Session,其內部提供了5種類型的Session供開發者使用:django

  • 數據庫(默認)
  • 緩存
  • 文件
  • 緩存+數據庫
  • 加密cookie

一、數據庫Sessionjson

Django默認支持Session,而且默認是將Session數據存儲在數據庫中,即:django_session 表中。
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默認)
     
    SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串(默認)
    SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路徑(默認)
    SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默認)
    SESSION_COOKIE_SECURE = False                            # 是否Https傳輸cookie(默認)
    SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http傳輸(默認)
    SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默認)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否關閉瀏覽器使得Session過時(默認)
    SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次請求都保存Session,默認修改以後才保存(默認)
 
 
 
b. 使用
 
    def index(request):
        # 獲取、設置、刪除Session中數據
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在則不設置
        del request.session['k1']
 
        # 全部 鍵、值、鍵值對
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用戶session的隨機字符串
        request.session.session_key
 
        # 將全部Session失效日期小於當前日期的數據刪除
        request.session.clear_expired()
 
        # 檢查 用戶session的隨機字符串 在數據庫中是否
        request.session.exists("session_key")
 
        # 刪除當前用戶的全部Session數據
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 若是value是個整數,session會在些秒數後失效。
            * 若是value是個datatime或timedelta,session就會在這個時間後失效。
            * 若是value是0,用戶關閉瀏覽器session就會失效。
            * 若是value是None,session會依賴全局session失效策略。

二、緩存Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cache'  # 引擎
    SESSION_CACHE_ALIAS = 'default'                            # 使用的緩存別名(默認內存緩存,也能夠是memcache),此處別名依賴緩存的設置
 
 
    SESSION_COOKIE_NAME = "sessionid"                        # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串
    SESSION_COOKIE_PATH = "/"                                # Session的cookie保存的路徑
    SESSION_COOKIE_DOMAIN = None                              # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                             # 是否Https傳輸cookie
    SESSION_COOKIE_HTTPONLY = True                            # 是否Session的cookie只支持http傳輸
    SESSION_COOKIE_AGE = 1209600                              # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                   # 是否關閉瀏覽器使得Session過時
    SESSION_SAVE_EVERY_REQUEST = False                        # 是否每次請求都保存Session,默認修改以後才保存
 
 
 
b. 使用
 
    同上

三、文件Session

a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.file'    # 引擎
    SESSION_FILE_PATH = None                                    # 緩存文件路徑,若是爲None,則使用tempfile模塊獲取一個臨時地址tempfile.gettempdir()                                                            # 如:/var/folders/d3/j9tj0gz93dg06bmwxmhh6_xm0000gn/T
 
 
    SESSION_COOKIE_NAME = "sessionid"                          # Session的cookie保存在瀏覽器上時的key,即:sessionid=隨機字符串
    SESSION_COOKIE_PATH = "/"                                  # Session的cookie保存的路徑
    SESSION_COOKIE_DOMAIN = None                                # Session的cookie保存的域名
    SESSION_COOKIE_SECURE = False                               # 是否Https傳輸cookie
    SESSION_COOKIE_HTTPONLY = True                              # 是否Session的cookie只支持http傳輸
    SESSION_COOKIE_AGE = 1209600                                # Session的cookie失效日期(2周)
    SESSION_EXPIRE_AT_BROWSER_CLOSE = False                     # 是否關閉瀏覽器使得Session過時
    SESSION_SAVE_EVERY_REQUEST = False                          # 是否每次請求都保存Session,默認修改以後才保存
 
b. 使用
 
    同上

四、緩存+數據庫Session

數據庫用於作持久化,緩存用於提升效率
 
a. 配置 settings.py
 
    SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'        # 引擎
 
b. 使用
 
    同上

五、加密cookie Session

a. 配置 settings.py
     
    SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'   # 引擎
 
b. 使用
 
    同上

模型操做

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

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

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

  • PHP:activerecord
  • Java:Hibernate
  • C#:Entity Framework

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

Django的配置:

'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 's2day19',    ## 數據庫名稱
        'USER': 'root',
        'PASSWORD': '123qwe',    ## 安裝 mysql 數據庫時,輸入的 root 用戶的密碼
        'HOST': '127.0.0.1',
    }

1、建立表

一、基本結構

from django.db import models
  
class userinfo(models.Model):
    name = models.CharField(max_length=30)
    email = models.EmailField()
    memo = models.TextField()

二、字段

AutoField(Field)
        - int自增列,必須填入參數 primary_key=True

BigAutoField(AutoField)
        - bigint自增列,必須填入參數 primary_key=True

        注:當model中若是沒有自增列,則自動會建立一個列名爲id的列
        from django.db import models

        class UserInfo(models.Model):
            # 自動建立一個列名爲id的且爲自增的整數列
            username = models.CharField(max_length=32)

        class Group(models.Model):
            # 自定義自增列
            nid = models.AutoField(primary_key=True)
            name = models.CharField(max_length=32)

    SmallIntegerField(IntegerField):
        - 小整數 -32768 ~ 32767

    PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正小整數 0 ~ 32767
    IntegerField(Field)
        - 整數列(有符號的) -2147483648 ~ 2147483647

    PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField)
        - 正整數 0 ~ 2147483647

    BigIntegerField(IntegerField):
        - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807

    自定義無符號整數字段

        class UnsignedIntegerField(models.IntegerField):
            def db_type(self, connection):
                return 'integer UNSIGNED'

        PS: 返回值爲字段在數據庫中的屬性,Django字段默認的值爲:
            'AutoField': 'integer AUTO_INCREMENT',
            'BigAutoField': 'bigint AUTO_INCREMENT',
            'BinaryField': 'longblob',
            'BooleanField': 'bool',
            'CharField': 'varchar(%(max_length)s)',
            'CommaSeparatedIntegerField': 'varchar(%(max_length)s)',
            'DateField': 'date',
            'DateTimeField': 'datetime',
            'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
            'DurationField': 'bigint',
            'FileField': 'varchar(%(max_length)s)',
            'FilePathField': 'varchar(%(max_length)s)',
            'FloatField': 'double precision',
            'IntegerField': 'integer',
            'BigIntegerField': 'bigint',
            'IPAddressField': 'char(15)',
            'GenericIPAddressField': 'char(39)',
            'NullBooleanField': 'bool',
            'OneToOneField': 'integer',
            'PositiveIntegerField': 'integer UNSIGNED',
            'PositiveSmallIntegerField': 'smallint UNSIGNED',
            'SlugField': 'varchar(%(max_length)s)',
            'SmallIntegerField': 'smallint',
            'TextField': 'longtext',
            'TimeField': 'time',
            'UUIDField': 'char(32)',

    BooleanField(Field)
        - 布爾值類型

    NullBooleanField(Field):
        - 能夠爲空的布爾值

    CharField(Field)
        - 字符類型
        - 必須提供max_length參數, max_length表示字符長度

    TextField(Field)
        - 文本類型

    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   上傳圖片的寬度保存的數據庫字段名(字符串)

    DateTimeField(DateField)
        - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]

    DateField(DateTimeCheckMixin, Field)
        - 日期格式      YYYY-MM-DD

    TimeField(DateTimeCheckMixin, Field)
        - 時間格式      HH:MM[:ss[.uuuuuu]]

    DurationField(Field)
        - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型

    FloatField(Field)
        - 浮點型

    DecimalField(Field)
        - 10進制小數
        - 參數:
            max_digits,小數總長度
            decimal_places,小數位長度

    BinaryField(Field)
        - 二進制類型

三、參數

null                數據庫中字段是否能夠爲空
    db_column           數據庫中字段的列名
    db_tablespace
    default             數據庫中字段的默認值
    primary_key         數據庫中字段是否爲主鍵
    db_index            數據庫中字段是否能夠創建索引
    unique              數據庫中字段是否能夠創建惟一索引
    unique_for_date     數據庫中字段【日期】部分是否能夠創建惟一索引
    unique_for_month    數據庫中字段【月】部分是否能夠創建惟一索引
    unique_for_year     數據庫中字段【年】部分是否能夠創建惟一索引

    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'), ]
                            )

四、連表操做

  • 一對多: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()                                                 # 修改單條數據

二、進階操做

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

# 大於,小於
#
# models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值
# models.Tb1.objects.filter(id__gte=1)              # 獲取id大於等於1的值
# models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值
# models.Tb1.objects.filter(id__lte=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

# isnull
# Entry.objects.filter(pub_date__isnull=True)

# 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

# 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"

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

# date
#
# Entry.objects.filter(pub_date__date=datetime.date(2005, 1, 1))
# Entry.objects.filter(pub_date__date__gt=datetime.date(2005, 1, 1))

# year
#
# Entry.objects.filter(pub_date__year=2005)
# Entry.objects.filter(pub_date__year__gte=2005)

# month
#
# Entry.objects.filter(pub_date__month=12)
# Entry.objects.filter(pub_date__month__gte=6)

# day
#
# Entry.objects.filter(pub_date__day=3)
# Entry.objects.filter(pub_date__day__gte=3)

# week_day
#
# Entry.objects.filter(pub_date__week_day=2)
# Entry.objects.filter(pub_date__week_day__gte=2)

# hour
#
# Event.objects.filter(timestamp__hour=23)
# Event.objects.filter(time__hour=5)
# Event.objects.filter(timestamp__hour__gte=12)

# minute
#
# Event.objects.filter(timestamp__minute=29)
# Event.objects.filter(time__minute=46)
# Event.objects.filter(timestamp__minute__gte=29)

# second
#
# Event.objects.filter(timestamp__second=31)
# Event.objects.filter(time__second=2)
# Event.objects.filter(timestamp__second__gte=31)

2.1 高級操做

# extra
    #
    # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None)
    #    Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,))
    #    Entry.objects.extra(where=['headline=%s'], params=['Lennon'])
    #    Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"])
    #    Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid'])

    # F
    #
    # from django.db.models import F
    # models.Tb1.objects.update(num=F('num')+1)


    # Q
    #
    # 方式一:
    # Q(nid__gt=10)
    # Q(nid=8) | Q(nid__gt=10)
    # Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')

    # 方式二:
    # con = Q()
    # q1 = Q()
    # q1.connector = 'OR'
    # q1.children.append(('id', 1))
    # q1.children.append(('id', 10))
    # q1.children.append(('id', 9))
    # q2 = Q()
    # q2.connector = 'OR'
    # q2.children.append(('c1', 1))
    # q2.children.append(('c1', 10))
    # q2.children.append(('c1', 9))
    # con.add(q1, 'AND')
    # con.add(q2, 'AND')
    #
    # models.Tb1.objects.filter(con)


    # 執行原生SQL
    #
    # from django.db import connection, connections
    # cursor = connection.cursor()  # cursor = connections['default'].cursor()
    # cursor.execute("""SELECT * from auth_user where id = %s""", [1])
    # row = cursor.fetchone()

其餘操做

三、一對一操做

# 一對多的添加
# models.students.objects.create(stuname='二狗子', classid_id=2)
# models.students.objects.create(stuname='狗剩子', classid_id=1)
# models.students.objects.create(stuname='鐵蛋', classid_id=2)
# models.students.objects.create(stuname='王鋼蛋', classid_id=3)
# models.students.objects.create(stuname='鐵錘', classid_id=1)

# 一對多的查詢 classid爲FK字段 正向操做
# res = models.students.objects.all()
#
# for item in res:
#     print(item.id, item.stuname, item.classid_id, item.classid.classname)


# 反向操做
# obj.小寫表名_set.all()
# res = models.classes.objects.filter(classname='週末一期').first()
# print(res.id, res.classname)
#
# info = (res.students_set.all())
#
# for item in info:
#     print(item.stuname)

# 獲取特定的字段 values() 和 values_list() 以及神奇的雙下劃線
# res = models.classes.objects.all().values('classname')
# print(res)
# for item in res:
#     print(item['classname'])

# res = models.students.objects.all().values_list('stuname', 'classid_id', 'classid__classname')
# print(res)

# res = models.students.objects.filter(classid__classname='週末一期')
# print(res)
# for item in res:
#     print(item.stuname)

四、多對多操做

user_info_obj = models.UserInfo.objects.get(name=u'xxx')
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')

自定義web框架

from wsgiref.simple_server import make_server


def index():
    return [b'index',]


def login():
    return [b'login',]


def routers():
    urlpatterns = (
        ('/index/', index),
        ('/login/', login),
    )

    return urlpatterns


def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']
    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == url:
            func = item[1]
            break
    if func:
        return func()
    else:
        return [b'404 not found',]


if __name__ == '__main__':
    httpd = make_server('', 8011, RunServer)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
- 開啓全局的csrf驗證
        1. settings中,打開註釋 'django.middleware.csrf.CsrfViewMiddleware',
        2. 表單中,開啓csrf_token
            <form>
                {% csrf_token %}
                <input type='text'>
            </form>
        如上, 全站都會進行csrf驗證

    - 開啓全局的csrf,可是部分業務函數不進行檢驗
        1. settings中,打開註釋 ====》'django.middleware.csrf.CsrfViewMiddleware',
        2. views中,引入以下函數
            from django.views.decorators.csrf import csrf_exempt
            @csrf_exempt
            def csrf1(request):
                if request.method == 'GET':
                    return render(request, 'csrf1.html')
                else:
                    return HttpResponse('ok')
        如上, 即使全局開啓驗證,可是可使用裝飾器進行特殊處理,不使用

    - 關閉全局的csrf, 可是部分業務函數要使用csrf驗證
        1. settings中,註釋 ===》 #'django.middleware.csrf.CsrfViewMiddleware',
        2. views中,引入以下函數
            from django.views.decorators.csrf import csrf_protect
            @csrf_protect
            def csrf1(request):
                if request.method == 'GET':
                    return render(request, 'csrf1.html')
                else:
                    return HttpResponse('ok')

    如果CBV:
        from django.utils.decorators import method_decorator
        @method_decorator(csrf_protect, name='get')
        class User(View):
            def get(self, request):
                pass

            def post(self, request):
                pass

    ajax方式提交數據:

         將token放置到請求頭中, 攜帶過來

            headers : {'X-CSRFToken': token}

Form組件

建立Form類時,主要涉及到 【字段】 和 【插件】,字段用於對用戶請求數據的驗證,插件用於自動生成HTML;

一、Django內置字段以下:

Field
    required=True,               是否容許爲空
    widget=None,                 HTML插件
    label=None,                  用於生成Label標籤或顯示內容
    initial=None,                初始值
    help_text='',                幫助信息(在標籤旁邊顯示)
    error_messages=None,         錯誤信息 {'required': '不能爲空', 'invalid': '格式錯誤'}
    validators=[],               自定義驗證規則
    localize=False,              是否支持本地化
    disabled=False,              是否能夠編輯
    label_suffix=None            Label內容後綴
 
 
CharField(Field)
    max_length=None,             最大長度
    min_length=None,             最小長度
    strip=True                   是否移除用戶輸入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             總長度
    decimal_places=None,         小數位長度
 
BaseTemporalField(Field)
    input_formats=None          時間格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            時間間隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定製正則表達式
    max_length=None,            最大長度
    min_length=None,            最小長度
    error_message=None,         忽略,錯誤信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否容許空文件
 
ImageField(FileField)      
    ...
    注:須要PIL模塊,pip3 install Pillow
    以上兩個字典使用時,須要注意兩點:
        - form表單中 enctype="multipart/form-data"
        - view函數中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                選項,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默認select插件
    label=None,                Label內容
    initial=None,              初始值
    help_text='',              幫助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查詢數據庫中的數據
    empty_label="---------",   # 默認空顯示內容
    to_field_name=None,        # HTML中value的值對應的字段
    limit_choices_to=None      # ModelForm中對queryset二次篩選
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   對選中的值進行一次轉換
    empty_value= ''            空值的默認值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   對選中的每個值進行一次轉換
    empty_value= ''            空值的默認值
 
ComboField(Field)
    fields=()                  使用多個驗證,以下:即驗證最大長度20,又驗證郵箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象類,子類中能夠實現聚合多個字典去匹配一個值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件選項,目錄下文件顯示在頁面中
    path,                      文件夾路徑
    match=None,                正則匹配
    recursive=False,           遞歸下面的文件夾
    allow_files=True,          容許文件
    allow_folders=False,       容許文件夾
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,若是是::ffff:192.0.2.1時候,可解析爲192.0.2.1, PS:protocol必須爲both才能啓用
 
SlugField(CharField)           數字,字母,下劃線,減號(連字符)
    ...
 
UUIDField(CharField)           uuid類型
    ...

views.py

from django.forms import Form
from django.forms import fields
from django.forms import Widget,PasswordInput

class LoginForm(Form):
    username = fields.CharField(
        required=True,

        # label='用戶名',
        # initial=666,
        # help_text='幫助信息',
        # # disabled=True,
        # label_suffix='--->',

        max_length=18,
        min_length=6,
        error_messages={
            'required' : '用戶名不能爲空',
            'max_length': '用戶名不能超過18',
            'min_length': '用戶名最小爲6',
        }
    )

    # password = fields.IntegerField(
    #     required=True,
    #     max_value=99999999,
    #     min_value=100000,
    #     error_messages={
    #         'required' : '密碼不能爲空',
    #         'invalid'  :  '格式不正確',
    #         'min_value': '密碼最少六位',
    #         'max_value': '密碼最多12位',
    #     },
    #     # widget=PasswordInput
    # )

    email = fields.EmailField()



def login(request):

    if request.method == 'GET':
        obj = LoginForm()
        print(obj)

        return render(request, 'login.html', {'obj':obj})
    else:
        # username = request.POST.get('username')
        # print(username)
        obj = LoginForm(request.POST)

        if obj.is_valid():
            print(obj.cleaned_data)
        else:
            errors = obj.errors
            # <ul class="errorlist">
            #   <li>username
            #       <ul class="errorlist">
            #           <li>This field is required.</li>
            #       </ul>
            #   </li>
            # </ul>

            # print(type(errors))
            # print(errors)

        return render(request, 'login.html', {'obj' : obj})

Django內置分頁

views.py

def user(request):

    # for i in range(300):
    #
    #     username = 'root' + str(i)
    #
    #     models.UserInfo.objects.create(username=username, nickname=username, gender=1, age=23)

    from django.core.paginator import Paginator

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

    res = models.UserInfo.objects.all()

    # per_page: 每頁顯示條目數量
    # count:    數據總個數
    # num_pages:總頁數
    # page_range:總頁數的索引範圍,如: (1,10),(1,200)
    # page:     page對象
    paginator = Paginator(res, 10)

    print(paginator)

    # has_next              是否有下一頁
    # next_page_number      下一頁頁碼
    # has_previous          是否有上一頁
    # previous_page_number  上一頁頁碼
    # object_list           分頁以後的數據列表
    # number                當前頁
    # paginator             paginator對象
    info = paginator.page(cur_page)

    return render(request, 'user.html', {'info':info})

user.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h3>信息以下</h3>

<ul>
    {% for item in info.object_list %}
        <li>
            {{ item.username }}
        </li>
    {% endfor %}
</ul>

<div>

     {% if info.has_previous %}
        <a href="/user/?cur_page={{ info.previous_page_number }}">上一頁</a>
    {% endif %}

    {% for item in info.paginator.page_range %}
        <a href="/user/?cur_page={{ item }}">{{ item }}</a>
    {% endfor %}


    {% if info.has_next %}
        <a href="/user/?cur_page={{ info.next_page_number }}">下一頁</a>
    {% endif %}


</div>

</body>
</html>

自定義分頁

class PageInfo(object):

    def __init__(self, cur_page, total, per_page, show_page=11):
        '''
        :param cur_page: 當前第幾頁
        :param total: 總共多少數據
        :param per_page: 每頁多少條數據
        '''

        try:
            self.cur_page = int(cur_page)
        except Exception as e:
            self.cur_page = 1

        self.per_page = per_page
        self.show_page = show_page

        a,b = divmod(total, self.per_page)
        if b:
            self.total_page_num = a + 1
        else:
            self.total_page_num = a

    def start(self):

        return (self.cur_page - 1) * self.per_page

    def end(self):

        return self.cur_page * self.per_page

    def pager(self):

        page_list = []

        half = int((self.show_page - 1) / 2)

        # 上一頁
        if self.cur_page == 1:
            prev_page = "<a class='page' href='#'>上一頁</a>"
        else:
            prev_page = "<a class='page' href='/custom/?cur_page=%s'>上一頁</a>" % (self.cur_page - 1,)
        page_list.append(prev_page)


        # 當總頁數少於11頁的時候,顯示全部的
        if self.total_page_num <= self.show_page:
            begin = 1
            end = self.total_page_num + 1
        else:

            # 當前頁 <= 5時, 作處理
            if self.cur_page <= half:
                begin = 1
                end = self.show_page + 1
            elif self.cur_page + half >= self.total_page_num:
                begin = self.cur_page - half
                end = self.total_page_num + 1
            else:
                begin = self.cur_page - half
                end = self.cur_page + half + 1



        for i in range(begin, end):

            if i == self.cur_page:
                v = "<a class='page active' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
            else:
                v = "<a class='page' href='/custom/?cur_page=%s'>%s</a>" % (i, i)
            page_list.append(v)


        if self.cur_page == self.total_page_num:
            next_page = "<a class='page' href='#'>下一頁</a>"
        else:
            next_page = "<a class='page' href='/custom/?cur_page=%s'>下一頁</a>" % (self.cur_page + 1,)
        page_list.append(next_page)

        return ' '.join(page_list)

django request.POST和request.body獲取值時出現的狀況

django request.POST / request.body
    當request.POST沒有值 須要考慮下面兩個要求
        1.若是請求頭中的: Content-Type: application/x-www-form-urlencoded   request.POST中才會有值(纔會去request.body中解析數據)
        2.若1有,也不必定有值 必須有數據格式要求: name=alex&age=18&gender=男


    如:
        a. form表單提交 默認就會知足上訴的1和2
            <form method...>
                input
            </form>

        b. ajax提交
            $.ajax({
                url:...
                type:POST,
                data:{
                    name:alex,
                    age=18,
                }     #默認也會知足上訴1和2  請求頭默認爲上述狀況 內部數據格式會轉爲上述狀況
            })

           自定義ajax 狀況一
           $.ajax({
                url:...
                type:POST,
                headers:{'Content-Type':"application/json"}  #不一樣的請求頭 致使request.POST獲取不了數據 而request.body依舊存在數據
                data:{name:alex, age = 18}   #內部自動轉換 name=alex&age=18

           }) #即body有值 POST無值

           自定義ajax 狀況二
           $.ajax({
                url:...
                type:POST,
                headers:{'Content-Type':"application/json"}  #不一樣的請求頭 致使request.POST獲取不了數據 而request.body依舊存在數據
                data:JSON.stringfy{name:alex, age = 18} #{name:alex,age:18}

           })  #body有值 POST無值
           #從 request.body裏獲取數據 而後再經過json.loads(request.body)
相關文章
相關標籤/搜索