【Python之路Day17】django

Python的WEB框架有Django、Tornado、Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM、模型绑定、模板引擎、缓存、Session等诸多功能。

安装环境:

通过“cmd”打开一个新的命令提示符窗口,直接输入:“django-admin.py”,如果提示:“'django- admin.py' 不是内部或外部命令,也不是可运行的程序或批处理文件,那么说明你还没有django环境,请先下载安装,之后配好环境变量。相关参考:http://blog.csdn.net/suofiya2008/article/details/5706057

 

创建一个django项目

命令:“django-admin.py startproject [projectname]”在当前目录下建立一个名为[projectname]的项目,上图为我创建的名为CrazyMonitor的django项目。

 

启动与访问:

  在当前项目的目录下使用命令python manage.py runserver可以启动当前项目:

  

 

程序目录

 

配置文件

 模版

TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates'),
    )

静态文件

STATICFILES_DIRS = (
        os.path.join(BASE_DIR,'static'),
    )

 

创建APP

 python manage.py startapp app01

 

路由(urls.py):

 

路由系统

1、每个路由规则对应一个view中的函数

1
2
3
url(r'^index/(\d*)', views.index),
url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),

2、根据app对路由规则进行一次分类

1
url(r'^web/',include('web.urls')),

django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。

 在mysite下面创建一个urls.py

from django.conf.urls import url
from django.contrib import admin
from UserManageSys.views import index, login, register, add_user, del_user

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/$', index),
    url(r'^$', login),
    url(r'^login/$', login),
    url(r'^register/$', register),
    url(r'^user/add/$', add_user),
    url(r'^user/del/$', del_user),
]

 

 

在usermanagesys下面的views里创建上面urls对应的函数

from django.shortcuts import render, redirect
from django.http import Http404, HttpResponse
from UserManageSys import models
# Create your views here.


def index(request):
    user_list_db = models.UserInfo.objects.all()
    return render(request, 'index.html', {'li': user_list_db})


def login(request):
    if request.method == 'POST':
        username = request.POST.get('username', None)
        password = request.POST.get('password', None)
        user_exist = models.UserInfo.objects.filter(username=username, password=password).count()
        if user_exist:
            request.session['username'] = username  
            return redirect('/index/')              
        else:
            return render(request, 'login.html')
    return render(request, 'login.html', {'code': 0})


def register(request):
    if request.method == 'POST':
        u = request.POST.get('username', None)
        p = request.POST.get('password', None)
        e = request.POST.get('email', None)
        already_user = models.UserInfo.objects.filter(username=u).count()
        print(already_user)
        if already_user:
            return render(request, 'register.html')
        else:
            models.UserInfo.objects.create(username=u, password=p, email=e)
            return render(request, 'register.html')
    return render(request, 'register.html')


def add_user(request):
    if request.method == 'POST':
        u = request.POST.get('username', None)
        p = request.POST.get('password', None)
        e = request.POST.get('email', None)
        print(u, p, e)
        user_info = {'username': u, 'email': e}
        already_user = models.UserInfo.objects.filter(username=u).count()
        print(already_user)
        if already_user:
            data = {'status': 1, 'result': '此用户已经存在!', 'data': user_info}
            return render(request, 'add_user.html', data)
        else:
            models.UserInfo.objects.create(username=u, password=p, email=e)
            data = {'status': 0, 'result': '用户添加成功!', 'data': user_info}
            return render(request, 'add_user.html', data)
    return render(request, 'add_user.html')


def del_user(request):
    if request.method == 'POST':
        u = request.POST.get('username', None)
        p = request.POST.get('password', None)
        e = request.POST.get('email', None)
        print(u, p, e)
        user_info = {'username': u, 'email': e}
        already_user = models.UserInfo.objects.filter(username=u).count()
        print(already_user)
        if already_user:
            models.UserInfo.objects.filter(username=u, password=p, email=e).delete()
            data = {'status': 1, 'result': '用户删除成功!', 'data': user_info}
            return render(request, 'del_user.html', data)
        else:
            data = {'status': 0, 'result': '用户不存在成功!', 'data': user_info}
            return render(request, 'del_user.html', data)

    return render(request, 'del_user.html')

 

动态路由

比如分页:当urls大量过多的时候比如几百个的时候,那么肯定不会去写几百个路由规则
所有这个时候就需要动态urls,使用正则表达式来完成

