Django的MTV框架基础

————Model:数据————
1.连接MySQL数据库(settings.py设置范例):
# 配置数据库
DATABASES = {
    'default': {
        # 数据库引擎
        'ENGINE': 'django.db.backends.mysql',
        # 数据库名称
        'NAME': 'axf',
        # 账号和密码
        'USER': 'root',
        'PASSWORD': '123456',
        # IP和端口
        'HOST': 'localhost',
        'PORT': '3306'
    }
}
2.ORM(ObjectRelationalMapping=对象关系映射):
  • 将具体语言下的【数据及其结构(通常以表示)】映射为数据库的【表结构和数据
  • 在Django中,一旦数据结构发生变化,就需要重新进行数据迁移
3.数据迁移的操作
  • python manage.py makemigrations 生成数据迁移py文件
  • python manage.py migrate 执行数据迁移
4.数据定义
①数据类型
基本字段类型:
models.IntegerField(default=1)
models.FloatField(default=0)
models.BooleanField(default=False)
models.NullBooleanField()   #支持null、true、false三种值#
models.TextField(db_column='ps')   #大文本字段,一般超过4000使用#
models.DateTimeField(auto_now=True)
#使用Python的datetime.datetime实例表示的日期和时间
#若auto_now=True,每次保存对象时,自动设置该字段为当前时间
#若auto_now_add=True,当对象第一次被创建时自动设置当前时间(一次性的时间戳)
#注意:auto_now_add, auto_now,default三者是互斥的
其它字段类型:
model.DecimalField(max_digits=None, decimal_places=None)
#使用python的Decimal实例表示的十进制浮点数
#max_digits=总位数
#decimal_places=小数位数
model.DateField([auto_now=False, auto_now_add=False])  #使用Python的datetime.date实例表示的日期#
model.TimeField  #使用Python的datetime.time实例表示的时间#
models.AutoField(primary_key=True)
#一个根据实际ID自动增长的IntegerField,通常不指定,如果不指定,一个主键字段将自动添加到模型中
model.FileField  #上传文件字段
icon = models.ImageField(upload_to='icons')
#继承于FileField,框架对上传的对象进行校验,确保它是个有效的image
表关系字段:
暂无(查看后文)
定义字符串范例:
username = models.CharField(max_length=32, unique=True)
定义布尔值范例:
sex = models.BooleanField(default=False)
②字段约束
primary_key=False
#django会为表增加自动增长的主键列
#如果使用选项设置某属性为主键列后,则django不会再生成默认的主键列
max_length=None
unique=False
null=False #如果为True,则默认以空值NULL填充
blank=False #如果为True,则该字段允许为空白(即空字符串),这个约束常常用于表单验证
default=NOT_PROVIDED
db_index=False #若值为 True, 则在表中会为此字段创建索引
db_column=None #字段的名称,如果未指定,则使用属性的名称
【完整的约束源码】:
class Field(RegisterLookupMixin):
    ...
    def __init__(self, verbose_name=None, name=None, primary_key=False,
                 max_length=None, unique=False, blank=False, null=False,
                 db_index=False, rel=None, default=NOT_PROVIDED, editable=True,
                 serialize=True, unique_for_date=None, unique_for_month=None,
                 unique_for_year=None, choices=None, help_text='', db_column=None,
                 db_tablespace=None, auto_created=False, validators=(),
                 error_messages=None):
    ...
③元信息
class Meta:
    db_table = 'Flower'
    ordering = ["-f_color"]
④范例:用户定义
# 用户数据模型
class UserModel(models.Model):
    # 用户名密码邮箱
    username = models.CharField(max_length=32, unique=True)
    password = models.CharField(max_length=256)
    email = models.CharField(max_length=64, unique=True)
    # False 代表女
    sex = models.BooleanField(default=False)
    # 头像,图片字段,上传到静态资源文件夹下的icons/
    icon = models.ImageField(upload_to='icons')
    # 是否被逻辑删除
    is_delete = models.BooleanField(default=False)     

    class Meta:
 	db_table = "t_user"

