阿里山QQ

导航

Django web 进阶

1、路由系统

2、模板引擎

    simple_tag

3、Form

4、Ajax请求

    -简单数据

    -复杂数据

 

内容:
    -作业

    model

    xss、csrf(安全方面的内容)

    分页(公共的模块)
内容复习和今日内容

Django静态文件引用优化
存在两种引用方式:
1、方式1

2、方式2

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')]
        ,
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
                'django.core.context_processors.static',      #新增的内容
            ],
        },
    },
]

STATIC_URL = '/static/'
settings

为什么?

def static(request):
    """
    Adds static-related context variables to the context.
    """
    return {'STATIC_URL': settings.STATIC_URL}
from django.core.context_processors import static

对于views文件和templates来讲,在涉及较大量的时候,都应该进行分类处理,比如views\account.py类处理登录的函数,templates\account下的html文件为登录相关的html文件,如下

from django.conf.urls import url,include
from django.contrib import admin

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

urlpatterns = [
    url(r'^login/', account.login),
]
app01/urls
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render
def login(request):
    return render(request, "account/login.html")
account.py
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>abcd</h1>
    <h1>{{ STATIC_URL }}</h1>
    <script src="/static/js/jquery-2.1.4.min.js"></script>
    <script src="{{ STATIC_URL }}js/jquery-2.1.4.min.js"></script>
    <script src="{% static "js/jquery-2.1.4.min.js"%}"></script>

</body>
</html>
login.html

 

Form基本功能应用之保存用户输入内容


1、对于不同的函数使用的form,应该进行分类:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django import forms
class LoginForm(forms.Form):
    username = forms.CharField()            #字符串
    password = forms.CharField(widget=forms.PasswordInput)   #没有字符串的设定格式,通过widget进行设置
form\account.py

2、普通render方式如下,无法保存用户输入内容

点击submit之后,如果用户密码或用户名输入错误,密码和用户名输入框就会都变为空;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render
from  app01.forms import account as AccountForm
def login(request):
    '''
    if request.method == "POST":
        inp_obj = AccountForm.LoginForm(request.POST)       #封装了数据的对象,不仅可以做数据的验证,还可以将提交的数据再次显示到页面上去;
        return render(request, "account/login.html",{'obj':inp_obj})'''
    obj = AccountForm.LoginForm()
    return render(request, "account/login.html",{'obj':obj})       #没有封装数据的对象
views\account.py

 

采用如下方式,会保存用户名:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render
from  app01.forms import account as AccountForm    #为了区分views的account,使用as
def login(request):
    '''1、第一次登陆为get,不会执行if部分'''
    if request.method == "POST":
        inp_obj = AccountForm.LoginForm(request.POST)       #封装了数据的对象,不仅可以做数据的验证,还可以将提交的数据再次显示到页面上去;
        return render(request, "account/login.html",{'obj':inp_obj})
    obj = AccountForm.LoginForm()
    return render(request, "account/login.html",{'obj':obj})       #没有封装数据的对象
views/account.py

或者:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render
from  app01.forms import account as AccountForm    #为了区分views的account,使用as
def login(request):
    obj = AccountForm.LoginForm(request.POST)          #获取页面输入的数据
    if request.method == "POST":
        return render(request, "account/login.html",{'obj':obj})
    return render(request, "account/login.html",{'obj':obj})
views/account.py

 Form基本功能应用之验证以及错误信息

 下面利用form对于post提交的数据进行验证

对于error信息,有三种输出形式:

1、as_ul

2、as_data:用于form,和不用as_data相同;

3、as_json:用于Ajax;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render,HttpResponse
from  app01.forms import account as AccountForm    #为了区分views的account,使用as
def login(request):
    obj = AccountForm.LoginForm(request.POST)          #获取页面输入的数据
    if request.method == "POST":
        if obj.is_valid():
            all_data = obj.clean()
        else:
            #Form表单提交
            error = obj.errors
            print type(error)
            print error['username'],type(error['username'])
            print error['username'][0],type(error['username'][0])
            print error['username'][0]
            print error['password'][0]
            '''
            1、as_ul
            2、as_data
            3、as_json
           '''
            #Ajax
            #error = obj.errors.as_json()
            #return HttpResponse(error)
            #print error,type(error)
        return render(request, "account/login.html",{'obj':obj,'error':error})
    return render(request, "account/login.html",{'obj':obj})   #form返回obj对象
    #如果是ajax的话,return HttpReponse("字符串或者字符串类型的字典,不能为obj对象")
