3-3 django orm介绍与model设计

上节教程完成后代码(来学习本节前置条件):

github仓库地址:https://github.com/mtianyan/DjangoGetStarted

  • 对应commit: 留言板前端页面展示。本次内容截止教程3-2结束。

可能现在你还在通过手写sql语句来操作数据库,当我们有了orm,数据库操作变得很简单。这一小节我们来学习Django中的orm。

小项目不扫何以扫天下
使用Django+Xadmin打造在线教育平台

演示地址:
http://mxonline.mtianyan.cn

原生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就是为了让我们不再写上面那样的语句,而是像使操作数据库像使用类和类属性一样。

  • 第三章:通过留言板功能回顾django基础知识
    通过做一个小留言板,学习django基础知识
    教程仓库地址1:
    https://github.com/mtianyan/DjangoGetStarted

教程仓库地址1:
https://github.com/mtianyan/DjangoGetStarted
教程仓库地址2:
https://github.com/mtianyan/Mxonline2
教程仓库地址3:
https://github.com/mtianyan/Mxonline3

创建我们的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会发现并没有改动。

mark

因为setting中我们没有注册我们的app: message

注意:新建的app都要在setting中注册

通过留言版功能回顾django基础知识

教程中本章对应上传的仓库为:
https://github.com/mtianyan/DjangoGetStarted

对应第一次commit:留言板仓库初始化。内容截止3-1一章结束。

  • 将对于django目录结构,使用Django快速搭建可以提交的表单页面,models.py
    , urls.py, views.py。
  • 从数据库中取出数据展示到html中:Django Template的配置。
  • 即django的基础知识通过这个留言板项目进行一个全面细致的学习。

8-1 课程列表

拷贝课程列表页到template目录

创建课程相关的urls.py

Mxonline2/urls.py中声明包含到course的url中:

    # 课程app的url配置
    url(r"^course/", include('courses.urls', namespace="course")),

django2.0.1版本:

    # 课程app的url配置
    path("course/", include('courses.urls', namespace="course")),

书写处理列表展示相关的view

courses/views.py

class CourseListView(View):
    def get(self, request):
        return render(request, "course-list.html", { })

courses/urls.py

# encoding: utf-8
from courses.views import CourseListView

__author__ = 'mtianyan'
__date__ = '2018/1/13 0013 00:39'

from django.conf.urls import url

urlpatterns = [
    # 课程列表url
    url(r'^list/$', CourseListView.as_view(), name="list"),

]

django2.0.1版本:

# encoding: utf-8
__author__ = 'mtianyan'
__date__ = '2018/1/13 0013 01:57'

# encoding: utf-8
from courses.views import CourseListView
from django.urls import path
app_name = "courses"
urlpatterns = [
    # 课程列表url
    path('list/', CourseListView.as_view(), name="list"),

]

此时访问没有样式。我们开始对于course list html进行工作
可以观察到它和orglist一样可以有共同的头尾。所以继承base页面

xadmin中添加一些课程。

然后在view中返回课程数据

class CourseListView(View):
    def get(self, request):
        all_course = Course.objects.all()
        return render(request, "course-list.html", {
            "all_course":all_course,

        })

图片 1

mark

保留一个div

图片 2

mark

通过外键字段取外键表中字段

在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

mark

migrate message 生成数据表

mark

前往Navicat验证:

mark

可以看到我们的数据表已经创建成功。默认数据表名称为app名称_类名转换为小写
自动生成的id作为主键。

3-1 django目录结构

django目录:

projectname : 保存Django项目的urls,setting,uwsgi文件

如下图新建一个Django项目DjangoGetStarted,使用我们上章节中已存在的虚拟环境DjangoTest
(里面已经装好了django)

mark

分页功能

拷贝代码:

from pure_pagination import Paginator, EmptyPage, PageNotAnInteger
 # 对课程机构进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_orgs, 4, request=request)
        orgs = p.page(page)

改动完成:

class CourseListView(View):
    def get(self, request):
        all_course = Course.objects.all()
        # 对课程进行分页
        # 尝试获取前台get请求传递过来的page参数
        # 如果是不合法的配置参数默认返回第一页
        try:
            page = request.GET.get('page', 1)
        except PageNotAnInteger:
            page = 1
        # 这里指从allorg中取五个出来,每页显示5个
        p = Paginator(all_course,6 , request=request)
        courses = p.page(page)
        return render(request, "course-list.html", {
            "all_course":courses,

        })