5.数据查询
①查询语法:
XXX.objects.all()
XXX.objects.get(k1=v1,k2=v2)
过滤器:
XXX.objects.filter(条件语句)
XXX.objects.exclude(条件语句)
②过滤器
filter(条件语句):获取符合条件的
exclude(条件语句):去除不符合条件的
③条件语句
格式:
格式1—>属性名=值(忽略大小写)
格式2—>属性名__运算符=临界值
运算符:
gt 、lt、gte、lte
startswith(大小写敏感)、endswith、contains、exact
istartswith(忽略大小写)、iendswith、icontains、iexact
④缓存的二次筛选
查询时允许多个过滤器串联使用(链式调用)
只有第一次会执行数据库查询,后续操作是对已有结果集的筛选
⑤Q对象:实现复杂条件
条件与—>Q(条件语句) & Q(条件语句)
条件或—>Q(条件语句) | Q(条件语句)
条件非—>~ Q(条件语句)
表关系
一对一(OneToOneField)
#将关系字段定义在任意一方
#举栗子:Person-IDCard,从表IDCard持有外键
class IDCard(models.Model):
    	i_num = models.CharField(max_length= 18)
   	# False 代表女
   	i_sex = models.BooleanField(default=False)
    	# 一张身份证对应着一个人
    	i_person = models.OneToOneField(Person, on_delete=models.SET_NULL, null=True)
#一访问一
格式:对象.模型 类小写
举栗子:idcard = person.idcard
一对多(ForeignKey)
#将关系字段定义在多方
#举栗子:Person-Hobby,多方Hobby持有外键
class Hobby(models.Model):
    	h_name = models.CharField(max_length=16)
    	h_cost = models.FloatField(default=1000)
    	h_person = models.ForeignKey(Person, on_delete=models.PROTECT)
#一访问多
格式:对象.模型 类小写 _set
举栗子:hobbies = person.hobby_set
多对多(ManyToManyField)
#将关系字段定义在任意一方
#举栗子:Buyer-Goods,从表Goods声明关联关系
class Goods(models.Model):
    	g_name = models.CharField(max_length=128)
    	g_price = models.FloatField(default=1)
    	# 声明商品和买家有多对多关系
    	g_buyers = models.ManyToManyField(Buyer)
#多a访问多b
goods.g_buyers.add(buyer)
buyers = goods.g_buyers.all()
goods_list = buyer.goods_set.all()
on_delete
#定义删除对象时如何处理其级联数据(其外键/关系字段指向的数据)
#可选值:
models.CASCADE  —>默认值,默认删除级联数据
models.PROTECT  —> 不存在级联数据的时候允许删除&当存在级联数据的时候删除会抛出保护异常
models.SET_NULL  —> 级联数据赋值为空
models.SET_DEFAULT  —>前提是字段本身有默认值
models.SET()  —>删除的时候重新动态指向一个实体
维护表关系思路
1.在从表中添加关系字段,其类型即为【对方对象(或对象容器)】
2.框架自动为主表添加对应的关系字段,其类型即为【对方对象(或对象容器)】:.对方类名,IDE会自动提示可用的属性

6.Manager
显式属性 —> 开发者手动定义的,直接看的到的
隐式属性 —> 系统/框架根据需求,自动创建的对象
—>objects是model.Manager对象
—>当我们手动创建了Manager对象的时候,它就不会自动生成了

好处 —>配置默认的数据创建方式和查询方式
创建类并指定管理器 —>举栗子
class Dog(models.Model):
    	d_name = models.CharField(max_length=16)
    	d_legs = models.IntegerField(default=4)
    	is_delete = models.BooleanField(default=False)
    	# 交由管理器进行管理
    	d_manager = MyManager()


定义管理器类 —>
class MyManager(models.Manager):
定义创建实例方法:
# 创建狗的实例,默认两条腿
def create_model(self,d_name, d_legs = 2):
        dog = self.model()
        dog.d_name = d_name
        dog.d_legs = d_legs
        return dog
定义查询方法:
# 默认不包含被逻辑删除的狗狗
# 先调用model.Manager get_queryset
def get_queryset(self):
        return super(MyManager,self).get_queryset().exclude(is_delete=True)
