Django基础(二)

7、Model连表操作

  • 指定映射
  • 连表条件
  • 一对一
  • 多对多

    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
    
    表结构

一对一


1

2

3

4

5

6

7

8

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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

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

注意:xx_set中的【_set】是固定搭配

8、Form

django中的Form一般有两种功能:

  • 输入html
  • 验证用户输入

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django import forms
from django.core.exceptions import ValidationError

def mobile_validate(value):
    mobile_re = re.compile(r‘^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$‘)
    if not mobile_re.match(value):
        raise ValidationError(‘手机号码格式错误‘)

class PublishForm(forms.Form):

    user_type_choice = (
        (0, u‘普通用户‘),
        (1, u‘高级用户‘),
    )

    user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,
                                                                  attrs={‘class‘: "form-control"}))

    title = forms.CharField(max_length=20,
                            min_length=5,
                            error_messages={‘required‘: u‘标题不能为空‘,
                                            ‘min_length‘: u‘标题最少为5个字符‘,
                                            ‘max_length‘: u‘标题最多为20个字符‘},
                            widget=forms.TextInput(attrs={‘class‘: "form-control",
                                                          ‘placeholder‘: u‘标题5-20个字符‘}))

    memo = forms.CharField(required=False,
                           max_length=256,
                           widget=forms.widgets.Textarea(attrs={‘class‘: "form-control no-radius", ‘placeholder‘: u‘详细描述‘, ‘rows‘: 3}))

    phone = forms.CharField(validators=[mobile_validate, ],
                            error_messages={‘required‘: u‘手机不能为空‘},
                            widget=forms.TextInput(attrs={‘class‘: "form-control",
                                                          ‘placeholder‘: u‘手机号码‘}))

    email = forms.EmailField(required=False,
                            error_messages={‘required‘: u‘邮箱不能为空‘,‘invalid‘: u‘邮箱格式错误‘},
                            widget=forms.TextInput(attrs={‘class‘: "form-control", ‘placeholder‘: u‘邮箱‘}))

Form

Form

def publish(request):
    ret = {‘status‘: False, ‘data‘: ‘‘, ‘error‘: ‘‘, ‘summary‘: ‘‘}
    if request.method == ‘POST‘:
        request_form = PublishForm(request.POST)
        if request_form.is_valid():
            request_dict = request_form.clean()
            print request_dict
            ret[‘status‘] = True
        else:
            error_msg = request_form.errors.as_json()
            ret[‘error‘] = json.loads(error_msg)
    return HttpResponse(json.dumps(ret))

views

扩展:ModelForm

在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义


1

2

3

4

5

6

7

8

9

10

class AdminModelForm(forms.ModelForm):

    

    class Meta:

        model = models.Admin

        #fields = ‘__all__‘

        fields = (‘username‘‘email‘)

        

        widgets = {

            ‘email‘ : forms.PasswordInput(attrs={‘class‘:"alex"}),

        }

9、分页

分页功能在每个网站都是必要的,对于分页来说,其实就是根据用户的输入计算出应该在数据库表中的起始位置。

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

4、在数据表中根据起始位置取值,页面上输出数据



需求又来了,需要在页面上显示分页的页面。如:[上一页][1][2][3][4][5][下一页]

1、设定每页显示数据条数

2、用户输入页码(第一页、第二页...)

3、设定显示多少页号

4、获取当前数据总条数

5、根据设定显示多少页号和数据总条数计算出,总页数

6、根据设定的每页显示条数和当前页码,计算出需要取数据表的起始位置

7、在数据表中根据起始位置取值,页面上输出数据

8、输出分页html,如:[上一页][1][2][3][4][5][下一页]


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

#!/usr/bin/env python

# _*_coding:utf-8_*_

from django.utils.safestring import mark_safe

class PageInfo(object):

    def __init__(self,current,totalItem,peritems=5):

        self.__current=current

        self.__peritems=peritems

        self.__totalItem=totalItem

    def From(self):

        return (self.__current-1)*self.__peritems

    def To(self):

        return self.__current*self.__peritems

    def TotalPage(self):  #总页数

        result=divmod(self.__totalItem,self.__peritems)

        if result[1]==0:

            return result[0]

        else:

            return result[0]+1