在usermanagesys下面的urls写入以下内容:

from django.conf.urls import url,include
from django.contrib import admin
# 导入app下的view函数
from . import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/(\d+)$', views.book), // 正则匹配
]

 

在usermanagesys下面的views写入以下内容:

from django.shortcuts import render,HttpResponse
# Create your views here.
def book(request,num):
    print(num)
    return HttpResponse(num)
当用户访问http://127.0.0.1:8000/usermanagesys/book/数字的时候
django会在自动把参数传给views里的book函数

多个参数它是已/来分割的

来一个url的加法

1.在usermanagesys下面的urls写入以下内容:

from django.conf.urls import url,include
from django.contrib import admin
#导入app下的view函数
from . import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/(\d+)/(\d+)$', views.book),
]
2.在helloapp下面的views写入以下内容:

def book(request,num1,num2):
    print(num1,num2)
    num = int(num1) + int(num2)
    return HttpResponse(num)
3.测试访问:
http://127.0.0.1:8000/usermanagesys/book/2/1
显示3
http://127.0.0.1:8000/usermanagesys/book/2/10
显示12

 

动态的路由(Key:value的形式)

1.在usermanagesys下面的urls写入以下内容:

from django.conf.urls import url,include
from django.contrib import admin
#导入app下的view函数
from . import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^book/(?P<k1>\d+)/(?P<k2>\d+)$', views.book),
    这里?p<v1>这里的v1就是key,vlaue就是传进去的值,
]
2.在usermanagesys下面的views写入以下内容:

from django.shortcuts import render,HttpResponse
# Create your views here.
def book(request,k1,k2):
    print(k1,k2)
    return HttpResponse(k1+k2)

 

 

 模板

1、模板语言

模板中也有自己的语言,该语言可以实现数据展示

    • {{ 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  

  a、在app中创建templatetags模块

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/env python
#coding:utf-8
from django import template
from django.utils.safestring import mark_safe
from django.template.base import resolve_variable, Node, TemplateSyntaxError
   
register = template.Library()
   
@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 文件名

1
{% load xx %}

  d、使用simple_tag

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

  e、在settings中配置当前app,不然django无法找到自定义的simple_tag

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',

总结:
filter
限制:传参(只能传两个参数)
支持:模版语言的 if 条件
simple_tag
不支持:模版语言的 if 条件

支持N多个参数

 

模版的继承

目的:同样的样式模板,不用重复写,

母板:

  内容

  {% block 名称 %} {% endblock %}

  内容


子板:
  {% extends '母板html文件名' %}


  {% block 名称 %}

  具体子页面的内容...

  {% endblock %}

具体事例:

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="..." />
    <style>
        .pg-header{
            height: 48px;
            background-color: cadetblue;
        }
        .pg-body{
            min-height: 500px;
        }
        .pg-body .body-menu{
            width: 20%;
            float: left;
        }
        .pg-body .body-content{
            width: 80%;
            float: left;
        }
        .pg-footer{
            height: 100px;
            background-color: brown;
        }
        .active{
            background-color: aquamarine;
            color: white;
        }
    </style>

    {% block css %}{% endblock %}
</head>
<body>
    <div class="pg-header">
        后台系统V1
    </div>
    <div class="pg-body">
        <div class="body-menu">
            <ul>
                <li><a id="userinfo" href="/web/userinfo">用户管理</a></li>
                <li><a id="assets" href="/web/assets">资产管理</a></li>
            </ul>
        </div>
        <div class="body-content">

            {% block body %}{% endblock %}
        </div>

    </div>
    <div class="pg-footer"></div>
    <script src="xxx"></script>
    {% block js %}{% endblock %}
</body>
</html>

 

继承以上模板

{% extends 'layout.html' %}

{% block css %}
    <style></style>
{% endblock %}

{% block body %}
    <ul>
    {% for item in user_list %}
        <li>{{ item.username }},{{ item.salary }}</li>
    {% endfor %}
    </ul>

{% endblock %}

{% block js %}
    <script>
        document.getElementById('userinfo').className = 'active';
    </script>
{% endblock %}

 

 

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'邮箱'}))