views\account.py
{% load staticfiles %}
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login/" method="post">
        <p>{{ obj.username }}
            <span style="color: red;">{% error_msg error.username %}</span>    #因为模板语言不支持obj.username[0]的方式取第一个错误信息,所以通过simple_tag来实现
        </p>
        <p>{{ obj.password }}</p>
        <input type="submit" value="submit" />

    </form>
    <h1>abcd</h1>
    <script src="/static/js/jquery-2.1.4.min.js"></script>
    <script src="{% static "js/jquery-2.1.4.min.js"%}"></script>
    <script>


    </script>

</body>
</html>
login.html
#!/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 error_msg(error_list):
    if error_list:
        return error_list[0]
    return ""
templatetags\xx.py

 

下面利用Ajax推数据进行提交:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django.shortcuts import render,HttpResponse
from  app01.forms import account as AccountForm    #为了区分views的account,使用as
def login(request):
    obj = AccountForm.LoginForm(request.POST)          #获取页面输入的数据
    if request.method == "POST":
        if obj.is_valid():
            all_data = obj.clean()
        else:
            #Form表单提交
            error = obj.errors
            print type(error)
            #print error['username'],type(error['username'])
            #print error['username'][0],type(error['username'][0])
            #print error['username'][0]
            #print error['password'][0]
            '''
            1、as_ul
            2、as_data
            3、as_json
           '''
            #Ajax
            error = obj.errors.as_json()
            return HttpResponse(error)
            print error,type(error)
        return render(request, "account/login.html",{'obj':obj,'error':error})
    return render(request, "account/login.html",{'obj':obj})   #form返回obj对象
    #如果是ajax的话,return HttpReponse("字符串或者字符串类型的字典,不能为obj对象")
views\account.py
{% load staticfiles %}
{% load xx %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login/" method="post">
        <p>{{ obj.username }}
            <span style="color: red;">{% error_msg error.username %}</span>
        </p>
        <p>{{ obj.password }}</p>
        <input type="submit" value="submit" />
        <input type="button" onclick="SubmitAjax();" value="Ajax" />

    </form>
    <h1>abcd</h1>
    <script src="/static/js/jquery-2.1.4.min.js"></script>
    <script src="{% static "js/jquery-2.1.4.min.js"%}"></script>
    <script>
        function SubmitAjax(){
            $.ajax({
                'url':'/login/',
                type:'POST',
                data: {'username':'','password':''},
                success:function(arg){
                    console.log(arg);
                }
        })
        }

    </script>

</body>
</html>
login.html

 Form功能应用之自动生成select标签


#!/usr/bin/env python
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from app01.forms import home as HomeForm
def index(request):
    obj = HomeForm.ImportForm()
    return render(request,'home/index.html',{'obj':obj})
views\home.py
#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django import forms
class ImportForm(forms.Form):
    HOST_TYPE_LIST = (
        (1,'物理机'),
        (2,'虚拟机')
    )
    host_type = forms.IntegerField(
        widget=forms.Select(choices=HOST_TYPE_LIST)
    )
    hostname = forms.CharField()
    import json
    '''
    f = open('db_admin','w')
    dic = ((1,"Charles"),(2,"wahaha"))

    f.write(json.dumps(dic))
    f.close()
    '''
    fr = open('db_admin')
    data = fr.read()
    print data,type(data)
    data_tuple = json.loads(data)
    fr.close()
    admin = forms.IntegerField(
        widget=forms.Select(choices=data_tuple)
    )
    '''如果没有下面的构造方法,在配置文件db_admin内容修改之后,select下面选择的内容不会改变;
    原因是根据类的定义,其静态字段在程序启动的时候会在内存中加载一次之后不会再改变,除非类重新加载(程序重启)
    因为静态字段是存在于类中的,而对于self.的方法,其存在于对象中,在对象被重新赋值的时候,值会改变,这样可以在刷新页面的
    时候,select下面的选择内容会改变'''
    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs)
        fr = open('db_admin')
        import json
        data = fr.read()
        print data,type(data)
        data_tuple = json.loads(data)
        fr.close()
        self.fields['admin'].widget.choices = data_tuple