def Custompager(baseurl,currentPage,totalpage):  #基础页,当前页,总页数

    perPager=11

    #总页数<11

    #0 -- totalpage

    #总页数>11

        #当前页大于5 currentPage-5 -- currentPage+5

            #currentPage+5是否超过总页数,超过总页数,end就是总页数

        #当前页小于5 0 -- 11

    begin=0

    end=0

    if totalpage <= 11:

        begin=0

        end=totalpage

    else:

        if currentPage>5:

            begin=currentPage-5

            end=currentPage+5

            if end > totalpage:

                end=totalpage

        else:

            begin=0

            end=11

    pager_list=[]

    if currentPage<=1:

        first="<a href=‘‘>首页</a>"

    else:

        first="<a href=‘%s%d‘>首页</a>" % (baseurl,1)

    pager_list.append(first)

    if currentPage<=1:

        prev="<a href=‘‘>上一页</a>"

    else:

        prev="<a href=‘%s%d‘>上一页</a>" % (baseurl,currentPage-1)

    pager_list.append(prev)

    for in range(begin+1,end+1):

        if == currentPage:

            temp="<a href=‘%s%d‘ class=‘selected‘>%d</a>" % (baseurl,i,i)

        else:

            temp="<a href=‘%s%d‘>%d</a>" % (baseurl,i,i)

        pager_list.append(temp)

    if currentPage>=totalpage:

        next="<a href=‘#‘>下一页</a>"

    else:

        next="<a href=‘%s%d‘>下一页</a>" % (baseurl,currentPage+1)

    pager_list.append(next)

    if currentPage>=totalpage:

        last="<a href=‘‘>末页</a>"

    else:

        last="<a href=‘%s%d‘>末页</a>" % (baseurl,totalpage)

    pager_list.append(last)

    result=‘‘.join(pager_list)

    return mark_safe(result)   #把字符串转成html语言

总结,分页时需要做三件事:

  • 创建处理分页数据的类
  • 根据分页数据获取数据
  • 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

10、Cookie和Session

操作Cookie

  获取cookie:request.COOKIES[key]

  设置cookie:response.set_cookie(key,value)

由于cookie保存在客户端的电脑上,所以,jquery也可以操作cookie。


1

2

<script src=‘/static/js/jquery.cookie.js‘></script>

$.cookie("list_pager_num"30,{ path: ‘/‘ });

操作Session

  获取session:request.session[key]

  设置session:reqeust.session[key] = value

  删除session:del request[key]


1

2

3

4

5

request.session.set_expiry(value)

* 如果value是个整数,session会在些秒数后失效。

* 如果value是个datatime或timedelta,session就会在这个时间后失效。

* 如果value是0,用户关闭浏览器session就会失效。

* 如果value是None,session会依赖全局session失效策略。

更多见:http://docs.30c.org/djangobook2/chapter14/

应用


1

2

3

4

5

6

7

def login(func):

    def wrap(request, *args, **kwargs):

        # 如果未登陆,跳转到指定页面

        if request.path == ‘/test/‘:

            return redirect(http://www.baidu.com)

        return func(request, *args, **kwargs)

    return wrap

  

11、Ajax


1

2

3

4

5

6

7

8

9

10

11

$.ajax({

    url:"/web/index/",

    data:{id:1,name:‘alex‘},

    type:‘POST‘,

    success:function(data){

    },

    error:function(){

    }

});

12、跨站请求伪造

简介

django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

全局:

  中间件 django.middleware.csrf.CsrfViewMiddleware

局部:

  • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

应用

1、普通表单


1

2

3

4

5

veiw中设置返回值:

  return render_to_response(‘Account/Login.html‘,data,context_instance=RequestContext(request))  

html中设置Token:

  {% csrf_token %}

2、Ajax

对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

view.py


1

2

3

4

5

6

7

8

9

10

from django.template.context import RequestContext

# Create your views here.

def test(request):

    if request.method == ‘POST‘:

        print request.POST

        return HttpResponse(‘ok‘)

    return  render_to_response(‘app01/test.html‘,context_instance=RequestContext(request))

text.html


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

<!DOCTYPE html>

<html>

<head lang="en">

    <meta charset="UTF-8">

    <title></title>

</head>

<body>

    {% csrf_token %}

    <input type="button" onclick="Do();"  value="Do it"/>

    <script src="/static/plugin/jquery/jquery-1.8.0.js"></script>

    <script src="/static/plugin/jquery/jquery.cookie.js"></script>

    <script type="text/javascript">

        var csrftoken = $.cookie(‘csrftoken‘);

        function csrfSafeMethod(method) {

            // these HTTP methods do not require CSRF protection

            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));

        }

        $.ajaxSetup({

            beforeSend: function(xhr, settings) {

                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {

                    xhr.setRequestHeader("X-CSRFToken", csrftoken);

                }

            }

        });

        function Do(){

            $.ajax({

                url:"/app01/test/",

                data:{id:1},

                type:‘POST‘,

                success:function(data){

                    console.log(data);

                }

            });

        }

    </script>