def __init__(self, *args, **kwargs):
    super(SampleImportForm, self).__init__(*args, **kwargs)

    self.fields['idc'].widget.choices = models.IDC.objects.all().order_by('id').values_list('id','display')
    self.fields['business_unit'].widget.choices = models.BusinessUnit.objects.all().order_by('id').values_list('id','name')

Forms
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中字段的定义

class AdminModelForm(forms.ModelForm):
      
    class Meta:
        model = models.Admin
        #fields = '__all__'
        fields = ('username', 'email')
          
        widgets = {
            'email' : forms.PasswordInput(attrs={'class':"alex"}),
        }

 

 

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、设置数据表名称

class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    class Meta:
        verbose_name = '用户类型'
        verbose_name_plural = '用户类型'

 


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

class UserType(models.Model):
    name = models.CharField(max_length=50)
  
    def __unicode__(self):   #显示设定的字段名字,而不是objct,好区分
        return self.name
from django.contrib import admin
  
from app01 import  models
  
class UserInfoAdmin(admin.ModelAdmin):
    list_display = ('username', 'password', 'email')
  
  
admin.site.register(models.UserType)
admin.site.register(models.UserInfo,UserInfoAdmin)
admin.site.register(models.UserGroup)
admin.site.register(models.Asset)
View Code

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

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)
View Code

e、添加快速过滤

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)

 

 

Ajax

 

ajax需要使用jquery

作用是偷偷的往后台发请求,页面不刷新

$.ajax({
        url: '/index/',
        type: 'POST',
        data: {'username': 'alex','password': '123'},
        success: function(data){
            // 当后台return之后,该函数自动执行
            // data就是后台返回的数据
        }
    })
    

 

具体的例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <div>
        <p>用户名:<input type="text" id="username" /></p>
    </div>
    <div>
        <p>用户名:<input type="password" id="pwd" /></p>
    </div>
    <input type="button" value="提交" onclick="SubmitForm();" />

    <script src="/static/jquery-1.8.2.min.js"></script>

    <script>
        function SubmitForm(){
            $.ajax({
                url: '/web/ajax_demo/',
                type: 'POST',
                data: {'user': $('#username').val(), 'pwd': $('#pwd').val()},
                dataType: 'json',
                success: function (data) {
                    // data = 字符串 {status:xx,message:''}
                    // data对象
                    //var data_dict = JSON.parse(data);
                    if(data.status){
                        location.href = "http://www.baidu.com";
                    }else{
                        alert(data.message);
                    }
                }
            })
        }
    </script>
</body>
</html>

 

后台views文件:

def ajax_demo(request):
    if request.method == 'POST':
        ret = {'status': False, 'message': ''}

        user = request.POST.get('user',None)
        pwd = request.POST.get('pwd',None)

        if user == '111' and pwd == '222':
            ret['status'] = True
            return HttpResponse(json.dumps(ret))
        else:
            ret['message'] = "用户名或密码错误"
            return HttpResponse(json.dumps(ret))
    return render(request, 'ajax_demo.html')

 

Model

 

D jango 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等数据库,只需要在settings.py中配置即可,不用更改models.py中的代码,丰富的API极大的方便了使用。

1、数据库的连接方式以及设置:
在Django中默认使用的数据库类型是sqlite3,如果想要使用其他数据库就需要在settings中设置数据库的连接方式:

 

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases
 
# sqlite3数据库连接方式
# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }
 
# MySQL数据库连接方式
DATABASES = {
    'default': {
    'ENGINE': 'django.db.backends.mysql',
    'NAME':'dbname',
    'USER': 'root',
    'PASSWORD': 'xxx',
    'HOST': '',
    'PORT': '',
    }
}

 

2、创建表

数据需要在models.py文件中创建

class UserInfo(models.Model):
    # CharField类型不能为空,最少要指定一个长度
    user = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
    pwd = models.CharField(max_length=32)
    user_type = models.ForeignKey('UserType')
 
class UserType(models.Model):
    nid = models.AutoField(primary_key=True) #默认是有隐藏自增id,加上primary_key=True,去掉默认,用自已定义的自增nid
    caption = models.CharField(max_length=16)

注:在创建外键的时候直接写上UserType和'UserType'的不加引号和加引号,区别就是python程序从上到下解释的顺序问题,如果把UserType这个类写到下面就会没事了