forms\home.py
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>录入数据</h1>
    <form action="/index/">
        <p>{{ obj.host_type }}</p>
        <p>{{ obj.hostname }}</p>
        <p>{{ obj.admin }}</p>
    </form>
    <h1>数据列表</h1>

</body>
</html>
index.html
[[1, "Charles"], [2, "www"],[3,"ddddd"],[4,"gggggg"]]
db_admin

 

Form功能之生成动态select标签

上述代码可以进行优化:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django import forms
class ImportForm(forms.Form):
    HOST_TYPE_LIST = (
        (1,'物理机'),
        (2,'虚拟机')
    )
    host_type = forms.IntegerField(
        widget=forms.Select(choices=HOST_TYPE_LIST)
    )
    hostname = forms.CharField()
    admin = forms.IntegerField(
        widget=forms.Select()            #获取空值,在下面执行__init__方法的时候重新赋值
    )
    '''如果没有下面的构造方法,在配置文件db_admin内容修改之后,select下面选择的内容不会改变;
    原因是根据类的定义,其静态字段在程序启动的时候会在内存中加载一次之后不会再改变,除非类重新加载(程序重启)
    因为静态字段是存在于类中的,而对于self.的方法,其存在于对象中,在对象被重新赋值的时候,值会改变,这样可以在刷新页面的
    时候,select下面的选择内容会改变'''
    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs)
        fr = open('db_admin')      #在使用models的时候,可以使用数据库获取数据
        import json
        data = fr.read()
        print data,type(data)
        data_tuple = json.loads(data)
        fr.close()
        self.fields['admin'].widget.choices = data_tuple
forms\home.py

 

 

Model创建表之基础字段:

model中的数据库的错做为ORM;数据库通过model中的类表示,对象为其中的一行数据,对象.id ,对象.value为每行里面的数据;

其中settings中配置数据库:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}

#!/usr/bin/env python
#coding:utf-8
from __future__ import unicode_literals
from django.db import models

# Create your models here.
#ORM
#类-->数据库
#对象-->一行数据
#对象.id 对象.value -->每行里面的数据

class UserInfo(models.Model):         #默认情况下,表会生成两列
    name = models.CharField(max_length=32)
    ctime = models.DateTimeField(auto_now=True)   #创建时间字段,数据为当前时间
    uptime = models.DateTimeField(auto_now_add=True)    #更新数据,日期自动添加
    email1 = models.EmailField(max_length=32,null=True)    #表中添加一列,数据为null
    email2 = models.EmailField(max_length=32,default='123@123.com')   #表中添加一列,数据为'123@123.com'
    def __unicode__(self):     #输出对象的时候,输出数据库中一行数据为name的一列
        return self.name
app01\model
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from app01.forms import home as HomeForm
from  app01 import models
def index(request):
    models.UserInfo.objects.all().delete()     #删除数据
    before = models.UserInfo.objects.all()        #获取所有数据
    models.UserInfo.objects.create(name = 'Charles')    #添加数据
    after = models.UserInfo.objects.all()

    print before
    print after
    print after[0].ctime
    obj = HomeForm.ImportForm()
    return render(request,'home/index.html',{'obj':obj})
views\home.py

python manage.py syncdb命令同步数据库表,需要事先将app注册到settings中;

 

 

#!/usr/bin/env python
#coding:utf-8
from __future__ import unicode_literals
from django.db import models

# Create your models here.
#ORM
#类-->数据库
#对象-->一行数据
#对象.id 对象.value -->每行里面的数据

class UserInfo(models.Model):         #默认情况下,表会生成两列
    name = models.CharField(max_length=32)
    ctime = models.DateTimeField(auto_now=True)   #创建时间字段,数据为当前时间
    uptime = models.DateTimeField(auto_now_add=True)    #更新数据,日期自动添加
    email1 = models.EmailField(max_length=32,null=True)    #表中添加一列,数据为null
    email2 = models.EmailField(max_length=32,default='123@123.com')   #表中添加一列,数据为'123@123.com'
    ip=models.GenericIPAddressField(protocol="ipv4")
    img = models.ImageField(null=True,blank=True,upload_to="upload")    #blank=True表示在admin后台管理的时候允许为空   upload_to表示图片上传的路径,默认会自动创建

    def __unicode__(self):     #输出对象的时候,输出数据库中一行数据为name的一列
        return self.name
