暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Django开发

碧茂大数据 2021-03-08
215

更多精彩,请点击上方蓝字关注我们!

环境安装和配置

pip install virtualenv -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install virtualenvwrapper-win
mkvirtualenv web #创建虚拟环境
workon web #切换到虚拟机环境
pip install django==2.2.7


#settings.py
ALLOWED_HOSTS = ['*']
LANGUAGE_CODE = 'zh-hans'
#TIME_ZONE = 'UTC'
USE_TZ = False


应用环境配置

创建应用

>cd <项目目录>
>python manage.py startapp blog


  • migrations

    迁移文件集合

  • admin.py:项目的后台

  • apps.py:应用设置

  • models.py:模型(数据库)

  • views.py:视图(页面请求和响应)

注册应用

  • 修改settings.py

INSTALLED_APPS = [
...
'blog.apps.BlogConfig'
]


数据库配置

  • 启动mysql服务

  • [shuyun@master ~]$ sudo service mysqld start
    Starting mysqld: [ OK ]


    • 用户: root

    • 密码:123456

    • 端口:3306

    • 数据库连接参数:

  • 确认虚拟机IP

[shuyun@master ~]$ ifconfig
eth5 Link encap:Ethernet HWaddr 00:50:56:3A:1F:12
inet addr:192.168.89.200 Bcast:192.168.89.255 Mask:255.255.255.0


  • settings.py完成mysql配置

    • 开发环境

      DATABASES = {
      'default': {
      'ENGINE': 'django.db.backends.sqlite3',
      'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
      }
      }


    • 生产环境

DATABASES = {
'default':{
'ENGINE':'django.db.backends.mysql',
'NAME':'blog',
'USER':'root',
'PASSWORD':'123456',
'HOST':'192.168.89.200',
'PORT':3306,
}
}


安装pymysql

pip install PyMySQL 


修改blogproj/init.py

import pymysql 
pymysql.install_as_MySQLdb()


创建数据库和授权

[root@master ~]# mysql -uroot -p123456
mysql> create database blog;
mysql> grant all on blog.* to root@'%' identified by '123456';


创建管理员账号

用户:admin,密码:admin

python manage.py createsuperuser


数据模型

在models.py中完成如下配置

博客模型

from django.db import models
from django.contrib.auth.models import User

#文章类别
class Category(models.Model):
#默认自动生成id字段作为主键
name = models.CharField(verbose_name='名称', max_length=100)

#标签
class Tag(models.Model):
#默认自动生成id字段作为主键
name = models.CharField(verbose_name='名称', max_length=100)

class Post(models.Model):
title = models.CharField(verbose_name='标题', max_length=100)
body = models.TextField(verbose_name='正文') #TextField存储大段文本
create_time = models.DateTimeField(verbose_name='创建时间')
modified_time = models.DateTimeField(verbose_name='修改时间')
excerpt = models.CharField(verbose_name='摘要',max_length=255)
category = models.ForeignKey(Category, on_delete=models.CASCADE,verbose_name='类别') #一对多
tags = models.ManyToManyField(Tag, blank=True,verbose_name='标签') #多对多
author = models.ForeignKey(User,on_delete=models.CASCADE,verbose_name='用户')


数据库迁移

python manage.py makemigrations #创建迁移文件
python manage.py migrate #迁移到数据库


ORM操作

存数据

>python manage.py shell
In [1]: from blog.models import Category,Tag,Post
#写入类别
In [2]: cate = Category(name='test cate1')
In [3]: cate.save()
#写入标签
In [4]: tag = Tag(name='test tag1')
In [5]: tag.save()
#写入博客
In [2]: from django.contrib.auth.models import User
In [8]: from django.utils import timezone
In [4]: user = User.objects.get(username='admin')
In [7]: post = Post(title='title_test1',body='body_test1',create_time=timezone.now(),modified_time=timezone.now(),category=cate,author=user)
post.save()


读数据

#读取category
In [18]: cateall = Category.objects.all()
In [19]: cateall
Out[19]: <QuerySet [<Category: Category object (1)>, <Category: Category object (2)>]>
In [20]: cateall[0]
Out[20]: <Category: Category object (1)>
In [21]: cateall[0].name
Out[21]: 'test cate1'
#TODO练习:读取post的body数据
In [22]: post = Post.objects.all()
In [23]: post[0].body
Out[23]: 'body_test1'


删数据

#删类别
In [24]: cate1 = Category.objects.get(name='test cate1')
In [26]: cate1.delete()
Out[26]: (1, {'blog.Category': 1})
#TODO练习:删除post数据
In [27]: post = Post.objects.get(id=1)

In [28]: post.delete()
Out[28]: (1, {'blog.Post_tags': 0, 'blog.Post': 1})