使用 管理器类 —>
创建实例:
dog = Dog.d_manager.create_model("中国田园犬")
查询实例:
dogs = Dog.d_manager.all()
dogs = Dog.d_manager.all().filter(is_delete=False)
dogs = Dog.d_manager.filter(d_legs__lt=100)
dogs = Dog.d_manager.filter(Q(d_legs__lt=20)|Q(d_legs__gt=150))
7.继承
定义父类 —>
# 动物父类
class Animal(models.Model):
    	#名字和腿数
    	a_name = models.CharField(max_length=16, default='Animal')
    	a_legs = models.IntegerField(default=4)
    	class Meta:
        	#表名是抽象的,框架不会为当前类创建表
        	abstract = True
定义子类 —>
# 动物子类狗狗
class Dog(Animal):
    	#已经有了a_name和a_legs
    	#定义自己独有的字段
    	d_fun = models.TextField()
8.常用API
查询  —>
flowers = Flower.objects.all()
flowers = Flower.objects.all().order_by("-id")[0:2]
flowers = Flower.objects.filter(f_color__gt=100).filter(f_color__lt=150)
flowers = Flower.objects.filter(f_color__gt=100).exclude(f_color__gt=150).filter(f_name__contains="水")
flowers = Flower.objects.filter(f_name__endswith="1")
flowers = Flower.objects.filter(f_name="rose")
flowers = Flower.objects.filter(pk__in=[1,2,3,4])
flowers = Flower.objects.filter(f_time__year="2019")
students = Student.objects.filter(s_grade_id__gt=F('id')-5)
----------------------------------------------------------------------------
flower = Flower.objects.get(pk=10)
flower = Flower.objects.get(f_color=255)
----------------------------------------------------------------------------
flower = flowers.last()
flower = flowers.first()
if flowers.count() == 0:
if flowers.exists():
----------------------------------------------------------------------------
dogs = Dog.objects.filter(~Q(d_legs__lt=100))
插入  —>
grade = Grade()
grade.g_name =  'fuck'
grade.save()
----------------------------------------------------------------------------
person = Person.objects.create(p_name="小黄%d"%random.randrange(110))
p = Buyer.objects.create(b_name="清醒%d下" % flag)
goods = Goods.objects.create(g_name="娃娃%d" % flag, g_price=flag)
删除 —>
通过查询得到一个特定的grade对象
grade.delete()
修改  —>
通过查询得到一个特定的grade对象
grade.gname='shit'
grade.save()
————Template:模板(界面)————
1.模板目录位置
应用下 —> 不需要注册
—> 无法跨应用地进行复用
工程下 —> 需要注册(settings.py范例)
# django默认的模板配置
TEMPLATES = [ { ...,
        # 模板路径
        'DIRS': [os.path.join(BASE_DIR, 'templates'),],
   ...},]