app01\model.py

通过admin来管理数据库表:

from django.contrib import admin

# Register your models here.
from app01 import models
admin.site.register(models.UserInfo)
app01\admin.py

 

Model创建表之字段参数:

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   图片
24、models.FilePathField 文件

更多字段
更多字段参数
AutoField()
BooleanField()
CharField()
CommaSeparatedIntegerField()
DateField()
DateTimeField()
DecimalField()
EmailField()
FilePathField()
FloatField()
IntegerField()
BinIntegerField()
IPAddressField()
TextField()
TimeField()
URLField()
BinaryField()
model字段

 

 

 

下面介绍通过Django上传文件示例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form action="/upload/" method="POST"  enctype="multipart/form-data">  //enctype="multipart/form-data"表示多个文件上传  
        <p><input type="file" name="f1"/></p>
        <p><input type="file" name="f2"/></p>
        <p><input type="text" name="hostname"/></p>
        <input type="submit" value="upload"/>
    </form>
</body>
</html>
template/home/upload.html
def upload(request):
    if request.method=='POST':
        inp_post = request.POST    #获取所有的text文本信息
        inp_files=request.FILES    #获取所有的上传的文件信息
        file_obj1 = inp_files.get('f1')
        print file_obj1.name,type(file_obj1)   #获取上传文件的文件名
        print '333333333'
        print inp_post
        f = open(file_obj1.name,'wb')
        for line in file_obj1.chunks():    #chunks表示将文件进行切片,然后写入通过内存写入文件
            f.write(line)
        f.close()

    return render(request,'home/upload.html')
app01/views/home.py

 

 Model创建表之一对多:外键,让两张表建立关系;

#!/usr/bin/env python
#coding:utf-8
from __future__ import unicode_literals
from django.db import models

# Create your models here.
#ORM
#类-->数据库
#对象-->一行数据
#对象.id 对象.value -->每行里面的数据

class UserInfo(models.Model):         #默认情况下,表会生成两列
    USER_TYPE_LIST=(
        (1,'f'),
        (2,'m'),
    )
    user_type = models.IntegerField(choices=USER_TYPE_LIST,default=1)
    name = models.CharField(max_length=32,primary_key=True,verbose_name="姓名",unique=True)
    ctime = models.DateTimeField(auto_now=True,)   #创建时间字段,数据为当前时间
    uptime = models.DateTimeField(auto_now_add=True,db_column="SB")    #更新数据,日期自动添加
    email1 = models.EmailField(max_length=32,null=True)    #表中添加一列,数据为null
    email2 = models.EmailField(max_length=32,default='123@123.com')   #表中添加一列,数据为'123@123.com'
    ip=models.GenericIPAddressField(protocol="ipv4")
    img = models.ImageField(null=True,blank=True,upload_to="upload")    #blank=True表示在admin后台管理的时候允许为空

    def __unicode__(self):     #输出对象的时候,输出数据库中一行数据为name的一列
        return self.name


class Color(models.Model):
    name = models.CharField(max_length=16)

class Somthing(models.Model):
    c1 = models.CharField(max_length=10)
    c2 = models.CharField(max_length=10)
    c3 = models.CharField(max_length=10)
    c4 = models.CharField(max_length=10)
    color = models.ForeignKey(Color)     #将两张表通过外键进行关联

class Business(models.Model):
    nid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)

class Host(models.Model):
    hostname = models.CharField(max_length=16)
    business = models.ForeignKey('Business',to_field='nid')   #指定app01business表的nid列为外键
app01/model.py

>python manage.py makemigrations    

python manage.py migrate

更新表结构;

 

 

 

 

Model创建表之多对多:一个人可以属于多个组,一个组可以包含多个人;

 需要创建第三张表,关联用户ID和组ID;

class UserGroup(models.Model):
    group_name = models.CharField(max_length=16)

class User(models.Model):
    name = models.CharField(max_length=16)
    email = models.CharField(max_length=16)
    mobile = models.CharField(max_length=16)
    user_user_group= models.ManyToManyField('UserGroup')    #创建的第三张表,将UserGroup表id和User表的id进行关联
