1. 程式人生 > >Django+Bootstrap+Mysql 搭個人部落格

Django+Bootstrap+Mysql 搭個人部落格

初始化

新建專案

#pycharm手動建立django專案或如下
$ django-admin.py startproject website

#建立Django app
$ python manage.py startapp blog

更改資料庫配置(sqlite->mysql)

#/website/setting.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'blog',        #資料庫名字
        'USER'
: 'root', #賬號 'PASSWORD': 'tony', #密碼 'HOST': '127.0.0.1', #IP 'PORT': '3306', #埠 } }

更改資料庫配置還需初始化

#/website/__init__.py
import pymysql
pymysql.install_as_MySQLdb() 

#下面的只是除錯
db = pymysql.connect("localhost", 'root', 'tony', 'blog')
cursor =
db.cursor() cursor.execute("select version()") #執行sql語句除錯一波 data = cursor.fetchone() print(data) db.close()

模型設計

一個model也是一個數據庫的對映

#/blog/models.py
from django.db import models
from django.contrib.auth.models import User

class Category(models.Model):
    name = models.CharField('分類',max_length=
128) def __str__(self): return self.name class Meta: verbose_name = '部落格分類' verbose_name_plural = verbose_name class Tag(models.Model): name = models.CharField('標籤', max_length=128) def __str__(self): return self.name class Meta: verbose_name = '部落格標籤' verbose_name_plural = verbose_name class Entry(models.Model): title = models.CharField('文章標題',max_length=128) author = models.ForeignKey(User,verbose_name='作者',on_delete=models.CASCADE) img = models.ImageField(upload_to='blog_img',null=True,blank=True,verbose_name='部落格配圖') body = models.TextField('正文',) abstract = models.TextField('摘要',max_length=256,null=True,blank=True) visiting = models.PositiveIntegerField('訪問量',default=0) category = models.ManyToManyField('Category',verbose_name='部落格分類') tags = models.ManyToManyField('Tag',verbose_name='標籤') created_time = models.DateTimeField('建立時間',auto_now_add=True) modifyed_time = models.DateTimeField('修改時間',auto_now=True) def __str__(self): return self.title class Meta: ordering = ['-created_time'] verbose_name = '部落格正文' verbose_name_plural = verbose_name

admin:後臺管理介面, 新增刪除網站的內容

#/blog/admin.py
from django.contrib import admin
from . import models

class EntryAdmin(admin.ModelAdmin):
    list_display = ['title','author','visiting','created_time','modifyed_time']


admin.site.register(models.Category)
admin.site.register(models.Tag)
admin.site.register(models.Entry,EntryAdmin)

建立超級使用者
$ python manage.py createsuperuser

此時如果出現No such Table ‘auth_user’,說明沒有初始化(建立)預設資料庫表
建立預設庫
$ python manage.py migrate
如果已經執行過上面命令,就$ python manage.py makemigrations

url、views

#/website/urls.py
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/',include('blog.urls') ),
]
#/blog/urls.py
from django.conf.urls import url
from . import views

app_name = 'blog'

urlpatterns = [
    url(r'^$', views.index,name='blog_index'),
    url(r'^(?P<blog_id>[0-9]+)', views.detail,name='blog_detail'),
]
#/blog/views.py
from django.shortcuts import render

def index(request):

    return render(request,'blog/index.html',locals())


def detail(request,blog_id):

    return render(request,'blog/detail.html',locals())

基本前端

bootstrap和js都放進/static/

#/website/setting.py 新增靜態檔案路徑
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static'),
]
#/blog/templates/blog/detail.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>部落格詳情</title>
</head>
<body>
<h1>部落格{{ blog_id }}的詳情</h1>

</body>
</html>
#/blog/base.html
{% load staticfiles %}

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="utf-8">
    <title>{% block title %}{% endblock %}</title>

    <link href="{% static 'bootstrap/css/bootstrap.min.css' %}" rel="stylesheet">
    <link href="{% static 'blog/css/blog_nav.css' %}" rel="stylesheet">
    {% block css %}{% endblock %}

</head>
<body>
<nav class="navbar navbar-fixed-top">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#my-nav" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">hhh</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="my-nav">
      <ul class="nav navbar-nav">
        <li class="active"><a href="/blog/">部落格</a></li>
        <li ><a href="#">學習資源</a></li>
        <li ><a href="#">聯絡我</a></li>
      </ul>

      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">搜尋</button>
      </form>

      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">登入</a></li>
      </ul>

    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>