在html中使用时注意object_list

此时的all_course已经不是一个queryset,而是一个purepage对象。

图片 3

mark

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',
)]

django自动生成的目录

初始化完成后的目录如下:(如果不是,那么你们可能创建的不是django项目)

mark

可以看到主目录DjangoGetStarted与项目目录DjangoGetStarted

  • DjangoGetStarted(文件夹):
    • setting.py: 项目全局配置文件
    • urls.py: 主要的urls配置入口
    • wsgi.py: 是Django启动需要的文件。
  • templates(文件夹): 放置html文件
  • manage.py:
    启动Django需要的主要文件。(主要的Django命令都通过manage.py运行)

对于页码进行修改

图片 4

mark

直接把orglist中的那段拿过来就行了。自行替换变量名称

此时已经好了。

介绍字段参数

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

mark

知识点: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

mark

再输入下面命令生成数据表

migrate message 

可以看到上图过程中会告诉我们做了哪些变化,如删除了默认系统生成的主键id
,变更了name。新增了我们的object_id

前往Navicat验证右键设计表:

mark

可以看到object_id已经成为我们的新主键。

还需要我们自己创建的目录

app是Django里一个一个应用的文件夹单位。

通过 Tools -> Run manage.py Task创建app:

mark

排序功能

将之前的sort逻辑拷贝过来:

# 进行排序
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_orgs = all_orgs.order_by("-students")
            elif sort == "courses":
                all_orgs = all_orgs.order_by("-course_nums")

修改完成:

        # 进行排序
        sort = request.GET.get('sort', "")
        if sort:
            if sort == "students":
                all_course = all_course.order_by("-students")
            elif sort == "hot":
                all_course = all_course.order_by("-click_nums")

应放在分页之前。让分页处理所有筛选过的数据

return render时添加

            "sort":sort,

用来判断激活状态。

图片 5

mark

图片 6

mark

修改a标签参数

    # 热门课程推荐
        hot_courses = Course.objects.all().order_by("-students")[:3]
        return render
         "hot_courses":hot_courses

修改html中

图片 7

mark

for循环填充内容

图片 8

mark

这里的degree我们在数据库中填写的是字母。如何显示为中文。

  • 个人猜测: template if

get_degree_display degree是字段名。专门用于choice字段显示

本小节完成对应commit:

8-1完成课程列表页展示,分页,热门课程。

介绍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结束。

startapp message

可以看到当输入startapp message之后,创建了message应用。并存放在了:与项目目录同级目录。

mark

8-2 课程详情页1

拷贝course_detail进入template目录

可以看出这个页面也是继承base页面的。将course_list的页面框架拿过来

替换面包屑。

图片 9

mark

配置url访问

django2.0.1:

    # 课程详情页
    re_path('course/(?P<course_id>\d+)/', CourseDetailView.as_view(), name="course_detail"),

书写对应访问的view

 课程详情处理view

class CourseDetailView(View):
    def get(self, request, course_id):
        return  render(request, "course-detail.html", {

        })

尝试访问:

在列表展示页放入详情的url。

图片 10

mark

有参数类型的把参数也传进来

进行数据填充:先取出当前的课程

        # 此处的id为表默认为我们添加的值。
        course = Course.objects.get(id = int(course_id))

                return  render(request, "course-detail.html", {
            "course":course,
        })

html中取出数据:

图片 11

mark

课程的章节数如何实现?

models.py中自定义方法

    def get_zj_nums(self):
        # 获取课程章节数的方法
        return self.lesson_set.all().count()

添加课程类别字段

    category = models.CharField(max_length=20, default=u"", verbose_name=u"课程类别")

makemigrations
migrate

operation中专门有张表是做用户学习记录的。

UserCourse查询有哪些学生学习了这门课

    # 获取学习这门课程的用户
    def get_learn_users(self):
        # 谁的里面添加了它做外键,他都可以取出来
        return self.usercourse_set.all()[:5]

图片 12

mark

链式调用取出数据

添加一些用户课程进行验证

图片 13

mark

可以看到已经大功告成

课程详情的view中添加clicknums+1

        # 增加课程点击数
        course.click_nums += 1
        course.save()

图片 14

mark

3-4 django model的增删改

github仓库地址:https://github.com/mtianyan/DjangoGetStarted

  • 上小节完成代码对应commit:
    留言板数据库orm映射成表完成。内容截止教程3-3结束。

message/views.py中:

from .models import UserMessage