—> 可以在不同应用中复用
2. 模板语法
读取数据 —>
{{ xxx }}
{{ xxx.attr }}
{{ xxx.method }}
{{ xxx.i }}
{{ xxx.key }}
注释 —>
<!--普通HTML注释是可见的-->
{#  模板注释是不可见的  #}
{% comment %}...{% endcomment %}  #注释掉一吨内容
模板内计算 —>
加减  —>  {{ value|add:10 }}  
     —>  {{ value|add:-10 }}
乘除  —>  {% widthratio a b c %}   # a/b*c
大小写转换  —>  {{ animal.a_name|lower }}
           —>  {{ animal.a_name|upper }}
判断是否整除  —>  {% if forloop.counter|divisibleby:2 %}
连接容器内元素  —>  {{ animals|join:'=' }}
加载静态文件
—>  {% load static %}
—>  {% load staticfiles %}
—>  <img src="{% static 'img/dragon.gif' %}">  #访问静态资源
—>  settings.py配置:
·静态文件夹位置
·访问路由
·静态文件访问路由
STATIC_URL = '/static/'
# 静态文件存储目录:根目录/static/
STATICFILES_DIRS = [
    	os.path.join(BASE_DIR, 'static'),
]
流程控制 ——> 遍历
 
{% if forloop.first %}
    {% if forloop.last %}
    {{ forloop.counter0 }} #正序下标,索引从0开始
    {{ forloop.counter }}  #正序下标,索引从1开始算
    {{ forloop.revcounter }}  #逆序,索引从最大长度到1
—>  forloop.revcounter0  #逆序,索引从最大长度到0
—>  forloop.parentloop  #获取上一层 for 循环的 forloop
—>  {% empty %}  #当列表为空时用 for empty:
举栗子:
{% for animal in animals %}
    	<li>{{ animal.a_name }}</li>
{% empty %}
<h3>动物都跑啦</h3>
{% endfor %}
流程控制 ——> if条件
—>  {% if forloop.first %}...{% elif forloop.last %}...{% else %}...{% endif %}
—>  {% ifequal value1 value2 %}...{% else %}...{% endifequal %}
—>  {% ifnotequal value1 value2 %}...{% else %}...{% endifnotequal %}
转义开关 ——> 转义
—> {% autoescape off %}  {{ content }}  {% endautoescape %}
—> {{ content|safe }}
转义开关 ——> 抑制
—>  {% autoescape on %}  {{ content }}  {% endautoescape %}
—>  {{ content }}
父辈挖坑子孙填 ——>
—>  {% block extCSS %}...{% endblock %}
—>  {{ block.super }}  #引用父模板对当前块的实现
继承与兼并 ——>
—>  {% extends 'base_main.html' %} #继承父模板
—>  {% include xxx.html %}   #兼并另一个模板使之成为页面的一部分
3. 翻页框架
引入 ——>
样式 —>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.css">
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/css/swiper.min.css">
脚本 —>
<script src="https://cdn.bootcss.com/jquery/1.11.1/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Swiper/3.4.2/js/swiper.jquery.min.js"></script>
<--------------------------------------------------------------------->
样式 ——>
<div class="swiper-container" id="topSwiper">   # 外层包裹,需要配合脚本使用 ^.^对应脚本
<div class="swiper-wrapper">  # 翻页包装器
<div class="swiper-slide">...</div>   #  分页内容1
<div class="swiper-slide">...</div>     #  分页内容2
—>  如果需要分页器 : <div class="swiper-pagination"></div>
—>  如果需要导航按钮 :<div class="swiper-button-prev"></div>
—>  如果需要滚动条 :<div class="swiper-scrollbar"></div>
<---------------------------------------------------------------------->
脚本 ——> 查看 ^.^ 内容
$(function () {
       var swiper = Swiper(".swiper-container",{});
})
4.模板渲染过程
加载模板
template = loader.get_template('Hello.html')   # <class 'django.template.backends.django.Template'>
渲染模板
result = template.render())  # <class 'django.utils.safestring.SafeText'> 
result = template.render(context={"haha":"你哈什么哈"})   #  渲染时给模板传递数据

5.访问静态资源
settings.py的配置:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]
页面的配置:
{% load static %}
<img src="{% static 'img/dragon.gif' %}">

————View:业务(控制器)————
1.什么是视图
视图层=路由表(urls.py)+ 视图函数(views.py)
其角色相当于MVC中的Controller
其职能是协调models和Template的关系,并解除其耦合
过程:
路由表接收用户请求,并分配给相应的视图函数进行处理
视图函数调用模型获取数据
视图函数将数据交给模板渲染
视图函数将渲染结果返回给客户端

