django+xadmin在线教育平台(五)
3-3 django orm介绍与model设计
上节教程完成后代码(来学习本节前置条件):
对应commit: 留言板前端页面展示。本次内容截止教程3-2结束。
可能现在你还在通过手写sql语句来操作数据库,当我们有了orm,数据库操作变得很简单。这一小节我们来学习Django中的orm。
原生sql 与 orm
没有orm 的情况下message/views.py代码:
import MySQLdb
# 使用原生sql获取书的列表
def book_list(request):
# 创建到数据库的连接: 指明用户名,数据库,密码
db = MySQLdb.connect(user = 'me', db='mydb', passwd='secret', host='localhost')
# 创建一个游标对象执行器
cursor = db.cursor()
# 书写我们需要的sql语句
cursor.execute('SELECT name FROM books ORDER BY name')
# 对于fetchall()的结果做遍历,将遍历回来的结果当做数组,取第0个值name。
names = [row[0] for row in cursor.fetchall()]
db.close()
可不可以让数据库字段的查询和使用类的一个属性一样简单?没错登登登:orm上场了
book:name
book.name
book.save()
Django的orm就是为了让我们不再写上面那样的语句,而是像使操作数据库像使用类和类属性一样。
创建我们的models
verbose_name:对象的人类可读的名称,单数:
verbose_name = "pizza"
class Meta,内嵌于 UserMessage 这个类的定义中
如果 class Publisher 是顶格的,那么 class Meta 在它之下要缩进4个空格--按 Python 的传统
你可以在任意一个 模型 类中使用 Meta 类,来设置一些与特定模型相关的选项。
如:设置ordering = ['name'],默认地都会按 name 字段排序
message/models.py:
# 继承于django.db.models.Model
class UserMessage(models.Model):
# 设置最大长度,verbose_name在后台显示字段会用到
name = models.CharField(max_length=20, verbose_name=u"用户名")
# Django提供内置的邮箱字段会帮忙验证` default_validators = [validators.validate_email]`
email = models.EmailField(verbose_name=u"邮箱")
address = models.CharField(max_length=100, verbose_name=u"联系地址")
message = models.CharField(max_length=500, verbose_name=u"留言信息")
class Meta:
verbose_name = u"用户留言信息"
# db_table ,这里我们让它自动生成所以不用指定
这时我们执行makemigrations messages
会发现并没有改动。
因为setting中我们没有注册我们的app: message
注意:新建的app都要在setting中注册
在setting中注册我们的app
DjangoGetStarted/settings.py 大概36行INSTALLED_APPS
:
`INSTALLED_APPS`
[
前面的不用变,后面新增下一行
'message'
]
这时候我们重新运行Tools 菜单下 Run manage.py Task
会提示:
如果提示:
SyntaxError: Non-ASCII character '\xe7' in file D:\CodeSpace\PythonProject\DjangoGetStarted\apps\message\models.py on line
请注意可能你忘记在写过中文的地方加上:
#coding: utf-8
注意必须加在第一或二行。
然后执行下面命令:
makemigrations message
migrate message 生成数据表
前往Navicat验证:
可以看到我们的数据表已经创建成功。默认数据表名称为
app名称_类名转换为小写
自动生成的id作为主键。
Models讲解
除过普通的对应数据库的字段类型如CharField
,还有很多高级类型。如EmailField
提供email验证。
models.ForeignKey # 外键
models.DateTimeField # 时间字段
models.IntegerField # 整型
models.IPAddressField # IP地址
models.FileField # 上传文件
models.ImageField # 图片
ctrl按住+左键点击
models
进入之后点击fields
拖到文件开始可以看到所有字段:
__all__ = [str(x) for x in (
'AutoField', 'BLANK_CHOICE_DASH', 'BigIntegerField', 'BinaryField',
'BooleanField', 'CharField', 'CommaSeparatedIntegerField', 'DateField',
'DateTimeField', 'DecimalField', 'DurationField', 'EmailField', 'Empty',
'Field', 'FieldDoesNotExist', 'FilePathField', 'FloatField',
'GenericIPAddressField', 'IPAddressField', 'IntegerField', 'NOT_PROVIDED',
'NullBooleanField', 'PositiveIntegerField', 'PositiveSmallIntegerField',
'SlugField', 'SmallIntegerField', 'TextField', 'TimeField', 'URLField',
'UUIDField',
)]
介绍字段参数
CharField
必须指明默认最大长度。null=True,blank=True
指明字段可以为空
defalut = " "
指定默认值。
name = models.CharField(max_length=20,null=True,blank=True, verbose_name=u"用户名")
id是自动生成的,如果需要自定义主键,message/models.py中添加字段:
object_id = models.CharField(primary_key=True, verbose_name="主键")
此时点击Tools 菜单下 Run manage.py Task
输入makemigrations message
知识点:CharField必须指明最大长度
object_id改为:
object_id = models.CharField(primary_key=True, max_length=50 ,verbose_name="主键")
这时点击Tools 菜单下 Run manage.py Task
输入makemigrations message
You are trying to add a non-nullable field 'object_id' to usermessage without a default; we can't do that (the database needs something to populate existing rows).
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows)
2) Quit, and let me add a default in models.py
根据提示信息,我们需要给object_id
添加默认值:
object_id = models.CharField(primary_key=True, max_length=50,default="", verbose_name="主键")
get新知识点:object_id必须有默认值
输入2
退出:然后输入makemigrations message
再输入下面命令生成数据表
migrate message
可以看到上图过程中会告诉我们做了哪些变化,如删除了默认系统生成的主键
id
,变更了name
。新增了我们的object_id
前往Navicat验证右键设计表:
可以看到object_id
已经成为我们的新主键。
介绍Meta信息:
Meta信息中我们可以指定常见的类型:
db_table = "user_meassage"
自定义后生成表,表名会与我们的保持一致。而不会前缀appname
如:message_
这里因为我们已经生成过了,就不要做验证改变表名了。
ordering = '-object_id'
ordering指定默认排序字段,如:就会以object_id倒序
verbose_name_plural = u"用户留言信息"
verbose_name_plural:复数信息,便于人阅读。否则会在后台显示用户留言信息s
已经学习完毕了orm
将数据表映射表。
github地址:https://github.com/mtianyan/DjangoGetStarted
此节结束对应github commit:
留言板数据库orm映射成表完成。内容截止教程3-3结束。
3-4 django model的增删改
github仓库地址:https://github.com/mtianyan/DjangoGetStarted
- 上小节完成代码对应commit: 留言板数据库orm映射成表完成。内容截止教程3-3结束。
在message/views.py
中:
from .models import UserMessage
将我们刚才创建的model,import进来。.
代表是与当前同级的目录。
按照下图所示添加一条测试数据。
然后再我们的getform
方法内部添加下面代码:
def getform(request):
# UserMessage默认的数据管理器objects。
# 方法all()是将所有数据返回成一个queryset类型(django的内置类型)
all_message = UserMessage.objects.all()
#我们可以对于all_message进行遍历操作
for message in all_message:
# 每个message实际就是一个UserMessage对象(这时我们就可以使用对象的相关方法)。
print message.name
return render(request, 'message_form.html')
调试过程:
点击上图小红框位置,打上断点。
点击Run -> debug后:在浏览器里打开:
http://127.0.0.1:8000/form/
- 弹出上图代表已进入断点。
此时鼠标左键点击:all_message.可以看到这是一个
{QuerySet}类型的对象,里面存放着[<UserMessage: UserMessage object>]
按
f6
使运行到下一步。此时下方的值窗口内可以看到message的值。说明我们成功取到了数据库的值。
filter取出指定要求值
all_message = UserMessage.objects.filter(name=' mtianyan', address='西安')
按照上面调试过程重新调试可以看到我们同样取出了值。
小练习:将名字改为与自己数据库存放值不同的。查看结果。
变成了空列表,说明一切正确。
将数据存入数据库
了解:django/db/models/base.py 源码中提供save方法
def save(self, force_insert=False, force_update=False, using=None,
update_fields=None):
getform方法中添加代码:
# 存储部分
# 首先实例化一个对象
user_message = UserMessage()
# 为对象增加属性
user_message.name = "mtianyan2"
user_message.message = "blog.mtianyan.cn"
user_message.address = "西安"
user_message.email = "1147727180@qq.com"
user_message.object_id = "efgh"
# 调用save方法进行保存
user_message.save()
- 打上断点:如下图。
- 一直惦记f6单步调试,直到如下图:蓝色到
return
语句
可以在下方值窗口查看到值
Navicat进行验证
可以看到成功的添加了数据
mtianyan2
如何从html的提交中取到数据并保存进数据库
templates/message_form.html:
method是post。action就是指向我们在urls.py中配置的
/form/
前面必须加斜杠指根路径下form
里面的input会自动把值传递给后台:这时我们就可以在getform中取到刚才传递过来的值。
运行项目:然后输入需要填写的值。点击提交:出现403错误
Forbidden (403)
CSRF verification failed. Request aborted.
根据提示:我们的页面没有进行crsf的验证,这时django的安全机制,不允许任意form都往后台提交。
知识点:所以我们需要在html页面中加入csrf_token
{% csrf_token %}
原有那行删除掉。打上断点
刷新页面并提交。这时候在值窗口可以看到request对象下的POST中存放着我们提交的数据。内容如下
<QueryDict: {u'message': [u'\u54c8\u54c8'], u'address': [
u'\u897f\u5b89\u5e02'], u'csrfmiddlewaretoken': [
u'uIYSMOTWPJBPOPucRwd3uDaWtCzeEaem'], u'name': [
u'\u5929\u6daf\u660e\u6708\u7b19'], u'email': [u'1147727180@qq.com']}>
数据以dict:key-value 形式存储 key是由如下图html中的name所决定对应的。
数据库新增。
request.POST
中数据取出,存入user_message
对象
# html表单部分
# 此处对应html中的method="post",表示我们只处理post请求
if request.method == "POST":
# 就是取字典里key对应value值而已。取name,取不到默认空
name = request.POST.get('name', '')
message = request.POST.get('message', '')
address = request.POST.get('address', '')
email = request.POST.get('email', '')
# 实例化对象
user_message = UserMessage()
# 将html的值传入我们实例化的对象.
user_message.name = name
user_message.message = message
user_message.address = address
user_message.email = email
user_message.object_id = "ijkl"
# 调用save方法进行保存
user_message.save()
- 打断点在下图位置:
- 进入调试:点击点击method:是get请求。因为我们并没有按提交按钮,而是get这个网页
- 点击f8继续运行我们的项目 浏览器中填写表单内容点提交。
因为这次是表单提交,已经变成了post方式。按
f6
进行单步调试。
一直单步到如下图蓝色
这时候值浏览窗口可以看到
检查我们的user_message对象的属性是否已经全部添加进去,
使用f8 继续项目并前往Navicat验证
可以看到我们的数据库中已经新增,标志着我们已经成功存入数据。
删除数据。
对于查询到的数据做删除:
# 方法2 :filter取出指定条件值,逗号代表and 必须同时满足两个条件才返回。
all_message = UserMessage.objects.filter(name='mtianyan', address='西安')
# 我的数据库里保存着可以匹配到该条数据的一行。
# 删除操作:使用delete方法删除all_message
all_message.delete()
for message in all_message:
# 删除取到的message对象
message.detele()
# print message.name
点击run并访问:http://127.0.0.1:8000/form/
进入Navicat进行验证。
可以看到我们的那条mtianyan + 西安的数据已经被删除。
至此:我们已经学会了新增,删除,查询。
本节结束github对应commit:
django model的增删改数据库。本次内容截止教程3-4。
3-5 django url templates配置
项目Github地址:https://github.com/mtianyan/DjangoGetStarted
本节开始对应对应Github的commit:django model的增删改数据库。本次内容截止教程3-4。
本节将介绍url的配置,以及如何将数据库数据填充回前台html页面。
情景:只允许用户修改mtianyan
,如果没有就添加,如果有就回填使用户可以修改。
取出数据
message/views.py中的getform方法中
message = None
all_message = UserMessage.objects.filter(name='mtianyan', address='西安')
# if 判断是否存在数据
if all_message:
# all_message是一个list,可以使用切片。
message = all_message[0]
这里注意把前几节写的删除掉
将数据回填至html中
修改return render
return render(request, 'message_form.html',{
"my_message" : message
})
这里前面的"my_meassage"是我们可以自行命名的。会有一个
my_message
对象随着返回前端页面。
在前端页面中放入值。
为input系列标签添加value
: 使用my_message.name
取到我们传递过来的my_message
对象的属性值。
<input id="name" type="text" name="name"
value="{{ my_message.name }}" class="error" placeholder="请输入您的姓名"/>
请自行完成姓名,邮箱,联系地址三个
input
标签。
为textarea
标签添加值
<textarea id="message" name="message"
placeholder="请输入你的建议">{{ my_message.message }}</textarea>
运行项目,访问:http://127.0.0.1:8000/form/
成功!!我们已经将后台数据库数据成功展示到前台。
template模板渲染中的一些用法。
在我们的template模板中也就是form.html中,不允许我们写Python的语法,
它提供了一套自己的内建标签。
常用的几种模板标签介绍:
if - else
官方提供模板如下:
个人实践:
满足if运行结果:
不满足if:如改为my_message.name == "mtianyan1"
运行结果:
ifequal
& ifnotequal
官方文档解释:ifequal a b
相当于f a == b
.ifnotequal
则相当于if a != b
个人实践:
结果为:未找到中文昵称
slice
官方文档解释:其实就是切片操作。从头开始切到第n个。
个人实践:
本来
mtianyan
与mtianyan1
是不同的,但是切片后前八位相同。
运行结果显示 :对应中文昵称:天涯明月笙
URl的别名设置技巧
DjangoGetStarted/urls.py:
为r'^form/$'
添加别名:
url(r'^form/$', getform, name = "form_new")
前往html中修改action地址为下面所示:
<form action="{% url "form_new" %}" method="post" class="smart-green">
这时我们如果改动urls.py中的r'^form/$'
不需要再修改前端代码中值。
url先后顺序问题
注意url匹配规则中一定不要忘记/$
符号代表以form/
结束的才会有效。不会向后继续匹配。比如没有/$
url(r'^form', getform, name="form_new")
这时我们进入浏览器访问时输入http://127.0.0.1:8000/formemmm
都可以被响应。
特别是如果底下还配置有被这个规则包含的条目,会产生被写在更靠前的拦截住得不到正确处理的Bug。
上图我们是想要让formtest响应admin.site.urls。但是会被form提前拦截住。
所以我们一定要注意加上/$
符号。
至此我们完成了留言板项目:学习到了Django必备的基础知识。
下一章我们将开始我们的进阶学习:开发在线教育平台网站。
本章结束:
原文学习来自简书,作者:天涯明月笙
原文链接:https://www.jianshu.com/p/273134a8aea6
django+xadmin在线教育平台(五)的更多相关文章
- django+xadmin在线教育平台(一)
大家好,此教程为在慕学网的实战教程Python升级3.6 强力Django+杀手级Xadmin打造在线教育平台的学习笔记,不对望指正! 使用Django+Xadmin打造在线教育平台(Python2, ...
- django+xadmin在线教育平台(四)
3-2 配置表单页面 必要的该说的,该了解的 前置条件: 你已经学习了前面教程.将项目的文件夹目录结构,setting配置等修改完毕与我保持一致. 本节通过Django快速的配置一个留言板页面来学习 ...
- django+xadmin在线教育平台(十)
剩余app model注册 courses注册 新建courses/adminx.py: # encoding: utf-8 __author__ = 'mtianyan' __date__ = '2 ...
- django+xadmin在线教育平台(十五)
7-4 课程机构列表页数据展示2 前去html中进行数据填充 mark 可以看到所有城市是通过a标签,当前选中城市为active. mark 之后把下面的写死的城市删除掉. mark 这时 ...
- django+xadmin在线教育平台(十七)
8-1 课程列表 拷贝课程列表页到template目录 创建课程相关的urls.py Mxonline2/urls.py中声明包含到course的url中: # 课程app的url配置 url(r&q ...
- django+xadmin在线教育平台(六)
4-1 使用py3.6和django1.11开发系统前注意事项 直接通过Python3.6和django最新版本来开发我们的系统的一些注意事项. 原版本: Python 2.7 & djang ...
- django+xadmin在线教育平台(十六)
7-7 modelform 提交我要学习咨询1 对应表userask form会对字段先做验证,然后保存到数据库中. 可以看到我们的forms和我们的model中有很多内容是一样的.我们如何让代码重复 ...
- django+xadmin在线教育平台(十四)
7-1 django templates模板继承1 机构可以筛选类别 机构可以根据所在地区进行分类 右侧我要学习功能: form表单提交 右下:授课机构排名 页面头部与底部为全局头和全局底部. Dja ...
- django+xadmin在线教育平台(十一)
6-1 首页和登录页面的配置 用户访问我们的根目录,我们需要把html文件返回给用户.因此我们第一步把html文件放入template目录. mark 在html中找到首页的html.拷贝到我们的 ...
随机推荐
- Codeforces Round #506 (Div. 3) - D. Concatenated Multiples(思维拼接求是否为k的倍数)
题意 给你N个数字和一个K,问一共有几种拼接数字的方式使得到的数字是K的倍数,拼接:“234”和“123”拼接得到“234123” 分析: N <= 2e5,简单的暴力O(N^2)枚举肯定超时 ...
- mysql CPU占用高
https://blog.csdn.net/u011239989/article/details/72863333 QPS高,sql简单的场景下, 需要 1. 提高数据库的服务器性能CPU 内存等 2 ...
- C. Destroying Array 并查集,逆向思维
用并查集维护线段,从后往前枚举没个删除的位置id[i] 那么,现在删除了这个,就是没有了的,但是上一个id[i + 1]就是还没删除的. 然后现在进行合并 int left = id[i + 1];( ...
- vs2017 运行所选代码生成器时出错
[转]https://blog.csdn.net/sunshineyang1205/article/details/80211313 ASPNET MVC Core中像Controller中添加控制器 ...
- Entity Framework小知识
记录在使用EF中使用的技巧,以备查阅. 1.当需要查询一个列总和的时候,如果列是允许NULL或者未查到信息的时候,想要返回的是0 而非NULL时 db.表名.Sum(p=> (decimal?) ...
- win7,docker安装后,创建虚拟机分配不了ip错误 err: exit status 255
问题 win7装docker真麻烦,不如家里的win10爽.另外明明这是个很简单的操作,但是国内的解决方法有点落后,所以我写了个傻瓜式的. 有兴趣的可以直接看issue https://github. ...
- SQLServer 索引的使用情况
—在优化查询SQL语句,查看索引使用情况SQL语句: select db_name(database_id) as N'数据库名称', object_name(a.object_id) as N'表名 ...
- springboot 学习笔记(五)
(五)springboot整合thymeleaf模板,实现简单的登陆 1.修改上一节笔记中的user表,新增一个password字段,同时要求username为UNIQUE,以实现登陆校验,表结构如下 ...
- 输入网址调用第三方接口获取结果_java
最近公司给了一个第三方服务的网址,要我调用后返回需要用到的信息 具体网址:http://www.xxxx.com/xxx-api/xxxx/getXxxByUserId?userId=" + ...
- 【Android车载系统 News | Tech 5】车载设计开发
1. 基于Android的车载移动终端系统的研究与开发 http://wenku.baidu.com/link?url=hIKlQ2myEmR8N0CA28a_SLzLA2Q9R5Xpk20OJ53h ...