将我们刚才创建的model,import进来。.代表是与当前同级的目录。

按照下图所示添加一条测试数据。

mark

然后再我们的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')

调试过程:

mark

  • 点击上图小红框位置,打上断点。

  • 点击Run -> debug后:在浏览器里打开:http://127.0.0.1:8000/form/

mark

  • 弹出上图代表已进入断点。

mark

  • 此时鼠标左键点击:all_message.可以看到这是一个{QuerySet}类型的对象,里面存放着[<UserMessage: UserMessage object>]

  • f6使运行到下一步。此时下方的值窗口内可以看到message的值。说明我们成功取到了数据库的值。

mark

新建static目录

使用static目录来存放网站的静态文件:js,css,图片等。

8-3 课程详情页2

图片 15

mark

tab_cont1 中填充我们自己的内容。

图片 16

mark

教师数自定义函数

def get_teacher_nums:
    return self.teacher_set.all().count

不用自定义函数的方法如下

图片 17

mark

filter取出指定要求值

all_message = UserMessage.objects.filter(name=' mtianyan', address='西安')

mark

按照上面调试过程重新调试可以看到我们同样取出了值。

小练习:将名字改为与自己数据库存放值不同的。查看结果。

mark

变成了空列表,说明一切正确。

新建log目录

使用log目录来存放网站的日志文件

课程是否相关

定义课程的tag ,如果tag相同,那么是相关课程。

courses/models.py:

    tag = models.CharField(max_length=15, verbose_name=u"课程标签", default=u"")

更改数据库后必然。此处略。

 tag = course.tag
        if tag:
        # 需要从1开始不然会推荐自己
            relate_courses = Course.objects.filter(tag=tag)[1:2]
        else:
            relate_courses = []

return render加上:

            "relate_courses":relate_courses,

将数据存入数据库

了解: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()
  • 打上断点:如下图。

mark

  • 一直惦记f6单步调试,直到如下图:蓝色到return语句

mark

可以在下方值窗口查看到值

mark

新建media目录

使用media目录存放用户上传的图片等资源。

收藏功能:

将block js写到页面底部。

<script type="text/javascript">
//收藏分享
function add_fav(current_elem, fav_id, fav_type){
    $.ajax({
        cache: false,
        type: "POST",
        url:"{% url "org:add_fav" %}",
        data:{'fav_id':fav_id, 'fav_type':fav_type},
        async: true,
        beforeSend:function(xhr, settings){
            xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
        },
        success: function(data) {
            if(data.status == 'fail'){
                if(data.msg == '用户未登录'){
                    window.location.href="/login/";
                }else{
                    alert(data.msg)
                }

            }else if(data.status == 'success'){
                current_elem.text(data.msg)
            }
        },
    });
}

$('#jsLeftBtn').on('click', function(){
    add_fav($(this), {{ course.id }}, 1);
});

$('#jsRightBtn').on('click', function(){
    add_fav($(this), {{ course.course_org.id }}, 2);
});


</script>

刷新后又不见了的问题,从view中传递has_fav的参数。前台进行判断。

  # 是否收藏课程
        has_fav_course = False
        has_fav_org = False

        # 必须是用户已登录我们才需要判断。
        if request.user.is_authenticated:
            if UserFavorite.objects.filter(user=request.user, fav_id=course.id, fav_type=1):
                has_fav_course = True
            if UserFavorite.objects.filter(user=request.user, fav_id=course.course_org.id, fav_type=2):
                has_fav_org = True

return render

            "has_fav_course":has_fav_course,
            "has_fav_org":has_fav_org,

html中使用;

图片 18

mark

图片 19

mark

8-2&3完成课程详情页展示,课程详情页机构,相关推荐课程。收藏课程,收藏机构。

Navicat进行验证

可以看到成功的添加了数据mtianyan2

mark

解决项目大了之后app过多问题

  1. 新建文件夹 apps
  2. 将message文件夹拖入apps文件夹内:会自动生成__init__.py文件表明这是一个包。使得apps文件夹可导入。

mark

这时我们就会发现在导入我们的message的内容就得配置较长的路径。

mark

每次前面都得加上apps.,这可烦死人啦。

解决方案奉上

apps目录右键markSource Root(Mark
方法查看第一章pycharm简单使用:目录颜色不同的原因)

mark

mark成功之后变蓝(变绿的话,只能摸摸头了,当然选择原谅),然后可以直接使用短路径进行import

如何从html的提交中取到数据并保存进数据库

templates/message_form.html:

mark

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 %}

mark

原有那行删除掉。打上断点

mark

刷新页面并提交。这时候在值窗口可以看到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']}>

mark

数据以dict:key-value 形式存储 key是由如下图html中的name所决定对应的。

mark

Mark后Pycharm 不报错,Cmd下运行报错。

Mark后pycharm知道这是一个项目的Souce Root路径了,但是cmd并不知道。

在项目目录下通过cmd命令行使用python manage.py runserver

mark

pycharm中mark只是pycharm自身可以进行识别短路径。

解决方案:

我们在setting文件中配置我们的apps路径:

mark

图解读:我们需要在setting中向上图一样设置,程序就会接着报错。(换了一个错误了,滑稽脸)

import sys
sys.path.insert(0,os.path.join(BASE_DIR,'apps'))

上述代码为将apps拼接项目绝对路径后的路径插入当前系统的环境变量path中,这样就可以成功解决(个屁屁啊)。

成功性测试(测试已失败):

这个import放到manage.py文件是不行的 你把manage.py中这行删除
因为django整个的配置还没有启动好 import django的model是不行的,

插播:忘了失败吧,我偷学下面方法养你。

终极解决:将这个import方法比如urls.py.等可以成功启动。或者自行删除该import。

mark

红色警告:

You have unapplied migrations; your app may not work properly 
until they are applied. Run 'python manage.py migrate' to apply them.

是因为我们没有进行数据库models进行初始化migrate.

python manage.py migrate我们之后会用到,现在不要做。

数据库新增。

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()
  • 打断点在下图位置:

mark

  • 进入调试:点击点击method:是get请求。因为我们并没有按提交按钮,而是get这个网页

mark

  • 点击f8继续运行我们的项目 浏览器中填写表单内容点提交。

mark

因为这次是表单提交,已经变成了post方式。按f6进行单步调试。

一直单步到如下图蓝色

mark

这时候值浏览窗口可以看到

mark

检查我们的user_message对象的属性是否已经全部添加进去,

使用f8 继续项目并前往Navicat验证

mark

可以看到我们的数据库中已经新增,标志着我们已经成功存入数据。

github仓库项目初始化第一次commit。

mark

输入用户名密码,点击login。

mark

选择左侧导航中Git 设置你的git.exe的路径

mark

点击Share project on GitHub会弹出下图窗口

mark

填写你的项目名称描述。点击share

会弹窗让你选择需要上传的项目文件与commit信息。然后将项目上传至github。

我教程中上传的仓库为:
https://github.com/mtianyan/DjangoGetStarted

对应第一次commit:留言板仓库初始化。内容截止3-1一章结束。

删除数据。

对于查询到的数据做删除:

# 方法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进行验证。

mark

可以看到我们的那条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标签添加值

mark

        <textarea id="message" name="message"  
        placeholder="请输入你的建议">{{ my_message.message }}</textarea>

运行项目,访问:http://127.0.0.1:8000/form/

mark

成功!!我们已经将后台数据库数据成功展示到前台。

template模板渲染中的一些用法。

在我们的template模板中也就是form.html中,不允许我们写Python的语法,
它提供了一套自己的内建标签。

官方文档中template内建标签用法传送门

常用的几种模板标签介绍:

if - else

官方提供模板如下:

mark

个人实践:

mark

满足if运行结果:

mark

不满足if:如改为my_message.name == "mtianyan1"运行结果:

mark

ifequal & ifnotequal

mark

官方文档解释:ifequal a b
相当于f a == b.ifnotequal则相当于if a != b

个人实践:

mark

结果为:未找到中文昵称

slice

mark

官方文档解释:其实就是切片操作。从头开始切到第n个。

个人实践:

mark

本来mtianyanmtianyan1是不同的,但是切片后前八位相同。
运行结果显示 :对应中文昵称:天涯明月笙

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都可以被响应。

mark

特别是如果底下还配置有被这个规则包含的条目,会产生被写在更靠前的拦截住得不到正确处理的Bug。

mark

上图我们是想要让formtest响应admin.site.urls。但是会被form提前拦截住。

所以我们一定要注意加上/$符号。

至此我们完成了留言板项目:学习到了Django必备的基础知识。
下一章我们将开始我们的进阶学习:开发在线教育平台网站。

本章结束:

对应Commit: 留言板项目学习完成,本次内容截止教程3-5。完结,撒花。
项目Github地址:https://github.com/mtianyan/DjangoGetStarted

相关文章