视图

视图函数

  • 修改了blog/views.py

    from django.http import HttpResponse

    def index(request):
    return HttpResponse("欢迎学习Django!")


URL绑定

  • 配置项目URL:blogproj/urls.py

    ....
    from django.conf.urls import url,include

    urlpatterns = [
    ...
    url(r'',include('blog.urls'))
    ]


  • 在blog项目目录下创建urls.py文件

    • 添加代码

      from django.conf.urls import url,include
      from . import views

      urlpatterns = [
      url(r'', views.index, name='index')
      ]


  • 启动开发服务

    python manage.py runserver #默认8000端口
    #Starting development server at http://127.0.0.1:8000/
    python manage.py runserver 127.0.0.1:8001 #指定端口启动


    浏览器访问



模板系统

模板指静态页面(html)

静态文件:css、js

  • 创建templates/blog目录,新建index.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
    </head>
    <body>
    <h1>{{ welcome }}</h1>
    </body>
    </html>


{{ title }},{{ welcome }}:模板变量


  • 修改views.py

def index(request):
context = {'title':"Dylan的Blog", 'welcome':'欢迎来到我的博客'}
return render(request, 'blog/index.html', context=context)


  • 刷新页面



博客首页

静态文件

  • 拷贝模板

    • 项目目录下创建static/blog目录

    • 拷贝css和js到上述目录

    • 拷贝index.html到templates/blog目录

  • 修改settings

STATIC_ROOT = os.path.join(BASE_DIR,'static')  #新增


  • 修改index.html

{% load static %}
...
<!-- css -->
<link rel="stylesheet" href="{% static 'blog/css/bootstrap.min.css' %}">
<link rel="stylesheet" href="http://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
<link rel="stylesheet" href="{% static 'blog/css/pace.css' %}">
<link rel="stylesheet" href="{% static 'blog/css/custom.css' %}">

<!-- js -->
<script src="{% static 'blog/js/jquery-2.1.3.min.js' %}"></script>
<script src="{% static 'blog/js/bootstrap.min.js' %}"></script>
<script src="{% static 'blog/js/pace.min.js' %}"></script>
<script src="{% static 'blog/js/modernizr.custom.js' %}"></script>
</head>
...
<script src="{% static 'blog/js/script.js' %}"></script>
</body>
...

模板修改

视图

  • 修改views.py

...
from .models import Post
def index(request):
post_list = Post.objects.all().order_by("-create_time") #按照创建时间降序排列
context = {'post_list':post_list}
return render(request, 'blog/index.html', context=context)

模板

文章列表

  • 删除index.html的多余article,只保留1个


修改模板

遍历博客

                {% for post in post_list %}
<article class="post post-{{ post.id }}">
...
</article>
{% empty %}
<div class="no-post">暂时没有发布的文章!</div>
{% endfor %}

标题

<h1 class="entry-title">
<a href="single.html">{{ post.title }}</a>
</h1>

详情

<div class="entry-meta">
<span class="post-category"><a href="#">{{ post.category.name }}</a></span>
<span class="post-date"><a href="#"><time class="entry-date"
datetime="{{ post.create_time }}">
{{ post.create_time }}</time></a></span>
<span class="post-author"><a href="#">{{ post.author.username }}</a></span>
...
</div>

摘要

<div class="entry-content clearfix">
<p>{{ post.excerpt }}</p>
...

后台

注册模型

  • 修改blog/admin.py

from .models import Category,Tag,Post

admin.site.register(Category)
admin.site.register(Tag)
admin.site.register(Post)


汉化

  • 应用汉化, apps.py

class BlogConfig(AppConfig):
name = 'blog'
verbose_name = '博客'

  • 模型汉化, models.py

class Category(models.Model):
...
class Meta:
verbose_name='类别'
verbose_name_plural = verbose_name #复数形式
class Tag(models.Model):
...
class Meta:
verbose_name='标签'
verbose_name_plural = verbose_name #复数形式
class Post(models.Model):
...
class Meta:
verbose_name='文章'
verbose_name_plural = verbose_name #复数形式

  • 返回结果(对象->字符串)

class Category(models.Model):
...
def __str__(self):
return self.name
class Tag(models.Model):
...
def __str__(self):
return self.name
class Post(models.Model):
...
def __str__(self):
return self.title

定制后台

  • 只显示需要的字段

admin.site.register(Category)
admin.site.register(Tag)

class PostAdmin(admin.ModelAdmin):
list_display = ['title','create_time','modified_time','category','author']

admin.site.register(Post,PostAdmin)


  • 控制表单展示的字段和填充当前用户作为作者

    admin.py