运行Djando项目程序,执行命令创建数据,会自动加载model文件创建定义的表和字段:

python3 manage.py makemigrations
python3 manage.py migrate

 

创建表的的参数:

1、models.AutoField  自增列 = int(11)
  #如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField  #字符串字段
  #必须 max_length 参数
3、models.BooleanField  #布尔类型=tinyint(1)
  #不能为空,Blank=True
4、models.ComaSeparatedIntegerField  #用逗号分割的数字=varchar
  继承CharField,所以必须 max_lenght 参数
5、models.DateField  日期类型 date
  对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField  日期类型 datetime
  同DateField的参数
7、models.Decimal  十进制小数类型 = decimal
  必须指定整数位max_digits和小数位decimal_places
8、models.EmailField  字符串类型(正则表达式邮箱) =varchar
  对字符串进行正则表达式
9、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、ipv4、ipv6
  验证时,会根据设置报错
14、models.NullBooleanField  允许为空的布尔类型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  减号、下划线、字母、数字
18、models.SmallIntegerField  数字
  数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正则表达式
22、models.BinaryField  二进制
23、models.ImageField   #只针对admin后台上传图片,默认上传在根目录
24、models.FilePathField 文件

更多字段
View Code
1、null=True
  数据库中字段是否可以为空
2、blank=True
  django的 Admin 中添加数据时是否可允许空值
3、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中字段的显示名称
9、name|db_column  数据库中的字段名称
10、unique=True  不允许重复
11、db_index = True  数据库索引
12、editable=True  在Admin里是否可编辑
13、error_messages=None  错误提示
14、auto_created=False  自动创建
15、help_text  在Admin中提示帮助信息
16、validators=[]
17、upload-to
更多参数

执行成功状态:

bogon:django_modes01 zk$ python3 manage.py makemigrations
Migrations for 'app01':
  app01/migrations/0001_initial.py:
    - Create model UserInfo
    - Create model UserType
    - Add field user_type to userinfo
bogon:django_modes01 zk$ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, app01, auth, contenttypes, sessions
Running migrations:
  Rendering model states... DONE
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying app01.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying sessions.0001_initial... OK
状态

 

 如果已经创建完毕并且已经填充了数据,需要修改字段,或添加字段,再执行

python3 manage.py migrate makemigrations ;可能会报错,这个就需要把字段定义个值,或定义此字段可以为空,

如果提示:No changes detected
需要在settings.py的配置文件检测一下有没有注册app

  

 

3、创建数据

创建数据的时候有两种方式:

第一种方式:

obj = models.表名(字段名='***')
obj.save()

 

第二种方式:

models.表名.objects.create(字段名='***')

在views.py中写入数据:

from django.shortcuts import render,HttpResponse
from app01 import models
 
# Create your views here.
 
def index(request):
    # 创建用户类型表
    models.UserType.objects.create(caption='管路员')
    models.UserType.objects.create(caption='普通用户')
    models.UserType.objects.create(caption='超级管理员')
 
    # 创建用户信息表
    user_info_dict_1 = {'user': 'ales',
                      'email': 'alex@qq.com',
                      'pwd': 123,
                      'user_type': models.UserType.objects.get(nid=1),
                      }
 
    user_info_dict_2 = {'user': 'eric',
                      'email': 'eric@qq.com',
                      'pwd': 123,
                      'user_type_id': 2,
                      }
 
    models.UserInfo.objects.create(**user_info_dict_1)
    models.UserInfo.objects.create(**user_info_dict_2)
    print('yes')
 
    return HttpResponse('ok')

 

 

4、连表关系:

  • 一对多,models.ForeignKey(ColorDic)
  • 一对一,models.OneToOneField(OneModel)
  • 多对多,authors = models.ManyToManyField(Author)

应用场景:

  • 一对一:在某表中创建一行数据时,有一个单选的下拉框(下拉框中的内容被用过一次就消失了)。

    例如:原有含10列数据的一张表保存相关信息,经过一段时间之后,10列无法满足需求,需要为原来的表再添加5列数据。

  • 一对多:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择)。

    例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等。

  • 多对多:在某表中创建一行数据是,有一个可以多选的下拉框。

    例如:创建用户信息,需要为用户指定多个爱好。

 

5、数据库基本操作

#
    #
    # 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__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等于11、22、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"

