Django 框架的核心组件有:
• 每个项目都需要安装很多库,当项目结束后这些库不需要了,该如何清理?
• 在同一个主系统内,需要同时安装django1.11.6和django2.0.5如何实现
• 有了python虚拟环境,这些问题将迎刃而解
使用虚拟环境
[root@localhost ~]# mkdir pyproject
[root@localhost ~]# cd pyproject/
[root@localhost pyproject]# python3 -m venv django_env
[root@localhost pyproject]# source django_env/bin/activate
(django_env)[root@localhost pyproject]#
安装django
(django_env)[root@localhost pyproject]# pip install django==1.11.6
(django_env)[root@localhost pyproject]# cat ~/.pip/pip.conf
[global]
index-url=http://pypi.douban.com/simple/
[install]
trusted-host=pypi.douban.com
验证django
(django_env)[root@localhost pyproject]# python
Python 3.6.4 (default, Apr 27 2018, 08:26:23)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.__version__
'1.11.6'
一般为了方便,可以直接使用pycharm安装,具体安装步骤,自行搜索
(django_env)[root@localhost pyproject]# django-admin startproject mysite
(django_env)[root@localhost pyproject]# tree mysite
mysite/ # 项目的根目录
├── manage.py # 项目的管理文件
├── mysite # 项目的配置目录
│ ├── __init__.py # 初始化文件
│ ├── settings.py # 配置文件
│ ├── urls.py # URLConf路由映射文件
│ └── wsgi.py # 部署服务器时使用
└── templates # 模板网页的目录
2 directories, 5 files
(django_env)[root@localhost mysite]# python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
You have 13 unapplied migration(s). Your project may not work properly
until you apply the migrations for app(s): admin, auth, contenttypes,
sessions.
Run 'python manage.py migrate' to apply them.
May 09, 2018 - 23:13:04
Django version 1.11.6, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
# mysite/settings.py
DEBUG = True # 生产环境应该改为False
ALLOWED_HOSTS = '*' # 允许所有的客户端访问
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
(django_env) [root@localhost mysite]# python manage.py runserver 0:80
# 0:80 -> 0.0.0.0:80
http://127.0.0.1/admin
django后台可以使用各种类型的数据库,默认用的是sqlite数据库,不做任何修改,这个数据库直接可以用。
配置django使用mysql数据库:
[root@localhost mysite]# mysql -uroot -p'123456'
mysql> CREATE DATABASE djtest DEFAULT CHARSET utf8;
# 修改配置文件连接数据库的声明
# mysite/settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djtest',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
# 初始化pymysql
# mysite/__init__.py
import pymysql
pymysql.install_as_MySQLdb()
# 生成数据库的表。jdango默认已经集成了很多应用,如用户管理的应用,这些内建的应用也需要把数据保存到数据库。
(django_env) [root@localhost mysite]# python manage.py makemigrations
(django_env) [root@localhost mysite]# python manage.py migrate
mysql> use djtest;
mysql> show tables; # 查看生成的表
(django_env) [root@localhost mysite]# python manage.py createsuperuser
Username (leave blank to use 'root'): admin
Email address: [email protected]
Password:
Password (again):
Superuser created successfully.
firefox 127.0.0.1/admin
(django_env)[root@localhost mysite]# python manage.py startapp polls
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls',
]
from django.conf.urls import url,include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
#导入polls目录(术语称作为包)中的urls模块
url(r'^polls/', include('polls.urls'))
]
vim polls/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
]
r'^hello'
:匹配以hello开头的任意URL,如:/helloabc
r'^hello/$'
:匹配hello且后面无信息的URL,如:/hello,/hello/
r'^$'
:匹配 / 即空URL,通常用来设定应用的根,即默认入口。如: http://IP:port
或者http://IP:port/
from django.http import HttpResponse
#用户发给django的请求,函数必须提供一个参数进行接收
def index(request):
return HttpResponse(“Hi! 这是polls应用的首页。")
(django_env) [root@localhost mysite]# python manage.py runseer 0:80
(django_env) [root@localhost mysite]# firefox 127.0.0.1/polls
# 修改函数的返回值,使用render函数返回模板文件
# polls/views.py
def index(request):
return render(request, 'index.html')
# 创建模板文件
# 模板文件的位置:
# 项目目录下的templates目录
# 应用目录下的templates目录
# templates/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>投票首页</title>
</head>
<body>
<h1>投票首页</h1>
</body>
</html>
刷新页面查看内容
# polls/urls.py
... ...
url(r'^\d+/$', views.detail, name='detail'),
... ...
# polls/views.py # 追加
def detail(request):
return render(request, 'detail.html')
# templates/detail.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>投票详情页title>
head>
<body>
<h1>投票详情页h1>
body>
html>
#polls/urls.py
url(r'^(\d+)/$', views.detail, name='detail'),
#polls/views.py
def detail(request, question_id):
return render(request, 'detail.html', {'question_id': question_id})
#templates/detail.html
<body>
<h1>{{ question_id }}号问题投票详情页h1>
body>
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question,on_delete = models.CASCADE)
choice_text = models.CharField(max_length = 200)
votes = models.IntegerField(default = 0)
(django_env)[root@localhost mysite]# python manage.py makemigrations
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Choice
- Create model Question
- Add field question to choice
(django_env) [root@localhost mysite]# python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying polls.0001_initial... OK
登录数据库,查看创建的表
from django.contrib import admin
from .models import Question,Choice
admin.site.register(Question)
admin.site.register(Choice)
(django_env) [root@localhost mysite]# python manage.py shell
>>> from polls.models import Question,Choice
>>> Question.objects.all()
<QuerySet []>
>>> from django.utils import timezone
>>> q = Question(question_text="你希望进入哪个公司工作?",pub_date=timezone.now())
>>> q.save()
>>> q.id
1
>>> q.question_text
'你希望进入哪个公司工作?'
>>> q.pub_date
datetime.datetime(2018, 5, 18, 14, 50, 11, 282269, tzinfo=<UTC>)
>>> q.question_text = "你期待哪个公司给你发offer?"
>>> q.save()
>>> Question.objects.all()
<QuerySet [<Question:Question object>]>
提供友好实例名称
• 完全是这个对象无意义的表示。
接下来修复这个问题:
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
class Choice(models.Model):
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
(django_env) [root@localhost mysite]# python manage.py shell
>>> from polls.models import Question,Choice
>>> Question.objects.all()
<QuerySet [<Question:你期待哪个公司给你发offer?>]>
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
>>> from polls.models import Question, Choice
>>> Question.objects.get(id=1)
<Question: 你期待哪个公司给你发offer?>
>>> Question.objects.get(id=2)
......
polls.models.DoesNotExist: Question matching query does not exist.
>>> Question.objects.get(pk=1)
<Question: 你期待哪个公司给你发offer?>
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
>>> Question.objects.get(id=1)
<Question: 你期待的工资是多少?>
>>> Question.objects.filter(id=1)
<QuerySet [<Question: 你期待的工资是多少?>]>
>>> q1 = Question.objects.get(id=1)
>>> q1.question_text
'你期待的工资是多少?'
>>> q1.pub_date
datetime.datetime(2019, 7, 23, 9, 32)
>>> qset1 = Question.objects.filter(id=1)
>>> len(qset1)
1
>>> q2 = qset1[0] # 取出下标为0的实例
>>> q2.question_text
'你期待的工资是多少?'
>>> Question.objects.filter(id=1)
<QuerySet [<Question: 你期待哪个公司给你发offer?>]>
>>> Question.objects.filter(question_text__startswith='你')
<QuerySet [<Question: 你期待哪个公司给你发offer?>]>
>>> Question.objects.filter(id__exact=1)
<QuerySet [<Question: 你期待的薪资是多少?>]>
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: 你期待哪个公司给你发offer?>
# 取出全部数据
>>> Question.objects.all() # 返回查询集
>>> Question.objects.order_by('pub_date') # 按pub_date升序排列
>>> Question.objects.order_by('-pub_date') # 按pub_date降序排列
# 先过滤,再排序
>>> Question.objects.filter(id__gt=2).order_by('-pub_date')
# 在过滤的结果集上继续进行过滤
>>> Question.objects.filter(id__gt=2).filter(id__lt=4)
修改和删除
# 修改前先获取到实例
>>> q1 = Question.objects.get(id=3)
>>> q1
<Question: 住址在哪?>
# 修改就是属性重新赋值
>>> q1.question_text = ' 住址在哪?'
>>> q1.save()
# 删除
>>> q2 = Question.objects.get(question_text__contains='哪个城市找工作')
>>> print(q2)
你打算到哪个城市找工作?
>>> q2.delete() # delete后,数据库中已经删除对应的记录
>>> print(q2) # 仍然存在q2实例,只不过数据库中没有记录与之对应
>>> q2.save() # 再次保存,在表中创建新的记录
>>> from polls.models import Question,Choice
>>> q3 = Question.objects.create(question_text='你打算去哪个城
# 实例化
>>> c1 = Choice(choice_text='北京', question=q3)
>>> c1.save()
# 通过objects管理器
>>> c2 = Choice.objects.create(choice_text='上海', question=q3)
# 因为问题和选项存在着一对多的关系,也就是一个问题可以对应多个选项。因为选项类名字是Choice,所以问题实例都有一个choice_set。如果选项类名字是XuanXiang,那么问题实例就有一个xuanxiang_set。choice_set也是一个管理器,它也有和objects一样的方法。
>>> c3 = q3.choice_set.create(choice_text='广州')
def detail(request, question_id):
return HttpResponse("你正在查看的问题是:%s。" % question_id)
def result(request, question_id):
response = "你正在查看问题[%s]的结果。"
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("您正在为[%s]投票。")
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
url(r'^(?P[0-9]+)/$' , views.detail, name='detail'),
url(r'^(?P[0-9]+)/results/$' , views.result, name='result'),
url(r'^(?P[0-9]+)/vote/$' , views.vote, name='vote'),
]
为了解决硬码的这些问题,可以模板:
[root@localhost mysite]# mkdir -p polls/templates/polls
from django.shortcuts import render
from .models import Question
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)
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}a>
li>
{% endfor %}
ul>
{% else %}
<p>No polls are available.p>
{% endif %}
当模板系统遇到变量名里有小数点时会按以下顺序查找:
模板中可以使用的元素有:
from django.shortcuts import render,get_object_or_404
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
<h1>{{ question.question_text }}h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}li>
{% endfor %}
ul>
<h1>{{ question.question_text }}h1>
{% if error_message %}
<p><strong>{{ error_message }}strong>p>
{% endif %}
<form action="/polls/{{ question.id }}/vote/" method="post">
{% csrf_token %}
{% 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><br />
{% endfor %}
<input type="submit" value="投票" />
form>
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
choices = question.choice_set.get(pk=request.POST['choice'])
except(KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'qustion': question,
'error_message': '您没有做出任何选择',
})
else:
choices.votes += 1
choices.save()
return redirect('result', question_id=question_id)
def result(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request,'polls/results.html', {'question':question})
<h1>{{ question.question_text }}h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} : {{ choice.votes }}li>
{% endfor %}
ul>
<a href="/polls/">投票首页a>
======================内容补充
https://docs.djangoproject.com/en/1.11/ref/templates/language/
# 变量通过{{var}}来表示
# for 循环,变量在标签中不需要使用{{}}
<ul>
{% for athlete in athlete_list %}
<li>{{ athlete.name }}li>
{% endfor %}
ul>
# 判断
{% if athlete_list %}
Number of athletes: {{ athlete_list|length }}
{% elif athlete_in_locker_room_list %}
Athletes should be out of the locker room soon!
{% else %}
No athletes.
{% endif %}
# 把day02的static目录拷贝到应用目录下
(django_env) [root@room8pc16 mysite]# ls -d polls/static/
polls/static
# 静态文件目录,通过settings.py的STATICFILES_DIRS设置
# 项目目录的static目录
# 应用目录的static目录
# 修改index.html,第一行加入以下内容:
{% load static %}
# 在index.html的head标签中,加入以下内容:
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>投票首页title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
head>
<body>
<div class="container">
<div id="linux-carousel" class="carousel slide">
<ol class="carousel-indicators">
<li class="active" data-target="#linux-carousel" data-slide-to="0">li>
<li data-target="#linux-carousel" data-slide-to="1">li>
<li data-target="#linux-carousel" data-slide-to="2">li>
ol>
<div class="carousel-inner">
<div class="item active">
<a href="http://www.sogou.com" target="_blank">
<img src="{% static 'imgs/first.jpg' %}">
a>
div>
<div class="item">
<img src="{% static 'imgs/second.jpg' %}">
div>
<div class="item">
<img src="{% static 'imgs/third.jpg' %}">
div>
div>
<a href="#linux-carousel" data-slide="prev" class="carousel-control left">
<span class="glyphicon glyphicon-chevron-left">span>
a>
<a href="#linux-carousel" data-slide="next" class="carousel-control right">
<span class="glyphicon glyphicon-chevron-right">span>
a>
div>
<div class="row h4">
<div class="col-sm-12">
<h1 class="text-center text-warning">投票首页h1>
{#<div>{{ questions }}div>#}
<ol>
{% for question in questions %}
<li>
{# detail是urls.py中为详情页起的名字,它接受一个参数#}
<a href="{% url 'detail' question.id %}" target="_blank">
{{ question.question_text }}
a>
{{ question.pub_date }}
li>
{% endfor %}
ol>
div>
div>
<div class="row text-center h4">
<div class="col-sm-12">
<a href="#">TESTa>
div>
div>
div>
<script src="{% static 'js/jquery.min.js' %}">script>
<script src="{% static 'js/bootstrap.min.js' %}">script>
<script type="text/javascript">
$('#linux-carousel').carousel({
interval : 3000
});
script>
body>
html>
制作网页时,多个页面呈现的形式是一样的,可以先创建一个基础模板,把共性内容写到基础模板中。具体的模板文件都继承于基础模板,把个性化内容写到模板文件。
# templates/base.html 保留各个页面的共性部分,个性部分用block标签代替
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
head>
<body>
<div class="container">
<div id="linux-carousel" class="carousel slide">
<ol class="carousel-indicators">
<li class="active" data-target="#linux-carousel" data-slide-to="0">li>
<li data-target="#linux-carousel" data-slide-to="1">li>
<li data-target="#linux-carousel" data-slide-to="2">li>
ol>
<div class="carousel-inner">
<div class="item active">
<a href="http://www.sogou.com" target="_blank">
<img src="{% static 'imgs/first.jpg' %}">
a>
div>
<div class="item">
<img src="{% static 'imgs/second.jpg' %}">
div>
<div class="item">
<img src="{% static 'imgs/third.jpg' %}">
div>
div>
<a href="#linux-carousel" data-slide="prev" class="carousel-control left">
<span class="glyphicon glyphicon-chevron-left">span>
a>
<a href="#linux-carousel" data-slide="next" class="carousel-control right">
<span class="glyphicon glyphicon-chevron-right">span>
a>
div>
<div class="row h4">
<div class="col-sm-12">
{% block content %}{% endblock %}
div>
div>
<div class="row text-center h4">
<div class="col-sm-12">
<a href="#">TEST02a>
div>
div>
div>
<script src="{% static 'js/jquery.min.js' %}">script>
<script src="{% static 'js/bootstrap.min.js' %}">script>
<script type="text/javascript">
$('#linux-carousel').carousel({
interval : 3000
});
script>
body>
html>
# 将index.html中共性部分删除,个性部分写到对应的block中
# index.html
{% extends 'base.html' %}
{% load static %}
{% block title %}投票首页{% endblock %}
{% block content %}
<h1 class="text-center text-warning">投票首页h1>
<ol>
{% for question in questions %}
<li>
<a href="{% url 'detail' question.id %}" target="_blank">
{{ question.question_text }}
a>
{{ question.pub_date }}
li>
{% endfor %}
ol>
{% endblock %}
# detail.html
{% extends 'base.html' %}
{% load static %}
{% block title %}投票详情页{% endblock %}
{% block content %}
<h1>{{ question_id }}号问题投票详情页h1>
{% endblock %}
详情视图,只要把对应ID的问题取出即可
# polls/views.py
def detail(request, question_id):
question = Question.objects.get(id=question_id)
return render(request, 'detail.html', {'question': question})
# templates/detail.html
{% extends 'base.html' %}
{% load static %}
{% block title %}投票详情页{% endblock %}
{% block content %}
<h1 class="text-center text-warning">{{ question.id }}号问题投票详情页h1>
<h2>{{ question.question_text }}h2>
<form action="" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<div class="radio">
<label>
<input type="radio" name="choice_id" value="{{ choice.id }}">
{{ choice.choice_text }}
label>
div>
{% endfor %}
<div class="form-group">
<input class="btn btn-primary" type="submit" value="提 交">
div>
form>
{% endblock %}
在投票详情页,当用户提交表单时,将会把数据post给action对应的URL。
为选项投票就是把选项的票数votes加1,通过函数实现投票功能。在django里,访问一个url就会执行函数。
# polls/urls.py
url(r'^(\d+)/vote/$', views.vote, name='vote'),
def vote(request, question_id):
question = Question.objects.get(id=question_id)
choice_id = request.POST.get('choice_id') # 从用户post的表单中取出choice_id
choice = question.choice_set.get(id=choice_id) # 获取选项实例
choice.votes += 1
choice.save()
return redirect('result', question_id) # 重定向到result页面
<form action="{% url 'vote' question.id %}" method="post">
# polls/views.py
def result(request, question_id):
question = Question.objects.get(id=question_id)
return render(request, 'result.html', {'question': question})
{% extends 'base.html' %}
{% load static %}
{% block title %}投票结果页{% endblock %}danei
{% block content %}
<h1 class="text-center text-warning">{{ question.id }}号问题投票结果页h1>
<h2>{{ question.question_text }}h2>
<table class="table table-bordered table-hover table-striped">
<thead class="bg-primary text-center">
<tr>
<td>选项td>
<td>票数td>
tr>
thead>
<tbody>
{% for choice in question.choice_set.all %}
<tr>
<td>{{ choice.choice_text }}td>
<td>{{ choice.votes }}td>
tr>
{% endfor %}
tbody>
table>
{% endblock %}
附:
前台页面模板:https://coreui.io/
django2 by example: http://www.conyli.cc/django-2-by-example