</body>

</html>

更多:https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

13、中间件

简介

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

中间件中可以定义四个方法,分别是:

  • process_request(self,request)
  • process_view(self, request, callback, callback_args, callback_kwargs)
  • process_exception(self, request, exception)
  • process_response(self, request, response)

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

自定义中间件

1、创建中间件类


1

2

3

4

5

6

7

8

9

10

11

12

class RequestExeute(object):

    

    def process_request(self,request):

        pass

    def process_view(self, request, callback, callback_args, callback_kwargs):

        =1

        pass

    def process_exception(self, request, exception):

        pass

    

    def process_response(self, request, response):

        return response

2、注册中间件


1

2

3

4

5

6

7

8

9

10

MIDDLEWARE_CLASSES = (

    ‘django.contrib.sessions.middleware.SessionMiddleware‘,

    ‘django.middleware.common.CommonMiddleware‘,

    ‘django.middleware.csrf.CsrfViewMiddleware‘,

    ‘django.contrib.auth.middleware.AuthenticationMiddleware‘,

    ‘django.contrib.auth.middleware.SessionAuthenticationMiddleware‘,

    ‘django.contrib.messages.middleware.MessageMiddleware‘,

    ‘django.middleware.clickjacking.XFrameOptionsMiddleware‘,

    ‘wupeiqi.middleware.auth.RequestExeute‘,

)

14、admin

django amdin是django提供的一个后台管理页面,改管理页面提供完善的html和css,使得你在通过Model创建完数据库表之后,就可以对数据进行增删改查,而使用django admin 则需要以下步骤:

  • 创建后台管理员
  • 配置url
  • 注册和配置django admin后台管理页面

1、创建后台管理员


1

python manage.py createsuperuser

2、配置后台管理url


1

url(r‘^admin/‘, include(admin.site.urls))

3、注册和配置django admin 后台管理页面

a、在admin中执行如下配置


1

2

3

4

5

6

7

8

from django.contrib import admin

from app01 import  models

admin.site.register(models.UserType)

admin.site.register(models.UserInfo)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

b、设置数据表名称


1

2

3

4

5

6

class UserType(models.Model):

    name = models.CharField(max_length=50)

    class Meta:

        verbose_name = ‘用户类型‘

        verbose_name_plural = ‘用户类型‘

c、打开表之后,设定默认显示,需要在model中作如下配置


1

2

3

4

5

class UserType(models.Model):

    name = models.CharField(max_length=50)

    def __unicode__(self):

        return self.name

+

d、为数据表添加搜索功能


1

2

3

4

5

6

7

8

9

10

11

12

from django.contrib import admin

from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):

    list_display = (‘username‘‘password‘‘email‘)

    search_fields = (‘username‘‘email‘)

admin.site.register(models.UserType)

admin.site.register(models.UserInfo,UserInfoAdmin)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

e、添加快速过滤


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

from django.contrib import admin

from app01 import  models

class UserInfoAdmin(admin.ModelAdmin):

    list_display = (‘username‘‘password‘‘email‘)

    search_fields = (‘username‘‘email‘)

    list_filter = (‘username‘‘email‘)

    

admin.site.register(models.UserType)

admin.site.register(models.UserInfo,UserInfoAdmin)

admin.site.register(models.UserGroup)

admin.site.register(models.Asset)

更多:http://docs.30c.org/djangobook2/chapter06/

