Django入门-简易博客

慕课网课程:django入门与实践学习笔记

安装Django

pip install Django

新建项目

django-admin startproject HelloWorld

新建app

进入manage.py所在目录:

python manage.py startapp blog

然后在settings.py文件中加入新建的app:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

注意:新建的App名称不能和Django已有的App名称冲突。

配置Url

首先在blog下的views.py文件中定义处理请求的方法:

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.


def index(request):
    return HttpResponse("Hello World!")

然后配置URL:

方式一 直接添加

HelloWorld目录下的urls.py文件中,先导入刚才修改的views.py文件,然后添加相应的url:

from django.contrib import admin
from django.urls import path,include
from blog import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('index/', views.index),
]

运行后就可以通过localhost:8000/index/访问,可以看到返回的Hello Word!

方式二 通过include添加

先在刚刚新建的app blog目录下新建一个urls.py文件,在这里配置这个app相应的urls

from django.urls import path
from . import views

urlpatterns = [
    path('index/', views.index),
]

然后在HelloWorld目录下的urls.py文件中导入django.urls.include,通过include的方式将刚才新建的urls.py文件引入:

from django.contrib import admin
from django.urls import path,include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include("blog.urls")),
]

这时运行后通过localhost:8000/blog/index/访问,注意与方式一的差别。

创建Templates

blog的目录下新建templates目录,然后在blog/templates目录下新建blog目录(这样做是为了防止多个app下模板名冲突)。

然后在blog/templates/blog/下新建模板:index.html




    
    Title


    

{{ hello }}

然后在views.py下处理请求时返回这个模板页面的内容,需要用到render,修改之前的views.py文件为:

from django.shortcuts import render
from django.http import HttpResponse


def index(request):
    return render(request, 'blog/index.html', {'hello': 'Hello, Blog!'})

这里使用render返回模板内容,render中前两个参数是必填参数,还有其他几个非必填的参数,其中这里用到一个Dict字典,即{'hello': 'Hello, Blog!'},在模板index.html中,会自动填入hello对应的值。

创建Models

在Django中,一个Model对应数据库的一张数据表,Models以类的形式表现,包含一些基本字段及数据的一些行为。

新建

首先在应用根目录blog下创建models.py,引入django.db.models模块:

from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=32, default='Title')
    content = models.TextField(null=True)

这里创建了一个Article类,包含两个字段titlecontentCharFieldTextField表示对应的数据类型,default可以传入一个默认值,null=True表示可以为空。官方文档

生成数据表

生成数据迁移:

python manage.py makemigrations appName(可选)

迁移:

python manage.py migrate

blog/migrations文件夹下可以看到生成了一个迁移文件0001_initial.py

然后可以使用命令python manage.py sqlmigrate appName fileId查看SQL语句:

python manage.py sqlmigrate blog 0001

打印结果:

BEGIN;
--
-- Create model Article
--
CREATE TABLE "blog_article" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(32) NOT NULL, "content" text NULL);
COMMIT;

数据库文件保存在db.sqlite3中,可以使用第三方软件查看(SQLite Expert Personal轻量级且完全免费)。

Ubuntu系统下可以安装sqlite3,在命令行中直接操作数据库文件。

Ubuntu下sqlite3的安装和使用

安装:

sudo apt-get install sqlite3

简单使用:

创建和打开数据库:

sqlite3 test.db

如果当前目录存在test.db则会打开,否则会在当前目录创建test.db文件

查看数据表:

```sql lite
.tables


创建数据表``create table 表名(字段名)``:

```sql lite
create table class(ID int primary key , name text);

查看表中字段信息.schema 表名

```sql lite
.schema class


删除表``drop table 表名``:

```sql lite
drop table class;

添加记录insert into (列名1,列名2..) 表名 values( )

```sql lite
insert into class values (1, ‘Mike’);


删除记录``delete from 表名 where 条件``:

```sql lite
delete from class where ID = 1;

修改记录update 表名 set column1=value1,... where 条件

```sql lite
update class set name=’Jack’ where ID=1


查询记录``select 指定字段 from 表名 where 条件``:

```sql lite
select * from class

调整显示格式:

```sql lite
.header on
.mode column
select * from class;


退出:

```sql lite
.quit

页面呈现数据

通过sqlite工具可以看到db.sqlite3数据库中自动生成了一些表,其中包括blog_article表,就是对应的Article模型。

先在blog_article表中插入一段记录:

```sql lite
insert into blog_article values (‘Hello’, ‘Hello,Blog!’);


然后就是将这条记录展示在页面上,首先在``views.py``中导入``models``包,然后取出主键为1的数据:

```python
from . import models

article = models.Article.objects.get(pk=1)

通过render传递给前端:

from django.shortcuts import render
from . import models

def index(request):
    article = models.Article.objects.get(pk=1)
    return render(request, 'blog/index.html', {'article': article})