...
class PostAdmin(admin.ModelAdmin):
list_display = ['title','create_time','modified_time','category','author']
fields = ['title','body','excerpt','category','tags']

def save_model(self, request, obj, form, change):
obj.author = request.user #当前用户赋值
super().save_model(request, obj, form, change)
...

  • 自动填充创建时间和修改时间

    models.py

from django.utils import timezone
class Post(models.Model):
...
create_time = models.DateTimeField(verbose_name='创建时间',default=timezone.now)
...
def save(self, *args, **kwargs):
self.modified_time = timezone.now() #修改时间的自动调整
super().save(*args,**kwargs)


详情页

URL映射

  • url绑定

    blog/urls.py

    urlpatterns = [
    path(r'', views.index, name='index'),
    path('posts/<int:pk>', views.detail, name='detail')
    ]

  • 视图

    views.py

    from django.shortcuts import render,get_object_or_404
    ...
    def detail(request,pk):
    post = get_object_or_404(Post, pk=pk)
    context = {'post':post}
    return render(request,'blog/detail.html',context)

  • 模板

    • 把single.html拷贝到templates/blog目录,更名为detail.html

    • blog/urls.py增加app_name

      app_name = 'blog'
      ...

    • index.html

      <header class="entry-header">
      <h1 class="entry-title">
      <a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
      </h1>

    • models.py

      from django.urls import reverse
      ...
      class Post(models.Model):
      ...
      def get_absolute_url(self):
      return reverse('blog:detail', kwargs={'pk':self.pk})

模板继承

模板页

  • 创建templates/base.html,把index.html的内容拷贝过来,修改如下:

    <div class="content-body">
    ...
    <main class="col-md-8">
    {% block main %}
    {% endblock main %}
    </main>
    <aside class="col-md-4">
    {% block aside %}
    {% endblock aside %}
    </aside>
    ...
    </div>

主页继承模板

  • 修改index.html

    {% extends 'base.html' %}
    {% block main %}
    {% for post in post_list %}
    <article class="post post-{{ post.id }}">
    ...
    </article>
    {% empty %}
    <div class="no-post">暂时没有发布的文章!</div>
    {% endfor %}

    <div class="pagination">
    ...
    </div>
    {% endblock main %}


详情页继承模板

{% extends 'base.html' %}
{% block main %}
<article class="post post-{{ post.pk }}">
<header class="entry-header">
<h1 class="entry-title">{{ post.title }}</h1>
<div class="entry-meta">
<span class="post-category"><a href="#">{{ post.category.name }}</a></span>
<span class="post-date"><a href="#"><time class="entry-date"
datetime="{{ post.create_time }}">
{{ post.create_time }}</time></a></span>
<span class="post-author"><a href="#">{{ post.author.username }}</a></span>
<span class="comments-link"><a href="#">4 评论</a></span>
<span class="views-count"><a href="#">588 阅读</a></span>
</div>
</header>
<div class="entry-content clearfix">
{{ post.body }}
</div>
</article>
<section class="comment-area" id="comment-area">
...
{% endblock main %}
{% block aside %}
<div class="widget widget-content">
...
</div>
{% endblock aside %}


  • 静态文件处理

    把/static 移动到/blog目录下,并重启runserver

支持Markdown

  • 安装

    >pip install markdown

  • 修改detail视图,支持markdown

    ...
    def detail(request,pk):
    post = get_object_or_404(Post, pk=pk)
    #把markdown转换成html标签
    post.body = markdown.markdown(post.body, extensions=[
    'markdown.extensions.extra',
    'markdown.extensions.codehilite',
    'markdown.extensions.toc',
    ])
    context = {'post':post}
    return render(request,'blog/detail.html',context)
    ...

  • detail.html增加safe标签,解除html转义

    <div class="entry-content clearfix">
    {{ post.body|safe }}
    </div>

自动生成目录

  • 修改views.py

def detail(request,pk):
post = get_object_or_404(Post, pk=pk)
md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc',
])
# 把markdown转换成html标签
post.body = md.convert(post.body)
post.toc = md.toc #目录
context = {'post':post}
return render(request,'blog/detail.html',context)

  • 修改detail.html

{% block aside %}
<div class="widget widget-content">
<h3 class="widget-title">文章目录</h3>
{{ post.toc|safe }}
</div>
...

自动摘要生成

重写save,修改摘要

models.py

class Post(models.Model):
...
def save(self, *args, **kwargs):
self.modified_time = timezone.now() #修改时间的自动调整
#生成摘要
md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
])
self.excerpt = strip_tags(md.convert(self.body))[:50]
super().save(*args,**kwargs)

前端使用摘要标签

index.html

