django项目实例中模型的方法会在实例化的时候自动调用吗

Django 模型中一些自定义的总结 - 简书
Django 模型中一些自定义的总结
1.自定义管理器(Manager)
在语句Book.objects.all()中,objects是一个特殊的属性,通过它来查询数据库,它就是模型的一个Manager.
每个Django模型至少有一个manager,你可以创建自定义manager以定制数据库的访问.
这里有两个方法创建自定义manager:添加额外的修改manager返回的初始Queryset.
添加额外的manager
增加额外的manager是为模块添加表级功能的首选办法.(至于行级功能,也就是只作用于模型实例对象的函数,则通过自定义模型方法实现).
例如,为Book模型添加一个title_count()的manger方法,它接收一个keyword,并返回标题中包含keyword的书的数量.
#medols.py
from django.db import models
class BookManager(models.Manager):
def title_count(self, keyword):
return self.filter(title_icountains=keyword).count()
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
objects = BookManager()
def __str__(self):
return self.title
1.我们创建一个BookManager类,继承自django.db.models.Manager.它只有一个方法title_count(),来进行统计.注意,这个方法使用了self.filter(),这个self指manager本身.
2.将BookManager()赋值给模型的objects属性.它将取代模型的默认manager(objects).把它命名为objects是为了与默认的manager保持一致.
现在我们可以进行下面的操作:
&&& Books.objects.title_count('django')
#这是我们自定义的manager中的查询方法
&&& Books.objects.filter(title__icontains='django').count()
# 默认的查询方法依然可用
这样我们可以将经常使用的查询进行封装,就不必重复写代码了.
修改初始Manager Queryset
manager的基础Queryset返回系统中的所有对象.例如,Book.objects.all()返回book数据库中的所有书籍.你而已通过覆盖Manager.get_queryset()方法来重写manager的基础Queryset.get_queryset()应该按照你的需求返回一个Queryset.
例如,下面的模型有两个manger--一个返回所有对象,另一个仅返回作者是Roald Dahl的书
from django.db import models
#首先,定义一个Manager的子类
class DahlBookManager(models.Manager):
def get_queryset(self):
return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl')
# 然后,将它显式地插入到Book模型中
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
objects = models.Manager()
# 默认Manager
dahl_objects = DahlBookManager()
# 自定义的特殊Manager
在这个示例模型中,Book.objects.all()将返回数据库中的所有书籍,而Book.dahl_objects.all()只返回作者是Roald Dahl的书籍.注意我们明确的将objects设置为默认Manger的一个实例,因为如果我们不这样做,那么dahl_objects将成为唯一一个可用的manager.
由于get_queryset()返回一个Queryset对象,所以你可以使用filter(),exclude()和其他所有的Queryset方法.
如果你使用自定义的Manager对象,请注意,Django遇到的第一个Manager(以它在模型中被定义的位置为准)会有一个特殊状态。 Django将会把第一个Manager 定义为默认Manager ,Django的许多部分(但是不包括admin应用)将会明确地为模型使用这个manager。 结论是,你应该小心地选择你的默认manager。因为覆盖get_queryset()了,你可能接受到一个无用的返回对像,你必须避免这种情况.
2.自定义模型方法
为了给你的对像添加一个行级功能,那就定义一个自定义方法.鉴于manager经常被用来用一些整表操作(table-wide).模型方法应该只对特殊模型实例起作用.
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
def baby_boomer_status(self):
# Returns the person's baby_boomer status
import datetime
if self.birth_date & datetime.date():
return 'Pre-boomer'
elif self.birth_date & datetime.date():
return 'Baby boomer'
return 'Post-boomer'
def _get_full_name(self):
# Return the person's full name
return f'{self.first_name} {self.last_name}'
full_name = property(_get_full_name)
# 将类方法包装为属性
这些方法的使用:
&&& p = Person.objects.get(first_name='Barack', last_name='Obama')
&&& p.birth_date
datetime.date()
&&& p.baby_boomer_status()
'Baby boomer'
&&& p.full_name
# 注意这不是一个方法 -- 它被视为一个属性
'Barack Obama'
3.重写预定义的模型方法
还有一组模型方法了封装了一些你可能想要自定义的数据库行为.特别是你可能想要修改save()和delete()的工作方式.你可以自由的重写这些方法(以及其他的模型方法)来改变行为.重写内置方法的经典用例就是你想要在保存一个对象是做些其他的什么.例如:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
do_something()
super(Blog, self).save(*args, **kwargs)
#Call the "real" save() method.
do_something_else()
你也可以阻止保存行为:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def save(self, *args, **kwargs):
if self.name == 'Yoko Ono's Blog':
# Yoko shall never have her own blog!
super(Blog, self).save(*args, **kwargs)
#Call the "real" save() method
记住,继承超类的方法非常重要,即super(Blog, self).save(*args, **kwargs),它确保该对象仍被保存到数据库中.如果你忘记调用超类方法,那么默认的行为将不会发生,也不会发生数据库操作.
同样重要的是,您要传递可以传递给模型方法的参数——这就是*args, **kwargs所做的事情。Django将不时扩展内置模型方法的功能,并添加新的参数。如果您在方法定义中使用了*args, **kwargs,您将保证您的代码在添加时将自动支持这些参数。
Model.clean()
应用这个方法来提供自定义的模型验证,以及修改模型的属性.例如,你可以使用它来给一个字段自动提供值,或者用于多个字段需要一起验证的情形:
import detetime
from django.core.exceptions import ValidationError
from django.db import models
class Article(models.Model):
def clean(self):
# Don't allow draft entries to have a pub_date
if self.status == 'draft' and self.pub_date is not done:
raise ValidationEroor('Draft entries may not have a publication date')
#Set the pub_date for published items if it hasn't been set already
if self.status == 'published' and self.pub_date is None:
self.pub_date = datetime.date.today()
注意,调用模型的save()方法时,不会自动调用clean()方法,需要views手动调用.
上面的示例中,clean()引发的ValidationError异常通过一个字符串实例化,所以它将被保存在一个特殊的错误字典中,键为NON_FIELD_ERRORS.这个键用于整个模型出现的错误而不是一个特定字段穿线的错误:
from django.core.exceptions import ValidationError, NON_FIELD_ERRORS
article.full_clean()
except ValidationError as e:
non_field_errors = e.message_dict[NON_FIELD_ERRORS]
若要引发一个特定字段的异常,可以使用一个字典实例化ValidationError,其中字典的键为字段名.我们可以更新前面的例子,只引发pub_date字段上的异常:
class Article(models.Model):
def clean(self):
# Don't allow draft entries to have a pub_date.
if self.status == 'draft' and self.pub_date is not None:
raise ValidationError({'pub_date': 'Draft entries may not have a publication date.'})
原文:https://my.oschina.net/liuyuantao/blog/751438 查询集API 参考 本文档描述查询集 API 的细节。它建立在模型和数据库查询指南的基础上,所以在阅读本文档之前,你也许需要首先阅读这两部分的文档。 本文档将通篇使用在数据库查...
Django 1.8.2 文档Home | Table of contents | Index | Modules<>执行查询?一旦你建立好数据模型,Django 会自动为你生成一套数据库抽象的API,可以让你创建、检索、更新和删...
epub格式下载 感谢@Cluas 链接: https://pan.baidu.com/s/1kVGavLd 密码: raxg 全文链接 第一章 创建一个blog应用第二章 使用高级特性来增强你的blog第三章 扩展你的blog应用第四章上 创建一个社交网站第四章下 创建一...
本文转至:http://www.jianshu.com/p/a 创建第一个django应用 运行以下命令: 这个命令会创建应用的基本目录结构,类似下方结构: 设计博客的数据模型 我们将要为你的博客设计初始的数据模型。每一个model都是一个Python...
Django 文档协作翻译小组人手紧缺,有兴趣的朋友可以加入我们,完全公益性质。交流群:网站:http://python.usyiyi.cn/django/index.html 管理器 class Manager 管理器是一个接口,数据库查询操作通过它提供...
今天是加入好报30日群的第五天,也是第二周的(从9月1日开学那天起)周一(忙Day)。 其实早在半年前就看过好报关于这个活动的消息,只是那时想象每天500字是专业人士才可以做到的吧...虽然也有过“坐家梦”,但我深知自己视界不够开阔,感悟不够深刻,文章过于小情小调,属于哼哼...
我触摸着这本四月以来我一直带在身边的书,掩卷沉思,脑海中不断描绘着他所要呈现出来的那种富有动感的静止的美。如果有一天,我能有机会看一眼他的真迹,是不是我能更加真切的体会到他的存在?他的形象,随着他的画和他经历的一切,在我脑海越来越清晰。我是另一个玛雅,一路追寻着他的足迹,陪...
日本刀(にほんとう,Nihontou),这是外国人对日本传统刀剑的统称,其全称为平面碎段复体暗光花纹刃。依据形状、尺寸可分为太刀、打刀、肋差(肋指)、短刀等,其中日本人所称呼的刀,特指打刀这一形制的刀类;广义上的日本刀还包括长卷、剃刀、剑、枪等。自古以来,日本刀作为武器的同...
琳琅,也叫琅琅,但在最初我听成老琅,还心想,他才六岁而已呀!哈哈,惹得老师们大笑不止,我觉得我就是来搞笑的嘎嘎!
琅琅是大班刚转回来的一个学生,很不招人待见可以这么说,脾气坏,一旦想要的没立马得到就打同学,打老师,第一次见这样的孩子,真是逆天了。但我却很心...
1、and ‘and’逻辑符可以将任意表达式连在一起,并返回一个布尔类型的值。 2、while ‘while’后面没有条件,或者条件为真,则python会一直循环‘while’后面条件是“False、None、数字0、()、{}、[]”(ps:括号里面什么都没有)会被看做假...Error_404_资源不存在
404. 抱歉! 您访问的资源不存在!
请确认您输入的网址是否正确,如果问题持续存在,请发邮件至contact&#64;cnblogs.com与我们联系。Django的Model的继承有几种形式,分别是什么?
一、抽象继承:
顺便复习OOP思想,继承是面向对象的大前提╮(╯▽╰)╭,抽象类,之所以被创建是用来被继承的;一个类如果包含任何一种抽象方法,那么它就是抽象类;抽象方法一定要在子类中被复写;在继承关系中,抽象类永远在树枝节点上……扯远了,而且对于Python来说,已经没有这么多约束了。回到Django的Model,也一样,当我们需要某些公共
字段时,就需要一个父类为其他子类服务,这个父类没有manager,Django也不为这个类创建表,这种继承的定义方法如下:
class Animal(models.Model):
name = models.CharField(max_length=50)
age = models.PositiveIntegerField()
class Meta:
abstract = True
class Human(models.Model):
kind_hearted = models.BooleanField()
sex = models.CharField('sex', choices=(('m','male'), ('f', 'female')), max_length=1)
上例中,我们的Human子model中,自然包含了name和age的字段,但是Animal不能作为正常model使用,由于没有manager,所以也不能实例化、保存。在子类中,不可以建立与这个抽象父类中的相同的字段,Django表示对报错负责。
二、 正常的继承 , 多重继承 ,Joined映射
和抽象继承的主要区别是父类这时也可以拥有数据库表了,并且不在身为存储公共信息的抽象类了,父类也可以进行实例化,查询等操作了。
class Country(models.Model):
name = models.CharField(max_length=10)
class Province(Country):
return = models.BooleanField()
即在子类中只能增加方法,而不能增加属性,在不影响父类数据存储的前提下,使子类继承父类,此时子类称为父类的“代理”。例如:
from django.contrib.auth.models import User
class Person(User):
proxy = True
def can_dance(self):
return True
class Yellow(Person):
hometown = models.CharField(max_length=30)
class Black(Person)
tribe_name = models.CharField(max_length=100)
我们为Person类增加了一个方法,可以跳舞,并且保持了User的数据字段的不变。
Django的Queryset是什么,objects是什么,objects在哪里可以定义。
query + set,已经能猜出大概,它对应着数据库中的若干条记录。
例如有一个叫做Order的模型,在project的根目录下进入shell进行操作:
$python manage.py shell
&&&from app.order.models import Order
&&&type(Order.objects)
&class 'django.db.models.models.manager.Manager'&
&&&order = Order.objects.all()
&&&type(order)
&class 'django.db.models.query.QuerySet'&
上述方法很常用,看继承关系去理解Queryset和objets。objects是每个Model默认的manager类,通过manager的方法(也可通过QuerySet的方法得到,当然QuerySet也来自于manager),得到相应的Queryset,用以对数据库
字段进行更多的操作。
objects(manager)方法可以自定义添加,也可以直接赋值覆盖掉默认的管理方法。
试着添加一个新的管理器的步骤是这样,首先定义一个manager类继承自models.Manager ,并在其中对self进行操作,如下:
class OrderManager(models.Manager):
def title_count(self, keyword):
return self.filter(title__icontains=keyword).count()
class Order(models.Models):
title = models.CharField(max_length=100)
objects = OrderManager()
def __unicode__(self):
return self.title
上述例子中我们把 OrderManager 赋值给了objects,替换了默认的管理器。
tips:如果增加了新的管理器,且没有替换掉默认管理器,那么默认管理器需要显式的声明出来才可以使用。
Django中查询queryset时什么情况下用Q?
在进行相对复杂的查询时,使用 django.db.models.Q 对象。
例如需要进行复合条件的查询的SQL语句如下:
SELECT * FROM order WHERE id BETWEEN 20 ADN 100 AND(num &= '20' or num &= '30');
使用Q就可以写成:
from django.db.models import Q
from login.models import Order
Order.objects.get(
Q(id &= 20) & (id &= 100),
Q(num &= 20) | (num &= 30)
多嘴一句常识性问题啊…建数据库的时候避开各种关键字啊,否则忘了用``标记就报语法错误啊,
被leader骂成汪啊。
Django中想验证表单提交是否格式正确需要用到Form中的哪个函数?
is_valid()
方法,用于检查表单提交是否正确。
Django取消级联删除
这个文档写的比较清楚:
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
并且 SET_NULL 只有在 null 为True的时候,才可以使用。
Django中如何在Model保存前做一定的固定操作,比如写一句日志?
关键词: 信号
利用Django的Model的Signal Dispatcher, 通过django.db.models.signals.pre_save() 方法,在事件发生前,
触发信号,这一切都被调度中的receiver方法深藏功与名的保存了。
信号的处理一般都写在Model中,举个例子:
import logging
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver
class Order(models.Model):
logger = logging.getLogger(__name__)
@receiver(pre_save, sender=Order)
def pre_save_handler(sender, **kwargs):
logger.debug("{},{}".format(sender, **kwargs))
print 'fuck universe'
这样应该就实现了题中的要求,类似的方法还有比如 pre_init 是在Model实例之前会触发, post_init 在实例之后触发,同理就是 pre_save 和 post_save 了。
Django中如何读取和保存session,整个session的运行机制是什么。
说到session的运行机制,就一定要先说一下cookie这一段信息。一般情况下cookies都是我们的浏览器生成的(显然可以人为修改),用于服务器对户进行筛选和维护,但是这个听上去很好吃的东西,能存的东西有点少而且容易被别人利用。这时候基于cookies的session的意义就比较明显了,在客户端的cookies中我们只保存session id,而将完整信息以加密信息的形式保存到服务器端,这样服务器可以根据session id相对安全的在数据库中查询用户的更细致的信息和状态。
在Django中session和cookies的操作方法一样,如下:
request.session['order_id'] = order_id
del request.session['order_id']
session.get('order_id', False)
django的优缺点总结 - Python Web开发面试必备
Django是利用Python语言从事Web开发的首选框架。如果你以后想从事python web开发工作,就必需了解其优缺点。这些都可能会是你将来的面试题哦。Django的优点功能完善、要素齐全:自带...
Python练习Django项目——学习笔记
学习如何使用Django(http://djangoproject.com/ )来开发一个名为“学习笔记”(Learning Log)的项目,这是一个在线日志系统,让你能够记录所学习的有关特定...
来自非专业Python讲师的一份Django考题,面试无忧!
Django的面试题少之又少,然而对于Python程序员又不得不掌握。可以考察笔试者对于框架的理解和使用熟练度,展开了问,也可以问到很深的地方。Django的Model的继承有几种形式,分别是什么?(...
Django面试题系列(1)——migrate错误处理
如果想要深入学习Django,可以看下这个视频教程:超详细讲解Django打造大型企业官网
面试题1:migrate怎么判断哪些迁移脚本需要执行:
他会将代码中的迁移脚本和数据库中django_m...
Django面试题系列(2)-ORM实现复杂查询
如果您对Django感兴趣,可以看下这个超详细的课程:超详细讲解Django打造大型企业官网
假设有以下ORM模型:
from django.db import models
class S...
详解python django面向关系数据库的ORM对象映射系统(1)
django是一套开发成本低、迭代周期快的python web框架,而如mysql等关系数据库则是网站的必备组件,django通过设计一套python对象与数据库表的映射系统ORM,使得开发者不用写一...
没有更多推荐了,Django 千锋培训的学习笔记(1) - allenfeng33 - 博客园
随笔 - 30, 文章 - 1, 评论 - 1, 引用 - 0
Django 千锋培训读书笔记
https://www.bilibili.com/video/av/?p=1
切换到创建项目的目录
cd C:\Users\admin\Desktop\DjangoProject
创建名为project的项目命令
django-admin startproject project
注:所有路径不要有中文
切换到目录cd C:\Users\admin\Desktop\DjangoProject\project
目录层级说明:manage.py
一个命令行工具,可以让我们用多种方式对Django项目进行交互
__init__.py 一个空文件,它告诉Python这个目录应该被看做一个包
settings.py 项目的配置文件(主要处理文件)
项目的url声明 (主要处理文件)
项目与WSGI兼容的Web服务器入口
配置数据库
Django默认使用SQLite数据库
在settings.py文件中通过DATABASES选项进行数据库配置
Python3.x中安装的是PyMySQL
在__init__.py文件中写入两行代码import pymysql
pymysql.install_as_MySQLdb()
以数据库sunck为例进行示范:对settings.py中的DATABASES进行设置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': "sunck",
'USER': "root",
'PASSWORD': "admin123",
'HOST': "localhost",
'PORT': "<span style="color: #06"
创建应用--在一个项目中可以创建多个应用,每个应用进行一种业务处理
打开CMD,进入project(目录名)的目录下,输入命令创建名为myApp的app:
python manage.py startapp myAPP
myAPP目录说明
进行站点配置
在settings.py文件中,将myApp应用加入到INSTALLED_APPS选项中
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
定义模型 概述:有一个数据表就对应有一个模型
在models.py文件中定义模型
引入:from django.db import models
模型类要继承models.Model类
class Grades(models.Model):
gname = models.CharField(max_length=20)
gdate = models.DateTimeField()
ggirlnum = models.IntegerField()
gboynum = models.IntegerField()
isDelete = models.BooleanField(default=False)
class Students(models.Model):
sname = models.CharField(max_length=20)
sgender = models.BooleanField(default=True)
sage = models.IntegerField()
scontend = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
sgrade = models.ForeignKey("Grades", on_delete=models.CASCADE,)
不需要定义主键,在生成时自动添加,并且值为自动增加
在数据库中生成数据表
生成迁移文件
执行 python manage.py makemigrations
在migrations目录下生成一个迁移文件,此时数据库中还没有生成数据表
执行 python manage.py migrate
相当于执行MySQL语句创建了数据表
测试数据操作
进入到python shell
执行 python manage.py shell
from myApp.models import Grades, Students
from django.utils import timezone
from datetime import *
查询所有数据
类名.objects.all()
示例: Grades.objects.all()
本质:创建一个模型类的对象实例
示例:CMD窗口下:
grade1 = Grades()
grade1.gname = "python04"
grade1.gdate = datetime(year=2017, month=7, day=17)
grade1.ggirlnum = 3
grade1.gboynum = 70
grade1.save()
查看某个对象
类名.objects(pk=索引号)
Grades.objects.get(pk=2)
Grades.objects.all()
修改某个数据
模型对象属性 = 新值
grade2.gboynum = 60
grade2.save()
模型对象.delete()
grade2.delete()
注意:这是物理删除,数据库中的相应数据被永久删除
stu = Students()
stu.sname = "Xue Yanmei"
stu.sgender = False
stu.sage = 20
stu.scontend = "I am Xue Yanmei"
stu.sgrade = grade1
stu.save()
获得关联对象的集合
需求:猎取python04班级的所有学生
对象名.关联的类名小写_set.all()
示例:grade1.students_set.all()
需求:创建曾志伟,属于python04班级
stu3 = grade1.students_set.create(sname=u'Zhen Zhiwei',sgender=True,scontend=u"I am Zhen Zhiwei",sage=45)
注意:这样创建的数据直接被添加到了数据库当中。
启动服务器:
格式:python manage.py runserver ip:port
注意:ip可以不写,不写代表本机ip
端口号默认是8000
python manage.py runserver
这是一个纯python编写的轻量级web服务器,仅仅在开发测试中使用这个
Admin站点管理:
内容发布:负责添加,修改,删除内容的
配置Admin应用:
在settings.py文件中的INSTALLED_APPS中添加'django.contrib.admin',
这条默认是添加好的。
创建管理员用户:
在项目目录下执行 python manage.py createsuperuser
依次输入账号名,邮箱,密码即可完成用户创建
http://127.0.0.1:8000/admin/
把project\settings.py
中作如下设定:LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
管理数据表:
修改 myAPP\admin.py 如下:
from django.contrib import admin
# Register your models here.
from .models import Grades, Students
admin.site.register(Grades)
admin.site.register(Students)
自定义管理页面:
# 列表页属性
list_display = [] # 显示字段设置
list_filter = [] # 过滤字段设置
search_fields = [] # 搜索字段设置
list_per_page = [] # 分页设置
# 添加,修改页属性
fields = [] # 规定属性的先后顺序
fieldsets = [] # 给属性分组 注意:fields与fieldsets不能同时使用
属性示例:
# 列表页属性
list_display = ['pk', 'gname', 'gdate', 'ggirlnum', 'gboynum', 'isDelete']
list_filter = ['gname']
search_fields = ['gname']
list_per_page = 5
# 添加,修改页属性
# fields = ['ggirlnum', 'gboynum', 'gname', 'gdate', 'isDelete']
fieldsets = [
("num",{"fields":['ggirlnum', 'gboynum']}),
("base", {"fields":["gname", "gdate", "isDelete"]}),
关联对象:需求:在创建一个班级时可以直接添加几个学生
class StudentsInfo(admin.TabularInline):# 可选参数admin.StackedInline
model = Students
class GradesAdmin(admin.ModelAdmin):
inlines = [StudentsInfo]
布尔值显示问题示例:
class StudentsAdmin(admin.ModelAdmin):
def gender(self):
if self.sgender:
return "男"
return "女"
# 设置页面列的名称
gender.short_description = "性别"
list_display = ['pk', 'sname', 'sage', gender,
'scontend', 'sgrade', 'isDelete']
list_per_page = 10
admin.site.register(Students, StudentsAdmin)
执行按钮位置:
class StudentsAdmin(admin.ModelAdmin):
...snip...
actions_on_top = False
actions_on_bottom = True
admin.site.register(Students, StudentsAdmin)
使用装饰器完成注册:
@admin.register(Students)
class StudentsAdmin(admin.ModelAdmin):
def gender(self):
...snip...
actions_on_top = False
actions_on_bottom = True
视图的基本使用
在Django中,视图是对web请求进行回应
视图就是一个python函数,在views.py文件中定义。
定义视图:
示例:在myApp\views.py中写入
from django.shortcuts import render
# Create your views here.
from django.http import HttpResponse
def index(request):
return HttpResponse("Sunck is a good man")
配置url:方法一:path方法:
修改project目录下的urls.py文件:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myApp.urls')),
在myApp应用目录下创建urls.py文件:
from django.urls import path, include
from . import views
urlpatterns = [
path('',views.index),
配置url:方法二:url方法:
修改project目录下的urls.py文件:
from django.contrib import admin
from django.conf.urls import url,include
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('myApp.urls')),
在myApp应用目录下创建urls.py文件:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index),
模板的基本使用:
概述:模板是HTML页面,可以根据视图中传递过来的数据进行填充
创建模板:
创建templates目录,在目录下创建对应项目的模板目录(project/templates/myApp)
配置模板路径:
修改settings.py文件下的TEMPLATES下的'DIRS'为'DIRS': [os.path.join(BASE_DIR, 'templates')],
定义grades.html与students.html模板:
在templates\myApp\目录下创建grades.html与students.html模板文件
模板语法:
{{输出值,可以是变量,也可以是对象,属性}}
{%执行代码段%}
http://127.0.0.1:8000/grades
写grades.html模板:
&!doctype html&
&html lang="en"&
&meta charset="UTF-8"&
&meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"&
&meta http-equiv="X-UA-Compatible" content="ie=edge"&
&title&班级信息&/title&
&h1&班级信息列表&/h1&
&!--[python04, python05, python06]--&
{%for grade in grades%}
&a href="#"&{{grade.gname}}&/a&
{%endfor%}
定义视图:myApp\views.py
from .models import Grades
def grades(request):
# 去模板里取数据
gradesList = Grades.objects.all()
# 将数据传递给模板,模板再渲染页面,将渲染好的页面返回给浏览器
return render(request, 'myApp/grades.html', {"grades": gradesList})
配置url:myApp\urls.py
urlpatterns = [
url(r'^$', views.index),
url(r'^(\d+)/(\d+)$', views.detail),
url(r'^grades/', views.grades)
http://127.0.0.1:8000/students
写students.html模板
&!doctype html&
&html lang="en"&
&meta charset="UTF-8"&
&meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"&
&meta http-equiv="X-UA-Compatible" content="ie=edge"&
&title&学生页面&/title&
&h1&学生信息列表&/h1&
{%for student in students%}
{{student.sname}}--{{student.scontend}}
{%endfor%}
定义视图:myApp\views.py
from .models import Students
def students(request):
studentsList = Students.objects.all()
return render(request, 'myApp/students.html', {"students": studentsList})
配置url:myApp\urls.py
urlpatterns = [
url(r'^$', views.index),
url(r'^(\d+)/(\d+)$', views.detail),
url(r'^grades/', views.grades),
url(r'^students/', views.students),
需求:点击班级,显示对应班级的学生名字
运行不正常https://www.bilibili.com/video/av/?p=12
Django流程梳理
创建工程:执行 django-admin startproject 工程名
创建项目:执行 python manage.py startapp 项目名称
激活项目:修改 settings.py中的INSTALLED_APPS
配置数据库:
修改__init__.py文件
修改settings.py文件中的DATABASES
创建模型类:在项目目录下的models.py文件中创建
生成迁移文件:执行python manage.py makemigrations
执行迁移:执行python manage.py migrate
配置站点:略
创建模板目录/项目模板目录
在settings.py中的TEMPLATES添加templates路径
在工程目录下(project)修改urls.py
在项目目录下创建urls.py
使用他人Django代码需要的简易修改:
1.在settings.py中修改数据库名
2.在settings.py中修改数据库密码
3.删除由内向外文件(在对应目录里鼠标右键删除)
4.在数据库中创建对应第一步的数据库(自己在SQL中创建)
5.执行生成迁移文件
6.执行迁移
7.启动服务
8.浏览器测试
Django模型
Django对各种数据库提供了很好的支持,Django为这些数据库提供了统一的调用API
我们可以根据不同的业务需求选择不同的数据库。
配置数据库
修改工程目录下的__init__.py文件
import pymysql
pymysql.install_ad_MySQLdb()
修改settings.py文件中的DATABASES
配置数据库
定义模型类:一个模型都在数据库中对应一张数据库表
生成迁移文件
执行迁移生成数据表
使用模型类进行增删改查
概述:对象-关系-映射
根据对象的类型生成表结构
将对象,列表的操作转换成SQL语句
将SQL语句查询到的结果转换为对象,列表
极大的减轻了开发人员的工作量,不需要面对因数据库的变更而修改代码的问题
模型,属性,表,字段之间的关系
一个模型类在数据库中对应一张表,在模型类中定义的属性,对应该模型对照表中的一个字段
定义属性:见下文
创建模型类
在模型类中定义Meta类,用于设置元信息
class Meta:
db_table = "students"
ordering = ['id']
定义数据表名,推荐用小写字母,数据表名默认为项目名小写_类名小写
对象的默认排序字段,获取对象的列表时使用
ordering['id'] id按升序排列
ordering['-id'] id按降序排列
注意:排序会增加数据库开销
隐藏类属性objects:
是Manager类型的一个对象,作用是与数据库进行交互
当定义模型类时没有指定管理器,则Django为模型创建一个名为objects的管理器
自定义管理器示例:
定义stuObj管理器:
stuObj = models.Manager()
当为模型指定模型管理器,Django就不再为模型类生成objects模型管理器了。
自定义管理器Manager类
模型管理器是Django的模型进行与数据库交互的窗口,一个模型可以有多个模型管理器
向管理器类中添加额外的方法
修改管理器返回的原始查询集
通常会重写get_queryset()方法
代码示例:
class StudentsManager(models.Manager):
def get_queryset(self):
return super(StudentsManger, self).get_queryset().filter(isDelete=False)
class Students(model.Moder):
# 自定义模型管理器
# 当自定义模型管理器,objects就不存在了
stuObj = models.Manger()
stuObj2 = StudentsManager()
目的:向数据库中添加数据
当创建对象时,django不会对数据库进行读写操作,当调用save()方法时才与数据库交互,将对象保存在数据库表中。
__init__方法已经在父类models.Model中使用,在自定义的模型中无法使用。
在模型类中增加一个类方法,示例如下:
class Students(model.Moder):
...snip...
@classmethod
def createStudent(cls, name, age, gender, contend,
grade,lastT, createT, isD=False):
stu = cls(sname=name, sage=age, sgender=gender,
scontend=contend, sgrade=grade, lastTime=lastT, createTime=createT,
isDelete=isD)
return stu
在自定义管理器中添加一个方法,示例如下:
class StudentsManager(models.Manager):
def get_queryset(self):
return super(StudentsManager, self).get_queryset().filter(isDelete=False)
def createStudent(self, name, age, gender, contend, grade, lastT, createT, isD=False):
stu = self.model()
# print(type(grade))
stu.sname = name
stu.sage = age
stu.sgender = gender
stu.scontend = contend
stu.sgrade = grade
stu.lastTime = lastT
stu.createTime = createT
return stu
查询集表示从数据库获取的对象的集合
查询集可以有多个过滤器
过滤器就是一个函数,基于所给的参数限制查询集结果
从SQL角度来说,查询集和select语句等价,过滤器就像where条件
在管理器上调用过滤器方法返回查询集
查询集经过过滤器筛选后返回新的查询集,所以可以写成链式调用
创建查询集不会带来任何数据库的访问,直到调用数据库时,才会访问数据
直接访问数据的情况:
返回查询集的方法称为过滤器
all():返回查询集中的所有数据
filter():保留符合条件的数据
filter(键=值)
filter(键=值,键=值)
filter(键=值).filter(键=值)
exclude():过滤掉符合条件的
order_by():排序
values():一条数据就是一个字典,返回一个列表
返回一个满足条件的对象
如果没有找到符合条件的对象,会引发模型类.DoesNotExist异常
如果找到多个对象,会引发模型类MultipleObjectsReturned异常
count():返回查询集中对象的个数
first():返回查询集中第一个对象
last():返回查询集中最后一个对象
exits():判断查询集中是否有数据,如果有数据返回 True,否则返回 False.
限制查询集
查询集返回列表,可以使用下标的方法进行限制,等同于sql中的limit语句
注意:下标不能是负数
示例:studentsList = Students.stuObj2.all()[0:5]
查询集的缓存
每个查询集都包含一个缓存,来最小化对数据库的访问
在新建的查询集中,缓存首次为空,第一次对查询集求值,会发生数据缓存,Django会将查询出来的数据做一个缓存,并返回查询结果。
以后的查询直接使用查询集的缓存
实现了sql中的where语句,作为方法filter(),exclude(),get()的参数
语法:属性名称__比较运算符=值
外键:属性名称_id
转义:类似sql中的like语句
like有关情况看我哥他%是为了匹配点位,匹配数据中的%使用(where like "\%")
filter(sname__contains="%")
比较运算符
exact:判断,大小写敏感
filter(isDelete=False)
contains:是否包含,大小写敏感
studentsList = Students.stuObj2.filter(sname__contains="孙")
startswith,endswith:以value开头或结尾,大小写敏感
以上四个在前面加上i,就表示不区分大小写iexact,icontains,istartswith,iendswith
isnull,isnotnull
filter(sname__isnull=False)
in:是否包含在范围内
gt大于,gte大于等于,lt小于,lte小于等于
year,month,day,week_day,hour,minute,second
studentsList = Students.stuObj2.filter(lastTime__year=2017)
跨关联查询
处理join查询
模型类名__属性名__比较运算符
# 描述中带有‘薛延美’这三个字的数据是属于哪个班级的
grade = Grades.objects.filter(students__scontend__contains='薛延美')
print(grade)
查询快捷pk代表的主键
使用aggregate函数返回聚合函数的值
maxAge = Student.stuObj2.aggregate(Max('sage'))
maxAge为最大的sage。
可以使用模型的A属性与B属性进行比较
from django.db.models import F,Q
def grades1(request):
g = Grades.objects.filter(ggirlnum__gt=F('gboynum'))
# [&Grades: python02&,&Grades: python03&]
return HttpResponse("OOOOOOOo")
支持F对象的算术运算
g = Grades.objects.filter(ggirlnum__gt=F('gboynum')+20)
概述:过滤器的方法的关键字参数,条件为And模式
需求:进行or查询
解决:使用Q对象
def students4(request):
studentsList = Students.stuObj2.filter(Q(pk__lte=3) | Q(sage__gt=50))
return render(request, 'myApp/students.html', {"students": studentsList})
只有一个Q对象的时候,就是用于正常匹配条件
studentsList = Students.stuObj2.filter(~Q(pk__lte=3))
django根据属性的类型确定以下信息
当前选择的数据库支持字段的类型
渲染管理表单时使用的默认html控件
在管理站点最低限度的验证
django会为表增加自动增长的主键列,每个模型只能有一个主键列,如
果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
属性命名限制
遵循标识符规则,且变量不能与Python保留字相同
由于django的查询方式,不允许使用连续的下划线
定义属性时,需要字段类型,字段类型被定义在django.db.models.fields目录下,
为了方便使用,被导入到django.db.models中
导入: from django.db import models
通过 models.Field创建字段类型的对象,赋值给属性
对于重要类型都做逻辑删除,不做物理删除,实现方法是定义idDelete属性,
类型为BooleanField,默认值为False
一个根据实际ID自动增长的IntegerField,通常不指定,
如果不指定,一个主键字段将自动添加到模型中
CharField(max_length=字符长度)
字符串,默认的表彰样式是TextInput
大文本字段,一般超过4000时使用,默认的表单控件是Textarea
IntegerField
DecimalField(max_digits=None, decimal_places=None)
使用Python的Decimal实例表示的十进制浮点数
DecimalField.max_digits
DecimalField.decimal_places
小数点后的数字位置
FloatField
使用Python的float实例来表示的浮点数
BooleanField
True/False 字段,此字段的默认表彰控制是CheckboxInput
NullBooleanField
支持 Null, True, False 三种值
DateField([auto_now=False, auto_now_add=False])
使用Python的datetime.date实例表示的日期
参数说明:
DateField.auto_now
每次保存对象时,自动设置该字段为当前时间,用于“最后一次修改”
的时间戳,它总是使用当前日期,默认为 False
DateField.auto_now_add
当前对象第一次被创建时自动设置当前时间,用于创建的时间戳,
它总是使用当前日期,默认为 False
该字段默认对应的表单控件是一个TextInput.在管理员站点添加了一个
JavaScript写的日历控件,和一个“Today”的快捷按钮,包含了一个额外
的invalid_date错误消息键
auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间
的任何组合将会发生错误的结果
使用Python的datetime.time实例表示的时间,参数同DateField
DateTimeField
使用Python的datetime
datetime实例表示的日期和时间,参数同DateField
一个上传文件的字段
ImageField
继承了FileField的所有属性和方法,但对上传的对象进行校验,
确保它是一个有效的image
通过字段选项,可以实现对字段的约束
在字段对象中通过关键字参数指定
如果为True,Django将空值以NULL存储在数据库中,默认值为 False
如果为True,则该字段允许为空白,默认值为 False
null是数据库范畴的概念,blank是表彰验证范畴的概念
字段的名称,如果未指定,则使用属性的名称
若值为 True,则在表中会为此字段创建索引
primary_key
若为 True,则该字段会成为模型的主键字段
如果为 True,这个字段在表中必须有唯一值
ForeignKey:一对多,将字段定义在多的端中
ManyToManyField:多对多,将字段定义在两端中
OneToOneField:一对一,将字段定义在任意一端中
用一访问多
对象.模型类小写_set
grade.students_set
用一访问一
对象.模型类小写
grade.studnets
对象.属性_id
student.sgrade_id
作用:视图接收web请求,并响应web请求
本质:视图就是python中的一个函数
响应过程:
用户在浏览器中输入网址www.sunck.wang/sunck/index.html
---网址---&
django获取网址信息,去掉IP与端口号,网址变成:sunck/index.html
---虚拟路径与文件名---&
url管理器逐个匹配urlconf,记录视图函数
---视图函数名---&
视图管理,找到对应的视图去执行,返回结果给浏览器
---响应的数据---&
返回第一步:用户在浏览器中输入网址
404视图:找不到网页(url匹配不成功时返回)时返回
在templates目录下定义404.html
&!doctype html&
&html lang="en"&
&meta charset="UTF-8"&
&meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"&
&meta http-equiv="X-UA-Compatible" content="ie=edge"&
&title&Document&/title&
&h1&页面丢失&/h1&
&h2&{{request_path}}&/h2&
request_path:导致错误的网址
配置settings.py
如果为 True,永远不会调用404页面,需要调整为 False 才会显示
ALLOWED_HOSTS = ['*']
500视图:在视图代码中出现错误(服务器代码错误)
400视图:错误出现在客户的操作
配置流程:
制定根级url配置文件
settings.py文件中的ROOT_URLCONF
ROOT_URLCONF = 'project.urls'
默认实现了
urlpatterns
一个url实例的列表
正则表达式
url匹配正则的注意事项
如果想要从url中获取一个值,需要对正则加小括号
匹配正则前方不需要加'/'
正则前需要加'r'表示字符串不转义
引入其他url配置
在应用中创建urls.py文件,定义本应用的url配置,在工程urls.py中使用include方法
project\urls.py
from django.contrib import admin
from django.conf.urls import url,include
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include('myApp.urls', namespace="myAPP")),
myApp\urls.py
from django.urls import path, include
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name="index"),
url的反向解析
概述:如果在视图,模板中使用了硬编码链接,在url配置发生改变时,动态生成链接的地址
解决:在使用链接时,通过url配置的名称,动态生成url地址
作用:使用url模板
定义视图:
本质:一个函数
视图参数:
一个HttpRequest的实例
通过正则表达式获取的参数
位置:一般在views.py文件下定义
HttpRequest对象
服务器接收http请求后,会根据报文创建HttpRequest对象
视图的第一个参数就是HttpRequest对象
django创建的,之后调用视图时传递给视图
path:请求的完整路径(不包括域名和端口)
method:表示请求的方式,常用的有GET,POST
encoding:表示浏览器提交的数据的编码方式,一般为utf-8
GET:类似于字典的对象,包含了get请求的所有参数
POST:类似于字典的对象,包含了post请求的所有参数
FILES:类似字典的对象,包含了所有上传的文件
COOKIES:字典,包含所有的cookie
session:类似字典的对象,表示当前会话
is_ajax():如果是通过XMLHttpRequest发起的,返回 True
QueryDict对象
request对象中的GET,POST都属于QueryDict对象
根据键获取值,只能获取一个值
www.sunck.wang/abc?a=1&b=2&c=3
将键的值以列表的形式返回
可以获取多个值
www.sunck.wang/abc?a=1&b=2&c=3
获取浏览器传递过来数据
www.sunck.wang/abc?a=1&b=2&c=3
url(r'^get1', views.get1),
#结尾不能加$,否则无法匹配
def get1(request):
a = request.GET.get('a')
b = request.GET.get('b')
c = request.GET.get('c')
return HttpResponse(a + " " + b + " " + c)
www.sunck.wang/abc?a=1&a=2&c=3
url(r'^get2', views.get2),
def get2(request):
a = request.GET.getlist('a')
c = request.GET.get('c')
return HttpResponse(a1 + " " + a2 + " " + c)
使用表单模拟POST请求
关闭CSRF:project\project\settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
# 'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
def showregist(request):
return render(request, 'myApp/regist.html',)
def regist(request):
name = request.POST.get("name")
gender = request.POST.get("gender")
age = request.POST.get("age")
hobby = request.POST.getlist("hobby")
print(name)
print(gender)
print(age)
print(hobby)
return HttpResponse("regist")
url(r'^showregist/$', views.showregist),
url(r'^showregist/regist/$', views.regist),
&!doctype html&
&html lang="en"&
&meta charset="UTF-8"&
&meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"&
&meta http-equiv="X-UA-Compatible" content="ie=edge"&
&title&注册&/title&
&form action="regist/" method="post"&
姓名:&input type="text" name="name" value=""/&
性别:&input type="radio" name="gender" value="<span style="color: #"&男&input type="radio" name="gender" value="<span style="color: #"&女
爱好:&input type="checkbox" name="hobby" value="power"/&权利&input type="checkbox" name="hobby" value="money"&金钱&input type="checkbox" name="hobby" value="beauty"&美女&input type="checkbox" name="hobby" value="Tesla"&Tesla
&input type="submit" value="注册"&
HttpResponse对象
作用:给浏览器返回数据
HttpRequest对象是由Django创建的,HttpResponse对象是由程序员创建
不用模板,直接返回数据
语句示例:return HttpResponse("Sunck is a good man")
使用render方法
原型:render(request, templateName[, context])
作用:结合数据和模板,返回一个完整的HTML页面
request:请求体对象
templateName:模板路径
context:传递给需要渲染在模板上的数据
content:表示返回内容
charset:编码格式
status_code:响应状态码
content-type:指定输出的MIME类型
init:使用页面内容实例化HttpResponse对象
write(content):以文件的形式写入
flush():以文件的形式输出缓冲区
set_cookie(key, value, maxAge=None, exprise=None)
delete_cookie(key):
删除cookie
如果删除一个不存在的cookie,就当什么都没发生
子类HttpResponseRedirect
功能:重定向,服务器端的跳转
redirect(to)
to推荐使用反向解析
from django.http import HttpResponseRedirect
from django.shortcuts import redirect
def redirect1(request):
# return HttpResponseRedirect('/redirect2')
return redirect('/redirect2')
def redirect2(request):
return HttpResponse("我是重定向后的视图")
子类JsonResponse
返回Json数据,一般用于异步请求
__init__(self.data)
注意:Content-type类型为application/json
http协议是无状态的,每次请求都是一次新的请求,它不记得之前的请求。
客户端与服务器的一次通信就是一次会话
实现状态的保持,在客户端或服务端存储有关会话的数据
存储的方式
cookie:所有数据存储在客户端,不要存储敏感的数据
session:所有的数据存储在服务端,在客户端用cookie存储session_id
状态保持的目的:
在一段时间内跟踪请求者的状态,可以实现跨页面访问当前的请求者的数据
注意:不同的请求者之间不会共享这个数据,与请求者一一对应
启用session:project\project\settings.py
INSTALLED_APPS
'django.contrib.sessions',
MIDDLEWARE
'django.contrib.sessions.middleware.SessionMiddleware',
使用session
启用session后,每个httpRequest对象都有一个session属性
get[key, default=None]
根据键获取session值
清空所有会话
删除当前会话并删除会话的cookie
def main(request):
# 取session
username = request.session.get('name', '游客')
print(username)
return render(request, 'myApp/main.html', {'username': username})
def login(request):
return render(request, 'myApp/login.html')
def showmain(request):
print("*****************")
username = request.POST.get('username')
# 存储session
request.session['name'] = username
return redirect('/main/')
from django.contrib.auth import logout
def quit(request):
# 清除session
logout(request) # 方法1,推荐
# request.session.clear() # 方法2
request.session.flush() # 方法3
return redirect('/main/')
设置session过期时间
set_expiry(value)
request.session.set_expiry(10)
设置为10秒后过期
如果不设置,2个星期后过期
value设置为0代表关闭浏览器时过期
value设置为None代表设置永不过期,不推荐
Redis使用:略

我要回帖

更多关于 django项目实例 的文章

 

随机推荐