前端的模板可以直接使用对象及对象的"."操作,修改模板index.html如下:




    
    Title


    

{{ article.title }}

{{ article.content }}

在浏览器中访问就可以看到内容了。

Admin

Admin是Django自带的自动化数据管理界面,被授权的用户可以直接在Admin中管理数据库

配置Admin

创建超级用户

python manage.py createsuperuser

输入用户名、邮箱、密码(至少8位)

打开localhost:8000/admin/就可以访问

(修改settings.py中的LANGUAGE_CODE = 'zh_Hans'可将界面改为中文)

配置应用

在应用下的admin.py中引入自身的models模块(或里面的模型类),然后注册模型类,编辑blog目录下的admin.py

from django.contrib import admin
from .models import Article


admin.site.register(Article)

浏览器中刷新以下就可以看到Article了,点击进去可以很方便的管理Article的内容了。

修改数据默认显示名称

在点开Article管理它的所有实例时,看到每一个实例显示的是Article Object,这样不方便识别。

Article类下添加一个方法,Python3.6添加__str__(self),Python2.7添加__unicode__(self)方法,修改models.py文件:

from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=32, default='Title')
    content = models.TextField(null=True)

    def __str__(self):
        return self.title

这里返回的是文章的标题,那么在Article的管理界面,每一个Article的实例都会显示它的标题。

博客主页面

展示所有文章的列表

模板For循环

{% for xx in xxs %}
HTML语句
{% endfor %}

取出所有的文章,修改views.py

from django.shortcuts import render
from django.http import HttpResponse
from . import models


def index(request):
    # article = models.Article.objects.get(pk=1)
    articles = models.Article.objects.all()
    return render(request, 'blog/index.html', {'articles': articles})

展示文章列表,修改index.html




    
    Title


    

新文章

{% for article in articles %} {{ article.title }}
{% endfor %}

(超链接先暂时空着)

文章内容页面

先添加一个文章内容的模板,在blog/templates/blog/目录下新建article_page.html




    
    Article Page


    

{{ article.title }}


{{ article.content }}



修改文章

views.py文件中新增一个article_page方法,接收文章主键:

def article_page(request, article_id):
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'blog/article_page.html', {'article': article})

这里根据文章主键获取到对应的文章,传递给article_page.html模板。

配置Url,修改urls.py

urlpatterns = [
    path('index/', views.index),
    path('article//', views.article_page)
]

article/后面匹配一个数字,比如article/1/,表示文章的ID。在浏览器中访问localhost:8000/blog/article/1/就可以看到第一篇文章的内容。

Django中的超链接

template中的超链接:

{% url 'app_name:url_name' param %}

其中app_nameurl_name都在url中配置:

  • 在根urls.py里,为应用添加命名空间,写在include()函数的第二个参数位置,namespace='blog'
  • 在应用下的urls.py里,添加url的名称,写在url()/path()函数的第三个参数位置,``name=’article’

修改HelloWorld/urls.py

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include("blog.urls", namespace='blog')),
]

修改blog/urls.py,注意最下面要加上app_name='blog'

urlpatterns = [
    path('index/', views.index),
    path('article//', views.article_page, name='article_page'),
]
app_name = 'blog'

然后修改index.html配置超链接:


    

新文章

{% for article in articles %} {{ article.title }}
{% endfor %}

然后通过点击文章标题,就可以跳转到文章内容页面了。

博客编写页面

首先新建一个模板文件edit_page.html




    
    Edit Page




然后在views.py中添加一个响应函数:

def edit_page(request):
    return render(request, 'blog/edit_page.html')

urls.py中配置url:

path('edit/', views.edit_page)

基本配置完成后,就需要编写一个响应函数,处理Post请求:

获取Post表单数据:request.POST.get('name', 'DefaultValue')request.POST['参数名']

Django新建Article数据:models.Article.objects.create(title=title, content=content)

views.py中添加新的响应函数:

def edit_action(request):
    # 默认值设置为'TITLE','CONTENT'
    title = request.POST.get('title', 'TITLE')
    content = request.POST.get('content', 'CONTENT')
    # 新建一个Article
    models.Article.objects.create(title=title, content=content)

    # 返回到主页
    articles = models.Article.objects.all()
    return render(request, 'blog/index.html', {'articles': articles})

修改urls.py添加url并添加url的名称:

from django.urls import path
from . import views

urlpatterns = [
    path('index/', views.index, name='index'),
    path('article//', views.article_page, name='article_page'),
    path('edit/', views.edit_page, name='edit_page'),
    path('edit/action/', views.edit_action, name='edit_action')
]
app_name = 'blog'

然后修改edit_page.html文件,为表单添加action

{% csrf_token %}