app01/model.py

 

Model创建表之一对一:实际在数据库表创建的时候不存在;同一张表的同一列不能有重复的数据,否则不能insert进去;就是在一对多的基础上加上了不能重复的要求;

    比如用户名:密码:id等不能重复;

class User2(models.Model):
    name = models.CharField(max_length=16)
    email = models.CharField(max_length=16)
    mobile = models.CharField(max_length=16)

class AAdmin(models.Model):
    username = models.CharField(max_length=16)
    password = models.CharField(max_length=16)
    user_info = models.OneToOneField('User2')   #一对一两张表关联
app01/model.py

 

 Model操作表之基础操作

 增:

model.Tb1.objects.create(c1='xx',c2='oo') 
或者
obj = model.Tb1(c1='xx',c2='oo')
obj.save()
或者
dic = {'c1':'xx','c2':'oo'}     #可以将form提交的数据传入
model.Tb1.objects.create(**dic)

查:

model.Tb1.objects.get(id=123)  #获取一行,如果不存在,抛异常
model.Tb1.objects.all()    #获取全部
model.Tb1.objects.filter(name='seven','gender':'0')  #获取数据,可以用**dic替代括号中的内容

model.Tb1.objects.all().first()    #获取第一条数据
View Code

删:

model.Tb1.objects.filter(name='seven').delete()  

改:

model.Tb1.objects.filter(name='seven').update(gender='0')   #括号中的内容都可以通过**dic来替代

或者:
obj=model.Tb1.objects.get(id=1)   #获取对象
obj.c1='111'
obj.save()

好了,上面是关于表操作的基础部分,下面开始介绍如何在实际中操作:

1、创建表SimpleModel

class SimpleModel(models.Model):
    username = models.CharField(max_length=64)
    password = models.CharField(max_length=64)
app01/model.py

2、表数据的增加和查询:

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
from django.shortcuts import render
from app01.forms import home as HomeForm
from  app01 import models
def index(request):
    dic = {'username':'QQ','password':'123'}
    models.SimpleModel.objects.create(**dic)
    ret = models.SimpleModel.objects.all()
    print ret,type(ret),ret.query
    ret = models.SimpleModel.objects.all().values('username')
    print ret,type(ret)
    ret = models.SimpleModel.objects.all().values_list('username')
    print ret,type(ret)
    ret = models.SimpleModel.objects.all().values_list('id','username')
    print ret,type(ret)
    obj = HomeForm.ImportForm()
    return render(request,'home/index.html',{'obj':obj})
app01/views/home.py

3、替代之前将select的内容写入配置文件中的方式,采用数据库的方式:app01/forms/home.py