完善主机管理系统:

  1. 登陆注册(利用ajax实现,使用onblur事件,检测当前用户名是否已经存在)
  2. 用户会话保持(Session)
  3. Form验证用户输入
  4. 自定义中间件记录请求IP(或黑名单)
  5. 用户管理、用户组管理、主机管理(增删改查,分页)
  6. 自定义页面表格行数(可选)
时间: 2024-10-12 16:46:13

Django基础(二)的相关文章

Django 基础二

一 模版 一模版的组成 HTML代码+逻辑控制代码 二 逻辑控制代码的组成 1  变量(使用双大括号来引用变量) {{var_name}} 2  标签(tag)的使用(使用大括号和百分比的组合来表示使用tag) {%load staticfiles%} 3 过滤器(filter)的使用 {{ship_date|date:"Fj,Y"}},ship_date变量传给data过滤器,date过滤器通过使用"FJ,Y"这几个参数来格式化日期数据."|"

django基础二

一 模版 一模版的组成 HTML代码+逻辑控制代码 二 逻辑控制代码的组成 1  变量(使用双大括号来引用变量) {{var_name}} 2  标签(tag)的使用(使用大括号和百分比的组合来表示使用tag) {%load staticfiles%} 3 过滤器(filter)的使用 {{ship_date|date:"Fj,Y"}},ship_date变量传给data过滤器,date过滤器通过使用"FJ,Y"这几个参数来格式化日期数据."|"

Django基础二之URL路由系统

一 URL配置 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表.你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码. 基本格式  from django.conf.urls import url #循环urlpatterns,找到对应的函数执行,匹配上一个路径就找到对应的函数执行,就不再往下循环了,并给函数传一个参数request,和

02.Django基础二之URL路由系统

一 URL配置 Django 1.11版本 URLConf官方文档 URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表.你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码. 基本格式 from django.conf.urls import url #循环urlpatterns,找到对应的函数执行,匹配上一个路径就找到对应的函数执行,就不再往下循环了,并给函数传一个参数request,和w

Python Day19-20(Django基础)

一.Django基础 1.基本配置补充 可以用pycharm一键创建工程和APP 其他常用命令: python manage.py runserver 1.1.1.1:8000 python manage.py startapp appname python manage.py syncdb python manage.py makemigrations python manage.py migrate python manage.py createsuperuser 数据库配置 setting

Django基础(一)

h1,h2,h3 { display: block } h1 { background-color: #e59373; text-align: center; color: black !important } h2 { background-color: #8aab30; width: 60% } h3 { background-color: #336699; color: white; width: 30% } 知识预览 一 Django基本命令 二 路由配置系统(URLconf) 三 编写

Python之路-(js正则表达式、前端页面的模板套用、Django基础)

js正则表达式 前端页面的模板套用 Django基础 js正则表达式: 1.定义正则表达式 /.../  用于定义正则表达式 /.../g 表示全局匹配 /.../i 表示不区分大小写 /.../m 表示多行匹配 登录注册验证: test: 判断字符串是否符合规定的规则 rep = /\d+/;   (定义规则) rep.test('')   (引号里面必须包含字母和数字才返回true,否则为false) rep = /^\d+$/; (只有是纯数字时候才返回true,否则是false) exe

Django基础和基本使用

Django基础 Django是Python下的一款著名的Web框架 框架 任何语言进入到高级部分时,会有认证.session.http.连接数据库等等功能操作,没有框架时需要自己实现 框架 是整个或部分系统的可重用设计,表现为一组抽象组件及组件实例间交互的方法: Django优点 自带轮子众多,方便快速开发 如Auth,Cache,模板等 天生的MVC设计模块 实用的后台管理 自带ORM,Template,Form,Auth核心组件 简洁的url设计 周边插件丰富 Django缺点 重 同步阻

Python学习之旅—Django基础

前言  前段时间业务比较繁忙,没时间更新博客,从这周开始将继续为各位更新博客.本次分享的主题是Django的基础部分,涵盖Django MTV三部分,并通过一个简单的班级管理系统来说明如何使用Django进行开发,好啦,开始今天的主题吧! 一.浅谈MVC.MTV和MVVM 要学习Django,我们很有必要了解下MVC,MTV和MVVM三种模式. [001]MVC MVC(Model View Controller 模型-视图-控制器)是一种Web架构的模式(本文不讨论桌面应用的MVC),它把业务