其中csrf_token用于防止跨站请求伪造,凡是用到POST的表单,都需要添加这样一句话。(在hexo里,行级代码不能出现({+%+内容+%+} )这种语法,可能是模板语法的冲突,在块级代码中没事)

博客编写页面完成,可以为主页index.html新文章链接添加一个超链接:

新文章

这里还有一个小问题,就是每次刷新的时候都会新建一个article,而且都是默认值,解决办法如下:

修改views.py,导入HttpResponseRedirectreverse模块:

from django.http import HttpResponseRedirect
from django.urls import reverse

修改edit_action函数如下:

def edit_action(request):
    # 默认值设置为'TITLE','CONTENT'
    title = request.POST.get('title', 'TITLE')
    content = request.POST.get('content', 'CONTENT')
    # 新建一个Article
    models.Article.objects.create(title=title, content=content)

    # 返回到主页
    return HttpResponseRedirect(reverse('blog:index'))

修改文章

由于Article的id是由1开始递增,利用这个特点,我们可以复用edit_page.html来同时作为编写文章和修改文章的页面。即编写文章时,传入文章id为0;修改文章则将这篇文章的id传进去。

修改views.pyedit_page()方法:

def edit_page(request, article_id):
    if str(article_id) == '0':
          # 传入的id
        return render(request, 'blog/edit_page.html')
    article = models.Article.objects.get(pk=article_id)
    return render(request, 'blog/edit_page.html', {'article': article})

修改urls.py,在edit_page的url添加接收article_id

path('edit//', views.edit_page, name='edit_page'),

然后在index.htmlarticle_page.html中链接到edit_page的超链接传入文章id:

新文章

{% for article in articles %} {{ article.title }}
{% endfor %}

{{ article.title }}


{{ article.content }}



修改文章

edit_page.html中根据article_id判断是新建还是修改,修改的话要设置标题和内容:

{% csrf_token %} {% if article %}

{% else %}

{% endif %}

<input type="hidden" name="article_id" value=""><input type="hidden" name="article_id" value="0">是为了传递给edit_action()函数,用于判断是修改还是新建。然后修改views.py中的edit_action()函数:

def edit_action(request):
    # 默认值设置为'TITLE','CONTENT'
    title = request.POST.get('title', 'TITLE')
    content = request.POST.get('content', 'CONTENT')
    article_id = request.POST.get('article_id', 0)
    if article_id == '0':
        # 新建一个Article
        models.Article.objects.create(title=title, content=content)
        # 返回到主页
        return HttpResponseRedirect(reverse('blog:index'))
    else:
          # 修改文章内容
        article = models.Article.objects.get(pk=article_id)
        article.title = title
        article.content = content
        article.save()
        # 跳转到文章页面
        return render(request, 'blog/article_page.html', {'article': article})

补充内容

Templates过滤器

过滤器写在模板中,属于Django模板语言,可以修改模板中的变量,从而显示不同的内容

{{ value | filter }}

过滤器可叠加:

{{ value | filter1 | filter2 | ... }}

edit_page.html页面的代码可以简写为:





利用过滤器默认传递article_id的值为0,省去了冗余的if_else代码。另外value=""这里不用使用过滤器,因为article不存在的话得到的是空值,在这里显示空值不会有问题。

Django Shell

是一个Python的交互式命令行程序,自动引入了我们的项目环境,我们可以使用它与我们的项目进行交互。

使用Django Shell:

python manage.py shell

进入Django Shell交互环境后,可以直接使用命令与项目交互,比如:

>>> from blog.models import Article
>>> Article.objects.all()
, , , , , , , , , ]>
>>>

这里直接打印出了之前创建的所有Articles记录

Django Shell的作用:

  • 我们可以使用Django Shell来进行一些调试工作
  • 可以用来测试一些未知的方法

Admin增强

admin.py中创建admin配置类class ArticleAdmin(admin.ModelAdmin),在注册时和Article绑定admin.site.register(Article, ArticleAdmin)

然后在ArticleAdmin类中进行配置,比如显示其他字段list_display或者设置过滤器list_filter

为了效果明显,先给Article新增一个pub_time字段,修改models.py

class Article(models.Model):
    title = models.CharField(max_length=32, default='Title')
    content = models.TextField(null=True)
    pub_time = models.DateField(auto_now=True)

    def __str__(self):
        return self.title

pub_time作为发布时间,自动设置。然后别忘了数据迁移:

python manage.py makemigrations

python manage.py migrate

然后修改admin.py

class ArticleAdmin(admin.ModelAdmin):
      # 显示的字段
    list_display = ('title', 'content', 'pub_time')
    # 过滤器
    list_filter = ('pub_time',)


admin.site.register(Article, ArticleAdmin)

现在在admin中管理Article就可以看到这三个字段,并且由于设置了pub_time过滤器,右侧会出现一个pub_time的过滤器,可以点击YesterdayTodayPast 7 days等等选项。