进阶操作(双下划线)
View Code

 

单表查询:

# ret = models.UserType.objects.all()

# print(ret.query)   
# ret.query后台返回的是查询的sql语句

 

  输出结果:

SELECT `app01_usertype`.`nid`, `app01_usertype`.`caption` FROM `app01_usertype`

 

  获取查询结果的类型:

ret = models.UserType.objects.all()
print(type(ret), ret)

  结果:

<class 'django.db.models.query.QuerySet'> <QuerySet [<UserType: UserType object>, <UserType: UserType object>, <UserType: UserType object>]>

 

  可以看到类型是一个QuerySet类型,后面是所有的对象,每一个元素就是一个对象,可以循环拿出每一次的数据:

ret = models.UserType.objects.all()
    print(type(ret), ret)
 
    for item in ret:
        print(item, item.nid, item.caption)

  取出的结果:

UserType object 1 管路员
UserType object 2 普通用户
UserType object 3 超级管理员

 

 

查询单个字段:

ret = models.UserType.objects.all().values('nid')
    print(type(ret), ret)

  结果查询出nid字段对应的所有的数据 :

<class 'django.db.models.query.QuerySet'> <QuerySet [{'nid': 1}, {'nid': 2}, {'nid': 3}]>

  可以看查询的sql语句,用query方法:

ret = models.UserType.objects.all().values('nid')
print(type(ret), ret.query)

  查询的结果:

<class 'django.db.models.query.QuerySet'> SELECT `app01_usertype`.`nid` FROM `app01_usertype`

 

 

 

  当通过values循环取值的时候,如下:

ret = models.UserType.objects.all().values('nid')
    print(type(ret), ret.query)
    for item in ret:
        print(item, type(item))

 

  结果:

<class 'django.db.models.query.QuerySet'> SELECT `app01_usertype`.`nid` FROM `app01_usertype`
{'nid': 1} <class 'dict'>
{'nid': 2} <class 'dict'>
{'nid': 3} <class 'dict'>

通过结果可以看出,最外部是QuerySet,内部元素封装了一个是封装了这一行所有数据的对象,另外只拿到了某几列的字典!

  

  当通过values_list循环取值的时候,如下:

ret = models.UserType.objects.all().values_list('nid')
    print(type(ret), ret)

  查询结果:

    
<class 'django.db.models.query.QuerySet'> <QuerySet [(1,), (2,), (3,)]>

 

 

连表查询:

连表查询的时候和sqlachemy有多不同,django没有join这个方法:

  通过UserInfo做连表查询

ret = models.UserInfo.objects.all()
    print(type(ret), ret)
    for item in ret:
        print(item, item.user_type, item.id, item.email, item.user, item.pwd)

  查询结果:

<class 'django.db.models.query.QuerySet'> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
UserInfo object UserType object 1 tom@qq.com tom 123
UserInfo object UserType object 2 jerry@qq.com jerry 123

 

首先输出的是查找出来的UserInfo用户信息表,封装了用户所有的信息,而UserType就是一个对象,这个对象里封装的就是一行信息对应的字段(nid和caption),取出UserType对应的信息,例如:

ret = models.UserInfo.objects.all()
print(type(ret), ret)
for item in ret:
        print(item, item.user_type, item.id, item.email, item.user, item.pwd)
        print(item.user_type.nid, item.user_type.caption)

 

  结果:

<class 'django.db.models.query.QuerySet'> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
UserInfo object UserType object 1 tom@qq.com tom 123
UserInfo object UserType object 2 jerry@qq.com jerry 123
1 管理员
2 普通用户

  

  如果只想看到数据对应的名称,就需要加映射values:

ret = models.UserInfo.objects.all().values('user', 'user_type__caption')
print(ret, ret.query)

 

  结果:

<QuerySet [{'user': 'ales', 'user_type__caption': '管路员'}, {'user': 'eric', 'user_type__caption': '普通用户'}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`)

通过结果可以看到user_type__caption可以跨表直接获取相应的结果,再看sql语句中django本身加上了一个join。

 

如果在models中在加上一个表"P",然后在UserType中增加一条外键指向"平"P",

需求:要查找UserInfo表中的name和UserType表中的caption和P表中的neme的方法就是在找下一个对象的时候继续加双下划线:

  增加的表结构:

 

  查询语法:

ret = models.UserInfo.objects.all().values('user', 'user_type__caption', 'user_type__p__name')
print(ret, ret.query)

  查询的结果:

<QuerySet [{'user_type__p__name': 'allan', 'user_type__caption': '管理员', 'user': 'ales'}, {'user_type__p__name': 'allan', 'user_type__caption': '普通用户', 'user': 'eric'}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption`, `app01_p`.`name` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) INNER JOIN `app01_p` ON (`app01_usertype`.`p_id` = `app01_p`.`id`)

 

   如果要拿用户类型是管理员的所有用户:

ret = models.UserInfo.objects.filter(user_type__caption="管理员").values('user', 'user_type__caption')
    print(ret)

  结果:

<QuerySet [{'user': 'tom', 'user_type__caption': '管理'}]>

 

 

5、下划线外键反向查找

  找到管理员相关联的信息:

obj = models.UserType.objects.filter(caption='管理员').first()
print(obj.nid, obj.caption)

 

这里查找的是usertype中的数据,如果通过usertype表查找到userinfo表中的信息就得用***_set:

obj = models.UserType.objects.filter(caption='管理员').first()
print(obj.nid, obj.caption)
print(obj.userinfo_set.all())
 
ret = models.UserType.objects.all().values('nid', 'caption', 'userinfo__user')
print(ret)
1 管理员
<QuerySet [<UserInfo: UserInfo object>]>
<QuerySet [{'caption': '管理员', 'userinfo__user': 'alex', 'nid': 1}, {'caption': '普通用户', 'userinfo__user': 'eric', 'nid': 2}, {'caption': '超级管理员', 'userinfo__user': None, 'nid': 3}]>
[27/Aug/2016 15:35:31] "GET /index/ HTTP/1.1" 200 2

 

  如果需要固定字段查找:

obj = models.UserType.objects.all().values('nid', 'userinfo__user')
    print(obj)

 

   结果:

<QuerySet [{'userinfo__user': 'alex', 'nid': 1}, {'userinfo__user': 'eric', 'nid': 2}, {'userinfo__user': None, 'nid': 3}]>

 

 

6、多对多之表创建

多对多创建表的时候直接使用ManyToManyField让django自动创建第三张表或者自己手动创建第三张表

models表结构(自定义的第三张表):

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')
 
class HostToGroup(models.Model):
    hgid = models.AutoField(primary_key=True)
    host_id = models.ForeignKey('Host')
    group_id = models.ForeignKey('Group')
    status = models.IntegerField()

 

views文件中插入数据:

models.Host.objects.create(hostname='c1', ip='1.1.1.1')
models.Host.objects.create(hostname='c2', ip='1.1.1.2')
models.Host.objects.create(hostname='c3', ip='1.1.1.3')
models.Host.objects.create(hostname='c4', ip='1.1.1.4')
models.Host.objects.create(hostname='c5', ip='1.1.1.5')
 
models.Group.objects.create(name='技术部')
models.Group.objects.create(name='财务部')
models.Group.objects.create(name='人事部')
models.Group.objects.create(name='公关部')
models.Group.objects.create(name='运营部')
models.Group.objects.create(name='销售部')
models.Group.objects.create(name='客服部')

 

 

操作表:

  获取财务部的对象:

obj = models.Group.objects.get(gid=2)
print(obj.gid, obj.name, obj.h2g.all())

 

   结果:

2 财务部 <QuerySet []>

 

 

给财务部添加主机:

# 添加一台主机      
obj = models.Group.objects.get(gid=2)
 # print(obj.gid, obj.name, obj.h2g.all())
 h1 = models.Host.objects.get(hid=1)
 obj.h2g.add(h1)
# 把剩下的全部添加
obj = models.Group.objects.get(gid=2)
 # print(obj.gid, obj.name, obj.h2g.all())
 # h1 = models.Host.objects.get(hid=1)
 q = models.Host.objects.filter(hid__gt=1)
 obj.h2g.add(*q)

 

 

将一台机器分配给多个组(就得用反向操作了):

h = models.Host.objects.get(hid=1)
h.group_set.add(*models.Group.objects.filter(gid__gt=2))

 

 

 

管理
posted @ 2016-09-03 04:08  也敲寡妇门  阅读(274)  评论(0编辑  收藏  举报