django搭建web网站

首先我们聊一下django的前世今生,据说03年的时候下面这几家公司开始使用python构建网站,
Lawrence Journal-World newspaper
Adrian Holovaty
Simon Willison
这几家公司的工作性质都有一个共同的特点就是每天需要不停的处理各类新闻事务、作品,话说当时编辑部门提出的需求变化之快让技术部门毫无招架之力,所以django就在这年诞生了,django与其快速开发的特性,方便的model管理,MTV模型(model-template-view)成就了djano在python web领域的霸主地位,下面的演示将带大家一起领略django的神奇魅力。

步骤

1、环境准备,安装django3.0版本,mysql驱动
2、创建一个项目,并设置settings
3、初始化数据库,创建django超级用户用于后台model管理
4、创建一个app,在settings注册app,在models.py创建模型,并在admin.py注册model,生成迁移文件并同步到数据库
5、app下views创建视图层
6、app下创建urls路由配置文件,并为视图层配置跳转
7、app下创建templates/appName/结构目录,并在目录下创建视图层对应的html模板
8、效果展示
9、使用django view模板,简化代码量
10、static静态资源使用

1、安装django3.0版本,指定安装源为国内豆瓣源

pip install django==3.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install  -i http://pypi.douban.com/simple --trusted-host pypi.douban.com mysqlclient

django-admin startproject djangotest

2、settings.py设置

# 设置显示语言
from django.utils.translation import gettext_lazy as _
LANGUAGES = [
    ('zh-Hans', _('Chinese')),
]
LANGUAGE_CODE = 'zh-Hans'

# 设置时区
TIME_ZONE = 'Asia/Shanghai'

# 设置数据库,默认使用sqlite3,这里使用mysql
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

3、初始化数据库
3-1 在数据库执行下面命令创建django库

 create database django default charset utf8;

3-2 在项目下执行python manage.py migrate 同步django后台管理的相关表


image.png

image.png

3-3 创建超级用户用于django后台登陆,管理model

python manage.py createsuperuser
image.png

3-4 启动项目,访问http://127.0.0.1:8000,http://127.0.0.1:8000/admin

python manage.py runserver
image.png

image.png

image.png

image.png

4、创建一个app,在settings注册app,在models.py创建模型,并在admin.py注册model,生成迁移文件并同步到数据库

4-1 创建一个民意调查的app,需求,我们需要对网友关注的问题进行网络投票,一个问题对应多种答案,每个网民可以对其中的一个答案进行投票
python manage.py startapp polls

image.png

4-2 在settings.py INSTALLED_APPS增加polls app

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls.apps.PollsConfig',
]

4-3 models.py创建model模型

from django.db import models

# 继承Model,django会自动识别并在数据库创建该表
class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
    
    # 用于django后台显示该字段
    def __str__(self):
        return self.question_text

class Choice(models.Model):
    # 一对多关系,删除question时,对应的choice也会删除
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

    def __str__(self):
        return self.choice_text

4-4 admin.py注册 model

from django.contrib import admin
from .models import Question, Choice
admin.site.register(Question)
admin.site.register(Choice)

4-5 生成迁移文件,并同步到数据库

python manage.py makemigrations
python manage.py migrate

image.png

image.png

4-6 后台可以看到已更新刚注册的model


image.png

4-7 增加几个quesiton,并对question设置几个选项


image.png

image.png

image.png

image.png

image.png

5、polls/views.py创建视图层

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from .models import Question, Choice
from django.urls import reverse

# 获取最近相关的5个问题
def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request, 'polls/index.html', context)

# 投票页面
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

# 投票处理
def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        # POST请求的key需要与detail.html input name属性保持一致
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except(KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html',{
            'question':question,
            'error_message': "You didn't select a choice"
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

# 投票结果展示
def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question':question})

6、app下创建urls.py路由配置文件,并为视图层配置跳转

from django.urls import path
from . import views

# app命名空间,django一个项目包含n个app,使用命名可以可以对url进行分类
app_name = 'polls'
urlpatterns =  [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
    path('<int:question_id>/results/', views.results, name='results'),
]

项目路由配置

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

urlpatterns = [
    path('admin/', admin.site.urls),
    path('polls/', include('polls.urls')),
]
image.png

7、app下创建templates/appName/结构目录,并在目录下创建视图层对应的html模板,下面的是django模板的固定写法.

image.png

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if latest_question_list %}
    <ul>
        {% for question in latest_question_list %}
            <li> <a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a> </li>
        {% endfor %}
    </ul>
{% else %}
    <p> don't have resources </p>
{% endif %}
</body>
</html>

detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1> {{ question.question_text }} </h1>
{% if error_message %} <p> <strong> {{ error_message }} </strong> </p> {% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
    {% csrf_token %}
    <ul>
        {% for choice in question.choice_set.all %}
            <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
            <label for="choice{{ forloop.counter }}"> {{ choice.choice_text }} </label>
        {% endfor %}
    </ul>
    <input type="submit" value="Vote">
</form>

</body>
</html>

results.html

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

<ul>
    {% for choice in question.choice_set.all %}
        <li> {{ choice.choice_text }} -- {{ choice.votes }} </li>
    {% endfor %}
</ul>
<a href="{% url 'polls:vote' question.id %}"> Vote again? </a>
</body>
</html>

8、效果展示

index首页


image.png

投票页面


image.png

结果展示页面


image.png

9、django为单个model或model list集合提供了模板,对于上面的index,detail,results,都是查询model或model集合,下面对这些view进行简化

9-1 修改views.py, urls.py如下

views.py
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import get_object_or_404, render
from django.views import generic
from .models import Question, Choice

class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.order_by('-pub_date')[:5]

# django DetailView模板 默认返回的是<app name>/<model name>_detail.html,你甚至可以不指定template_name,
# 只要你按照相应的规则创建html
class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        # POST请求的key需要与detail.html input name属性保持一致
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except(KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html',{
            'question':question,
            'error_message': "You didn't select a choice"
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))


urls.py
from django.urls import path
from . import views

app_name = 'polls'

# 这里使用主键代替上面的question_id
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]


10、django给我们每一个app提供了静态资源的管理,创建<app name>/static/<app name>/style.css


image.png

index.html引用样式

{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342