from django import forms
from app01 import models
class ImportForm(forms.Form):
    HOST_TYPE_LIST = (
        (1,'物理机'),
        (2,'虚拟机')
    )
    host_type = forms.IntegerField(
        widget=forms.Select(choices=HOST_TYPE_LIST)
    )
    hostname = forms.CharField()
    admin = forms.IntegerField(
        widget=forms.Select()            #获取空值,在下面执行__init__方法的时候重新赋值
    )
    '''如果没有下面的构造方法,在配置文件db_admin内容修改之后,select下面选择的内容不会改变;
    原因是根据类的定义,其静态字段在程序启动的时候会在内存中加载一次之后不会再改变,除非类重新加载(程序重启)
    因为静态字段是存在于类中的,而对于self.的方法,其存在于对象中,在对象被重新赋值的时候,值会改变,这样可以在刷新页面的
    时候,select下面的选择内容会改变'''
    def __init__(self, *args, **kwargs):
        super(ImportForm, self).__init__(*args, **kwargs)
        self.fields['admin'].widget.choices = models.SimpleModel.objects.all().values_list('id','username')
        '''
        fr = open('db_admin')      #在使用models的时候,可以使用数据库获取数据
        import json
        data = fr.read()
        print data,type(data)
        data_tuple = json.loads(data)
        fr.close()
        self.fields['admin'].widget.choices = data_tuple
View Code

4、将该数据库可以通过admin后台进行管理:

from django.contrib import admin

# Register your models here.
from app01 import models
admin.site.register(models.UserInfo)
admin.site.register(models.SimpleModel)
app01/admin.py

 

Admin定制:

class School(models.Model):
    name = models.CharField(max_length=128,unique=True)
    city = models.CharField(max_length=64)
    addr = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class UserProfile(models.Model):
    user = models.OneToOneField(User) #alex
    name = models.CharField(max_length=64)
    school = models.ForeignKey('School')


class ClassList(models.Model):
    course = models.ForeignKey(Course,verbose_name=u"课程")
    semester = models.IntegerField(verbose_name=u"学期")
    course_type = models.CharField(max_length=64,choices=course_type_choices,default='offline_weekend')
    teachers = models.ManyToManyField(UserProfile)
    start_date = models.DateField()
    graduate_date = models.DateField()

  

定制代码如下:

from django.contrib import admin
import models
# Register your models here.


class UserProfileAdmin(admin.ModelAdmin):
    list_display = ('id','user','name','school')     #定义要显示的字段,不能是多对多的字段
    search_fields = ('name','school__name')      #可以被搜索的字典,如果是通过外键关联,使用__表示
    list_filter = ('name','school__name')            #定义右侧通过哪些字段过滤出来的内容
    list_editable = ('name','user','school')      #定义哪些字段可以直接被编辑的
    list_per_page = 10                   #定义每页显示几行数据
    raw_id_fields = ('user','school')          #如果是通过外键关联的字段,可能存在许多选择的内容,优化选择


class ClassListAdmin(admin.ModelAdmin):
    list_display = ('course','semester','course_type','start_date','graduate_date')
    filter_horizontal = ('teachers',)          #多对多的字段,显示更加明显
admin.site.register(models.UserProfile,UserProfileAdmin)
admin.site.register(models.Customer)
admin.site.register(models.CustomerTrackRecord)
admin.site.register(models.ClassList,ClassListAdmin)
admin.site.register(models.Course)
admin.site.register(models.CourseRecord)
admin.site.register(models.StudyRecord)
admin.site.register(models.School)

 还有xadmin可以定制化漂亮的admin展示,有兴趣可以自己查!!

 

 

 

 

 

自定义Admin action

默认的admin action只要批量选择删除的功能,action只有在批量的时候才会有用;

def changeschool(modelAdmin,request,queryset):
    print '--->',request,queryset
    queryset.update(school=2)
    changeschool.short_description=u'set 2'


def changeschool1(modelAdmin,request,queryset):
    print '--->',request,queryset
    queryset.update(school=1)
    changeschool1.short_description=u'set 1'


class UserProfileAdmin(admin.ModelAdmin):
    list_display = ('id','user','name','school')
    search_fields = ('name','school__name')
    list_filter = ('name','school__name')
    list_editable = ('name','user','school')
    list_per_page = 10
    raw_id_fields = ('user','school')
    actions = [changeschool,changeschool1,]

  

 

 

Admin定制之加颜色

首先在model中定义方法:

class Customer(models.Model):
    qq = models.CharField(max_length=64,unique=True)
    name = models.CharField(verbose_name=u"姓名",max_length=32,blank=True,null=True)
    phone = models.BigIntegerField(blank=True,null=True)
    course = models.ForeignKey('Course')

    course_type = models.CharField(max_length=64,choices=course_type_choices,default='offline_weekend')
    consult_memo = models.TextField()
    source_type_choices = (('qq',u"qq群"),
                   ('referral',u"内部转介绍"),
                   ('51cto',u"51cto"),
                   ('agent',u"招生代理"),
                   ('others',u"其它"),
                   )

    source_type = models.CharField(max_length=64,choices=source_type_choices)

    def choice_source(self):
        if self.source_type == 'qq':
            format_td = format_html('<span style="padding:2px;background-color:pink;color:white"> %s</span>' %self.source_type)
        elif self.source_type == 'referral':
            format_td = format_html('<span style="padding:2px;background-color:pink;color:white"> %s</span>'%self.source_type)
        else:

            format_td = format_html('<span style="padding:2px;background-color:pink;color:blank"> %s</span>' %self.source_type)
        return format_td

    choice_source.short_description='source_type'     #修改admin显示的字段

  将定义的函数注册到Admin中:

class CustomerAdmin(admin.ModelAdmin):
    list_display = ('source_type','choice_source')

 

效果如下:

 

 

 

 Model操作表之进阶操作:

获取个数:
models.Tb1.objects.filter(name='seven').count()

大于,小于
models.Tb1.objects.filter(id__gt=1)
models.Tb1.objects.filter(id__lt=1)
models.Tb1.objects.filter(id__lt=10,id_gt=1)

in
models.Tb1.objects.flter(id__in=[11,22,33])
models.Tb1.objects.exclude(id__in=[11,22,33])

contains   类似于like
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])    #between  and


其他类似:
startwith,istartwith,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'))
models.Tb1.objects.all().values(id).annotate(c=Count('num'))    #以id进行分组,并计算相同组的num的最大值、最小值、和、个数等;
View Code

 

 连表操作(数据库数据插入和数据查询展示),一对多操作

1、创建用户组表和用户组表,并通过外键进行关联

class UserGroup_NEW(models.Model):
    caption = models.CharField(max_length=64)
    def __unicode__(self):
        return self.caption


class User_NEW(models.Model):
    username = models.CharField(max_length=64)
    user_group = models.ForeignKey('UserGroup_NEW')   #默认创建的外键会加上_id,可以使用db_clomn来修改为自定义的列名
    def __unicode__(self):
        return self.username
app01/models.py

2、form

#!/usr/bin/env python
# _*_ coding:utf-8 _*_

from django import forms
from app01 import models
class UserForm(forms.Form):
    username = forms.CharField()
    user_group_id = forms.IntegerField(       #采用方式2直接插入数据的话,需要加_id
        widget=forms.Select()            #获取空值,在下面执行__init__方法的时候重新赋值
    )
    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        self.fields['user_group_id'].widget.choices = models.UserGroup_NEW.objects.all().values_list('id','caption')
app01/forms/foreign.py

3、数据插入方式有两种:a、通过对象插入;b、直接插入;

#!/usr/bin/env python
# _*_ coding:utf-8 _*_
from django.shortcuts import HttpResponse,render
from app01 import models
from app01.forms import foreign as ForgienForm
def create_user_group(request):
    # models.UserGroup_NEW.objects.create(caption='CEO')    #向用户组中添加数据
    # models.UserGroup_NEW.objects.create(caption='CTO')
    # models.UserGroup_NEW.objects.create(caption='COO')
    return HttpResponse('ok')

def create_user(request):
    obj = ForgienForm.UserForm(request.POST)
    if request.method =="POST":
        print "数据提交"
        #print request.POST
        if obj.is_valid():
            all_data = obj.clean()
            print all_data
            #获取对象
            # group_obj = models.UserGroup_NEW.objects.get(all_data['use_group'])      方式1  通过对象级别插入数据,group_obj代表对象,是一列数据
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group=group_obj)
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group_id=all_data['user_group'])   #方式2:可以通过两种方式插入数据,默认在Django中插入外键会加_id,
                                                                                     #此种方法可以直接插入数据
            models.User_NEW.objects.create(**all_data)     #将方式2直接修改为此种方式创建数据
            print models.User_NEW.objects.all().count()
        else:
            pass
    user_list = models.User_NEW.objects.all()    #数据查询
    print user_list
    return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})
app01/views/foreign.py

4、html模板文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/create_user/" method="post">
    <p>{{ obj.username }}</p>
    <p>{{ obj.user_group_id }}</p>
    <input type="submit" value="submit"/>
</form>
    <table>
        {% for item in user_list %}
        <tr>
            <td>{{ item.username }}</td>
           <td>{{ item.user_group.caption }}</td>      {# 因为在model中的外键等一对多的操作,表示对象(就是一行数据),然后取一行数据的单独一列#}
        </tr>
        {% endfor %}
    </table>
</body>
</html>
create_user.html
[<User_NEW: Charles>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: QQ>]
[26/Jun/2016 17:40:50] "GET /create_user/ HTTP/1.1" 200 894
数据提交
{'username': u'wahaha', 'user_group_id': 1}
5
[<User_NEW: Charles>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: wahaha>]
[26/Jun/2016 17:41:03] "POST /create_user/ HTTP/1.1" 200 1023
[<User_NEW: Charles>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: wahaha>]
[26/Jun/2016 17:46:27] "GET /create_user/ HTTP/1.1" 200 1013
数据提交
{'username': u'aaa', 'user_group_id': 1}
6
[<User_NEW: Charles>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: QQ>, <User_NEW: wahaha>, <User_NEW: aaa>]
[26/Jun/2016 17:46:34] "POST /create_user/ HTTP/1.1" 200 1141
结果

 

通过get的方式获取想要查询的数据:

1、直接get获取数据库中的数据

def create_user(request):
    obj = ForgienForm.UserForm(request.POST)
    if request.method =="POST":
        print "数据提交"
        #print request.POST
        if obj.is_valid():
            all_data = obj.clean()
            print all_data
            #获取对象
            # group_obj = models.UserGroup_NEW.objects.get(all_data['use_group'])      方式1  通过对象级别插入数据,group_obj代表对象,是一列数据
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group=group_obj)
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group_id=all_data['user_group'])   #方式2:可以通过两种方式插入数据,默认在Django中插入外键会加_id,
                                                                                     #此种方法可以直接插入数据
            models.User_NEW.objects.create(**all_data)     #将方式2直接修改为此种方式创建数据
            print models.User_NEW.objects.all().count()
        else:
            pass
    val = request.GET.get('username')    #通过get的方式获取数据
    user_list = models.User_NEW.objects.filter(username=val)    #数据查询
    # user_list = models.User_NEW.objects.all()    #数据查询
    print user_list
    return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})
app01/views/foreign.py

2、get通过对象获取数据

####通过双下划线实现
def create_user(request):
    obj = ForgienForm.UserForm(request.POST)
    if request.method =="POST":
        print "数据提交"
        #print request.POST
        if obj.is_valid():
            all_data = obj.clean()
            print all_data
            #获取对象
            # group_obj = models.UserGroup_NEW.objects.get(all_data['use_group'])      方式1  通过对象级别插入数据,group_obj代表对象,是一列数据
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group=group_obj)
            # models.User_NEW.objects.create(hostname=all_data['username'],
            #                                user_group_id=all_data['user_group'])   #方式2:可以通过两种方式插入数据,默认在Django中插入外键会加_id,
                                                                                     #此种方法可以直接插入数据
            models.User_NEW.objects.create(**all_data)     #将方式2直接修改为此种方式创建数据
            print models.User_NEW.objects.all().count()
        else:
            pass
    # val = request.GET.get('username')    #通过get的方式获取数据
    # user_list = models.User_NEW.objects.filter(username=val)    #数据查询
    # user_list = models.User_NEW.objects.all()    #数据查询
    val = request.GET.get('usergroup')        #get获取对象的数据,通过__实现
    user_list = models.User_NEW.objects.filter(user_group__caption=val)
    print user_list
    return render(request,'foreign/create_user.html',{'obj':obj,'user_list':user_list})
app01/views/foreign.py

注意:1、在连表操作的时候,ForeignKey对应的行表示对象;2、添加数据的时候,默认需要在对应的列的名称后面加_id;3、获取数据的时候,如果是使用模板语言,可以使用item.user_group.caption来获取另外一张表的数据;如果使用filter查询指定的数据,使用双下划线__来获得另外一张表对应的数据;

总结作业:

1、user_group对应对象;

2、创建数据  user_group_id;

3、获取数据   通过模板加.

4、查询数据    filter加__   两个下划线表示跨一张表;

 

如果存在多张表通过外键进行关联:通过.filter(user_group__aa__name)进行数据查询

class A(models.Model):
    name = models.CharField(max_length=12)

class UserGroup_NEW(models.Model):
    caption = models.CharField(max_length=64)
    aa = models.ForeignKey('A')
    def __unicode__(self):
        return self.caption


class User_NEW(models.Model):
    username = models.CharField(max_length=64)
    user_group = models.ForeignKey('UserGroup_NEW')   #默认创建的外键会加上_id,可以使用db_clomn来修改为自定义的列名
    def __unicode__(self):
        return self.username

    # .filter(user_group__aa__name)
多张表通过外键关联

 后台也可以使用.连表来取数据:

for item in user_list:

    print item.user_group.caption

 

作业:

xx管理:
1、登录form
2、session    结合装饰器
3、装饰器
4、主机、主机组进行关联;
      添加:主机,主机组;
      删除
      修改
      查

 

 

 

 


posted on 2016-08-04 10:09  阿里山QQ  阅读(291)  评论(0编辑  收藏  举报