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/'
为什么?
def static(request): """ Adds static-related context variables to the context. """ return {'STATIC_URL': settings.STATIC_URL}
对于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")), ]
from django.conf.urls import url,include from django.contrib import admin from app01.views import account urlpatterns = [ url(r'^login/', account.login), ]
#!/usr/bin/env python # _*_ coding:utf-8 _*_ from django.shortcuts import render def login(request): return render(request, "account/login.html")
{% 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>
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进行设置
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}) #没有封装数据的对象
采用如下方式,会保存用户名:
#!/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}) #没有封装数据的对象
或者:
#!/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})
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对象")
{% 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>
#!/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 ""
下面利用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对象")
{% 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>
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})
#!/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
<!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>
[[1, "Charles"], [2, "www"],[3,"ddddd"],[4,"gggggg"]]
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
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
#!/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})
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
通过admin来管理数据库表:
from django.contrib import admin # Register your models here. from app01 import models admin.site.register(models.UserInfo)
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()
下面介绍通过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>
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')
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列为外键
>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进行关联
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') #一对一两张表关联
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() #获取第一条数据
删:
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)
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})
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
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)
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的最大值、最小值、和、个数等;
连表操作(数据库数据插入和数据查询展示),一对多操作
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
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')
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})
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>
[<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})
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})
注意: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、主机、主机组进行关联; 添加:主机,主机组; 删除 修改 查