2.路由的定义
定义路由响应函数:
url(r'^hehe/(\d+)/', views.hehe_user, name='hehe')
# 将指定路由交由指定函数进行处理&当前函数被命名为'hehe'
将特定路由派发给子路由表:
url(r'^app/', include('App.urls', namespace='app'))
#将所有/app/xxx派发给App下的urls.py处理&namespace='app'上述子路由表被命名为'app'
【反向解析】=得到【指定路由表中的指定函数】对应的路由
3.路由参数
普通参数规则:
在url匹配规则中使用括号,
url规则中有多少括号,request参数后就要有多少参数,
一一对应,按位置对应(位置参数),
写法(\正则).
<---------------------------------------------------------------------->
普通参数示例:
url(r'^hehe/(\d+)/', views.hehe_user, name='hehe')
def hehe_user(request, user_id):
<---------------------------------------------------------------------->
关键字参数规则:
关键字参数 (?P<year>\正则 ) ,P代表params
需要和视图函数的参数 (year),按照名称匹配
<---------------------------------------------------------------------->
关键字参数示例:
url(r'^getdate/(?P<month>\d+)/(?P<day>\d+)/(?P<year>\d+)', views.get_date, name='getdate')
def get_date(request, year, month, day)
<---------------------------------------------------------------------->
反向解析路径:
模板中:
{% url 'namespace:name'  value1 value2 ...%}
{% url 'namespace:name' key=value key=value ...%}
视图中:
reverse('namespace:name', args=(value1,value2...))
reverse('namespace:name', kwargs={key:value, key: value})
4.发起请求
直接声明url:
<a href="/three/wahaha/">你们店里有哇哈哈哈哈嘛</a>
<a href="/four/hehe/9527/">去查找秋香</a>
<a href="/four/getdate/3/30/2018/">美国老的时间</a>
反向解析获得url:
<a href="{% url 'two:haha' %}">哇哈哈</a>
#namespace='two'的那个urls.py #上述urls.py中定义的name='haha'的那个响应函数
<---------------------------------------------------------------------->
<a href="{% url 'two:hehe' 17951 %}">已失效,年底移动资费至少百分之三十</a>
#namespace='two'的那个urls.py
#上述urls.py中定义的name='hehe'的那个响应函数
#路径参数为17951
#最终url形如:/two/hehe/17951/
<---------------------------------------------------------------------->
<a href="{% url 'two:getdate' year=2018 month=3 day=31 %}">一觉恍如隔世</a>
#namespace='two'的那个urls.py
#上述urls.py中定义的name='getdate'的那个响应函数
#getdate这个响应函数中定义了三个参数:year,month,date
#三个路径参数分别为: year=2018 month=3 day=31
#最终url形如:/two/getdate/2018/3/31/

5.返回响应
渲染页面并返回:
return HttpResponse(result) # 以HttpResponse形式返回渲染结果
return HttpResponse("<h1>HelloWorld</h1>") # 直接在响应中给页面内容
return render(request, 'Hello.html') # 直接返回渲染结果
return render(request, 'AnimalList.html', context={"animals": animals, "data": data_dict})
#渲染模板时传递数据
请求重定向:
return HttpResponseRedirect("/four/wahaha")
return HttpResponseRedirect("/four/getdate/4/1/2018/")
return HttpResponseRedirect(reverse("two:haha"))
return HttpResponseRedirect(reverse("two:getdate", kwargs={"year":"2019","month":"11", "day":"11"}))
return redirect(reverse("axf:user_login"))
返回JSON数据:
return JsonResponse({"msg": "ok", "status": "200", "data": "精神一下"})
用途:1.响应前端AJAX请求 2.为移动端APP返回数据 ……
JSON VS XML:(太厚重,已过时)

6.Request对象
1.请求对象
2.视图函数中的第一个参数
3.是由Django框架根据用户的请求信息,为开发者自动创建的一个对象
4.包含了请求的所有信息:
path、method、encoding、GET、POST、FILES、COOKIES、session
is_ajax、META
5.用法举栗:
user_id = request.session.get("user_id")
request.session["user_id"] = user.id
if request.method == "GET":
goodsid = request.GET.get("goodsid",None) # 获得请求数据
username = request.POST.get("username",None) # 获取表单数据
icon = request.FILES.get("icon") # 获取上传的文件位置,类型是字符串
request.session.flush() # 清空session

7.Response对象
1.响应对象
2.由开发者自己创建
3.服务器和客户端交流的方式
4.分类:
HttpResponse -》 render
HttpResponseRedirect -》redirect
JsonResponse
5.属性和方法
content
status_code
content-type (text/html)or (image/jpeg)
write()
flush() -->将缓冲区的内容推到response.content中

8.错误页面定制
1.关闭DEBUG模式
2.settings.py中设置:ALLOWED_HOSTS=['*']
想要覆盖哪个错误,就书写相应的HTML:404.html、502.html








猜你喜欢

转载自blog.csdn.net/dorisi_h_n_q/article/details/80548376
今日推荐