</header>
<div class="entry-content clearfix">
<p>{{ post.excerpt }}</p>

  • 方法2:直接用模板过滤器

    index.html

                        <div class="entry-content clearfix">
    <p>{{ post.body|truncatechars:60 }}</p>

自定义模板标签

  • 创建blog/templatetags/blog_extras.py,templatetags是package

  • 创建templates/blog/inclusions目录,用来存放模板标签html

最新文章

  • 定义模板标签

blog_extras.py添加

from blog.models import Post,Category,Tag
from django import template
register = template.Library()

@register.inclusion_tag('blog/inclusions/_recent_posts.html',takes_context=True)
def show_recent_posts(context,num=3):
post_list = Post.objects.all().order_by('-create_time')[:num]
return {'recent_post_list':post_list}

  • 添加模板

创建templates/blog/inclusions/_recent_posts.html

<div class="widget widget-recent-posts">
<h3 class="widget-title">最新文章</h3>
<ul>
{% for post in recent_post_list %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</li>
{% empty %}
暂无文章!
{% endfor %}
</ul>
</div>

  • 使用模板标签

    base.html

    {% load blog_extras %}
    ...
    <aside class="col-md-4">
    {% block aside %}
    {% endblock aside %}
    {% show_recent_posts %}
    </aside>

分类

  • 注册分类模板标签:show_categories

    blog_extras.py

    ...
    @register.inclusion_tag('blog/inclusions/_categories.html', takes_context=True)
    def show_categories(context):
    return {'category_list':Category.objects.all()}

  • 创建模板:_categories.html

     <div class="widget widget-category">
    <h3 class="widget-title">分类</h3>
    <ul>
    {% for cate in category_list %}
    <li>
    <a href="#">{{ cate.name }} <span class="post-count">(13)</span></a>
    </li>
    {% empty %}
    暂无分类!
    {% endfor %}
    </ul>
    </div>

  • 使用模板标签

base.html

...
<aside class="col-md-4">
...
{% show_categories %}
</aside>

练习1:模板标签

归档

标签云

其他页面

分类

  • 视图函数

    views.py

    from .models import Post,Category
    ...
    def category(request, pk):
    cate = get_object_or_404(Category, pk=pk) #类别对象
    post_list = Post.objects.filter(category=cate).order_by('-create_time')
    return render(request, 'blog/index.html', context={'post_list':post_list})

  • url映射

    blog/urls.py

    urlpatterns = [
    ...
    path('categories/<int:pk>', views.category, name='category'),
    ]

  • 模板页面跳转

    • 修改blog/inclusions/_categories.html

...
<li>
<a href="{% url 'blog:category' cate.pk %}">{{ cate.name }} <span class="post-count">(13)</span></a>
...

练习2

标签页

归档页

部署

环境搭建

  • python3安装、虚拟环境,依赖包

  • 激活虚拟环境

    source home/shuyun/web/bin/activate

  • 创建项目目录并授权给shuyun

    mkdir -p home/shuyun/program
    chown -R shuyun.shuyun home/shuyun/program

  • 项目打包,上传到服务器(put、svn、git)的/home/shuyun/program

  • 解压项目文件

    cd home/shuyun/program
    unzip blogproj.zip

  • 测试

    cd home/shuyun/program/blogproj
    python manage.py runserver 0.0.0.0:8000

浏览器访问 http://服务器IP:8000

使用gunicorn

  • 确保服务器可以访问公网

  • 安装

    pip3 install gunicorn

  • 启动服务到后台

    nohup gunicorn blogproj.wsgi -w 2 -k gthread -b 0.0.0.0:8000 &

    浏览器访问: http://服务器IP:8000

Nginx

  • 安装

    # yum install nginx -y

  • 配置修改

    • /etc/nginx/nginx.conf

      user shuyun;
      ...

    • 创建/etc/nginx/conf.d/blogproj.conf

      server {
      charset utf-8;
      listen 8080;
      server_name 0.0.0.0;

      location static {
      alias home/shuyun/program/blogproj/static;
      }

      location {
      proxy_set_header Host $host;
      proxy_pass http://127.0.0.1:8000;
      }
      }

  • 启动服务

    # service nginx start

  • 收集静态文件

    $ python manage.py collectstatic

浏览器访问:http://192.168.89.200:8080/

本文完〜

图文 / 来源网络

版权归原作者所有,侵联删

END


碧茂课堂精彩课程推荐:

1.Cloudera数据分析课;

2.Spark和Hadoop开发员培训;

3.大数据机器学习之推荐系统;

4.Python数据分析与机器学习实战;

详情请关注我们公众号:碧茂大数据-课程产品-碧茂课堂

现在注册互动得海量学币,大量精品课程免费送!




关注最新行业动态,

加群进行技术交流




文章转载自碧茂大数据,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论