{% block content %}{% endblock %}

 <footer>
    <div class="footer" role="navigation">
        <div class="container">
            <div class="navbar-text">
                <ul class="footer-text">
                    <li><a href="#">主頁</a></li>
                               <li><a href="#">聯絡我們</a></li>
                               <li><a href="#">關於博主</a></li>
                               <li><a href="#">文件支援</a></li>
                               <li><a href="/blog/">部落格首頁</a></li>
                </ul>
                <p>Copyright © 2018 hh </p>

            </div>
        </div>
    </div>
</footer>


<script src="{% static 'jquery-3.3.1.min.js' %}"></script>
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>

{% block script %}{% endblock %}

</body>
</html>
#/static/blog/css/blog_nav.css
body {
    margin-top: 30px;
    font-weight: 400;
    /* Required padding for .navbar-fixed-top. Change if height of navigation changes. */
    padding-top: 70px;
}

/* Navbar and footer (global) styling */
.navbar-fixed-top .nav {
    padding: 15px 0;
}

.navbar {
    color: black;
    border-width: thin;
    -webkit-transition: .2s;
    background-color: white;
    border-bottom: 1px solid #e0e0e0;
    background-color: white;
}

.navbar a {
    color: black;
}

.navbar-fixed-top .navbar-brand {
    padding: 0 15px;
}

.navbar-header .icon-bar {
    background-color: black;
}

.navbar-nav > li > .navbar-active {
    color: #E46E2E;
}

.navbar-scroll {
  background-color: white;
    animation-duration: 2s;
    animation-name: smooth;
    -moz-box-shadow: 1px 1px 1px #999;
    -webkit-box-shadow: 1px 1px 1px #999;
    box-shadow: 1px 1px 1px #999;
}

.jupytercon-nav > li > .black-tab {
    color: black;
}

.navbar-logo {
    height: 45px;
}

.nav > li > a {
    font-size: 20px;
    padding: 12px 16px 10px;
}

.nav > li > a:hover {
    background-color: transparent;
    color: #E46E2E;
    -webkit-transition: .2s;
}

.nav > li > a:focus {
    background-color: white;
}

.nav > li > a:active {
    background-color: #F8F8F8;
}

.nav > li > a:visited {
    background-color: #F8F8F8;
}

.tab:hover {
    background-color: transparent;
    color: #E46E2E;
}

.footer {
    background-color: #979797;
}

.footer p {
    color: white;
    padding-top: 10px;
}

.footer li {
    color: white;
    display: inline-block;
    text-decoration: none;
}

.footer a {
    color: white;
    text-decoration: none;
}

.footer li::after {
    content:" |";
}

.footer li:last-of-type::after {
    content:"";
}

.footer-text {
    font-size: 16px;
    margin-left: 0;
    padding-left: 0;
}

.navbar-brand {
    float: left;
    height: 50px;
    padding: 15px 15px;
    font-size: 20px;
    line-height: 20px;
    margin-top: 27px;
}

nav .navbar-form{
    padding: 10px;
}
#/blog/index.html
{% extends 'blog/base.html' %}

{% block title %}部落格首頁{% endblock %}

{% block content %}

    部落格首頁
    <div style="height: 440px; " ></div>

{% endblock %}

最終目錄如下:
在這裡插入圖片描述

前端設計

#/website/setting.py
....
MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace("//","/")
MEDIA_URL = '/media/'

新增圖片的url

#/website/urls.py
from django.conf.urls import url,include
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static


urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^blog/',include('blog.urls') ),

] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT )        #新增圖片的url

新增兩個方法

#/blog/models.py
class Entry(models.Model):
		...
    def get_absolute_url(self):
        #獲取當前部落格詳情頁的url
        return reverse("blog:blog_detail",kwargs={"blog_id":self.id})     #app名字,詳情頁url的別名,引數是當前部落格的id

    def increase_visiting(self):
        #訪問量加1
        self.visiting += 1
        self.save(update_fields=['visiting'])   #只儲存某個欄位
#/blog/views.py
from django.shortcuts import render
from . import models

def index(request):
    entries = models.Entry.objects.all()

    return render(request,'blog/index.html',locals())


def detail(request,blog_id):
    entry = models.Entry.objects.get(id=blog_id)
    entry.increase_visiting()

    return render(request,'blog/detail.html',locals())
#index.html
{% extends 'blog/base.html' %}

{% block title %}部落格首頁{% endblock %}

{% block content %}

    <div class="container">
        <div class="row">
            <div class="col-md-9">
                {% for entry in entries %}
                    <h2><a href="{{ entry.get_absolute_url }}">{{ entry.title }}</a></h2> <br>
                    {% if entry.img %}
                        <