Django (D不发音)学习入门
如果在一台计算机下,想开发多个不同的项目,需要用到同一个包的不同版本,如果还使用命令在同一个目录下安装或者更新,可能影响到其它项目,或新项目用到的包的版本与当前版本有冲突,这样会导致其它项目无法运行,因此,要使用虚拟环境,在不同的虚拟环境下,制作不同的项目,彼此互不干涉;
Django 只在虚拟环境激活的情况下才能使用;
一、首先是 安装虚拟环境包:
DOS终端下输入 pip install --user virtualenv
linux 下 sudo apt-get install python-virtualenv
二、安装完虚拟环境后,建立虚拟环境:(虚拟环境名称 ll_env)
virtualenv ll_env
三、启动虚拟环境
Windows 下,ll_env\Scripts\activate
四、在虚拟环境中安装Django
pip install Django==2.11
五、创建项目
django-admin.py startproject learning_log (空格). (结尾的点很重要)
建立了名为 learning_log 的项目;
六、数据库迁移(创建数据库)
python manage.py migrate (这里默认使用的是SQLite 数据库)
七、查看项目
python manage.py runserver
启动服务器
在电脑web网页输入
http:// localhost:8000/ #查看页面
18-1 课后习题
在dos 环境下输入 mkdir InstaBook #创建文件夹
然后再输入 pip install --user virtualenv #安装虚拟环境包
输入 virtualenv env #创建虚拟环境,名称为env
输入 env\Scripts\activate #激活虚拟环境
输入 pip install django==2.2 #安装django版本指定2.2
输入 django-admin.py startproject instabook . #建立项目instabook(这里不要忘记在 ‘.’ 前面有个空格,PS:这块其实挺坑)
(若出现系统让升级Pip 版本,请输入 pip install --upgrade pip==20.2.2)
若pip 升级失效并丢失,在dos环境下进入虚拟环境目录,然后输入:
easy_install.exe pip
18.2 创建程序
python manage.py startapp learning_logs #创建应用程序 learning_logs
也有用下一个命令创建app的:
django-admin.py startapp learning_logs
以上两个命令都可以。
定义模型
在models.py这个文件中,定义一个类 Topic,代码如下:
from django.db import models #导入模块Models
class Topic(models.Model): #Topic是你的学习笔记的主题,这里以类的形式进行定义
"""A topic the user is learning about."""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
"""Return a string representation of the model."""
return self.text
这里面我们需要详细说明一下,以方便我们理解:
Model是你数据信息的唯一,确定的来源。它包含了基础字段(fields)和存储数据时的行为。总的来说,每一个Model都匹配一个数据表。
- 每一个Model都是一个继承于
django.db.models.Model
的class - Model的每一个属性都代表着数据表中的一个字段
- Django提供了一个自动生成的数据库访问的API,参见
Making queries
.
这里定义了一个类Topic,它继承了Model,而text与data_added 都是Topic的属性,因此可以理解为,其也是Model的属性;
这里text 是一个Charfield-由字符或文本组成的数据,它是model中的一个字段,需要存储少量文本,因此,必须在数据库中定义它的长度;
date_add是一个记录时间和日期的数据,实参auto_now_add=True ,表示每当用户创建新主题时,Django将自动将该日期作为当前日期和时间进行记录;
__str__函数主要作用就是告诉Django应该显示有关主题的信息。这里返回存储在属性text里面的信息。
这里面要引申一下Field的用法;
字段是模型当中最重要的部分,是数据库列表定义的模型唯一需要的部分;字段有类的属性进行定义,主要在命名字段的时候不要与模型API 接口名称相同,避免产生歧义;
Fieds的主要用法如下:
首先引入model模型,即:from django.db import models
字段(fields)
1、models.AutoField 自增列 = int(11)
如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=True。
2、models.CharField 字符串字段
必须 max_length 参数, 即 models.CharField(max_length=200)
3、models.BooleanField 布尔类型=tinyint(1) ;不能为空,Blank=True
4、models.ComaSeparatedIntegerField 用逗号分割的数字=varchar;继承CharField,所以必须 max_lenght 参数
5、models.DateField 日期类型 date,对于参数,auto_now = True 则每次更新都会更新这个时间;auto_now_add 则只是第一次创建添加,之后的更新不再改变。
6、models.DateTimeField 日期类型 datetime
同DateField的参数
7、models.Decimal 十进制小数类型 = decimal
必须指定整数位max_digits和小数位decimal_places
8、models.EmailField 字符串类型(正则表达式邮箱) =varchar
对字符串进行正则表达式
9、models.FloatField 浮点类型 = double
10、models.IntegerField 整形
11、models.BigIntegerField 长整形
integer_field_ranges = {
'SmallIntegerField': (-32768, 32767),
'IntegerField': (-2147483648, 2147483647),
'BigIntegerField': (-9223372036854775808, 9223372036854775807),
'PositiveSmallIntegerField': (0, 32767),
'PositiveIntegerField': (0, 2147483647),
}
12、models.IPAddressField 字符串类型(ip4正则表达式)
13、models.GenericIPAddressField 字符串类型(ip4和ip6是可选的)
参数protocol可以是:both、ipv4、ipv6
验证时,会根据设置报错
14、models.NullBooleanField 允许为空的布尔类型
15、models.PositiveIntegerFiel 正Integer
16、models.PositiveSmallIntegerField 正smallInteger
17、models.SlugField 减号、下划线、字母、数字
18、models.SmallIntegerField 数字
数据库中的字段有:tinyint、smallint、int、bigint
19、models.TextField 字符串=longtext
20、models.TimeField 时间 HH:MM[:ss[.uuuuuu]]
21、models.URLField 字符串,地址正则表达式
22、models.BinaryField 二进制
23、models.ImageField 图片
24、models.FilePathField 文件
参数
1、null=True
数据库中字段是否可以为空
2、blank=True
django的 Admin 中添加数据时是否可允许空值
3、primary_key = False
主键,对AutoField设置主键后,就会代替原来的自增 id 列
4、auto_now 和 auto_now_add
auto_now 自动创建---无论添加或修改,都是当前操作的时间
auto_now_add 自动创建---永远是创建时的时间
5、choices
sex_choice=((“F”,“FEMAL”),(“M”,’Male’),) #admin专用下拉选项
gender=models.CharFiled(max_length=2,choice=sex_choice)
6、max_length
7、default 默认值
8、verbose_name Admin中字段的显示名称
9、name|db_column 数据库中的字段名称
10、unique=True 不允许重复
11、db_index = True 数据库索引
12、editable=True 在Admin里是否可编辑
13、error_messages=None 错误提示
14、auto_created=False 自动创建
15、help_text 在Admin中提示帮助信息
16、validators=[]
17、upload-to
因为我们已经建立的应用,因此,必须在项目中将该应用进行添加,这里打开settings.py文件,在INSTALLED_APPS中添加该app的名字;
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# My apps
'learning_logs',
)
可以看出,INSTALLED_APPS是一个元组,这里面有很多的元素,料想其余元素若为app的话,应该是建立项目的时候自动生成的,这里我们不去管它;
因为我们已经建立了新的app应用,因此要为他迁移数据库,形成数据列表,这里需要在dos环境下,输入:
python manage.py makemigrations learning_logs # 创建更改文件,可以看见这时生成了迁移文件00001_initial.py,这个文件将在数据库中为模型Topic创建一个表;
python manage.py migrate #迁移刚才生成的表,将刚才生成.py文件应用到数据库;
每当我们要修改数据时,首先修改models.py , 然后调用makemigrations,形成迁移文件,最后,执行迁移动作,migrate!
18.2.3 Django管理网站;
创建超级用户:
python manage.py createsuperuser
这里有一种特殊情况,如果你忘记了之前创建的超级用户名或密码怎么办?
首先,在虚拟环境中进入shell模式,python manage.py shell
然后输入以下代码,对原有密码重置:
from django.contrib.auth.models import User # 引入管理员密码存放的数据库;
user=User.objects.filter() #查找该数据库存有哪些用户
user #查看有哪些用户
重置密码
user = User.objects.get(username='admin') #获取名称为admin的用户
user.set_password('123456') #设置新密码为123456
user.save() #保存user对象,完事儿了!
我们创建的模型必须手工注册,找到admin.py 文件,输入下列代码:
from django.contrib import admin
from learning_logs.models import Topic, Entry
admin.site.register(Topic)
注册了Topic模型!
18.2.4 定义模型Entry
这里定义一个Entry类,让Topic主题下包含多个条目,使之具备内容;
from django.db import models
class Topic(models.Model):
--------snip-----------
class Entry(models.Model):
"""Something specific learned about a topic."""
topic = models.ForeignKey(Topic)
text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'entries'
def __str__(self):
"""Return a string representation of the model."""
return self.text[:50] + "..."
topic是一个外键(foreign Key)实例,这里面涉及到数据了,外键引用数据库的一条记录;
Meta 类的具体用法,请参考一下链接:
https://www.cnblogs.com/jasonhaven/p/7497322.html
verbose_name_plural='entries' 这个是指定模型的复数形式是什么,其实就是给你的模型起个名字,这个名字可以是中文,不过表达的是复数;
这里不要忘记,在定义完模型之后,要在数据库中给它分配一个位置,用来存储信息,这就要我们迁移数据库;
dos下输入 : python manage.py makemigrations learning_logs
python manage.py migrate
迁移数据库以后,要进行网站注册
from django.contrib import admin
from learning_logs.models import Topic, Entry
admin.site.register(Topic)
admin.site.register(Entry)
18.2.7 Django shell 的使用实例
这里不再赘述,直接把代码上了吧:
python manage.py shell # 启动shell
from learning_logs.models import Topic # 导入models模型,引入Topic类
Topic.objects.all() # 获取模型Topic中的所有实例
topics = Topic.objects.all() # 将所有实例导入到topics中,此时它是一个元组
for topic in topics: #例遍所有元素
print(topic.id, topic) # 打印元素的id, 和元素内容
t = Topic.objects.get(id=1)
t.text
t.date_added
t.entry_set.all()
课后习题:
18-2
def __str__(self):
"""Return a string representation of the model."""
if len(self.text)>50:
return self.text[:50] + "..."
else:
return self.text
18-4 创建名为pizzeria的项目:
DOS下: python manage.py startproject pizzeria . # 一定不要忘了空格后面的点哦!
创建应用:
django-admin.py startapp pizzas #创建app,名称为pizzas
还是在models.py 里面,定义Pizza模型,代码如下:
from django.db import models
# Create your models here.
class Pizza(models.Model):
name=models.CharField(max_length=200)
data_added=models.DateTimeField(auto_now_add=True)
def __str__(self):
# """返回木星字符串表示"""
return self.name
class Topping(models.Model):
pizza=models.ForeignKey(Pizza,on_delete=models.CASCADE)
name=models.TextField()
date_add=models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural='entries'
def __str__(self):
return self.name[:50]+'...'
18.3创建网页:学习笔记主页
创建网页三步骤:一、定义URL(链接);二、编写视图(view);三、编写模板(templates)
打开learning_log主文件夹下的urls.py ,输入以下代码:(书中代码是基于django1.0的,2.0版本往上请输入以下代码:)
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
urlpatterns = [
path('admin/', admin.site.urls),# 这个是课程后面代码,定义的管理员页面链接
path('',include('learning_logs.urls',namespace='learning_logs')), #这里面有个include,从中我们可以看出,需要在learning_logs文件夹中新建一个urls.py文件,来与learning_log文件夹下的urls相呼应;
path('users/',include('users.urls',namespace='users')),# 这个也是后面课程代码,定义使用者页面链接
]
app_name = 'learning_logs'
在learning_logs文件夹下新建一个urls.py文件,代码如下:(书中代码还是老版本的)
from django.urls import path,include
from . import views
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'), #显示所有主题页
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'), #特定主题的详细页面
# 用于添加新主题网页
path("new_topic/",views.new_topic,name='new_topic'),
# 用于添加新条目
path("new_entry/(?p<topic_id>\d+)/", views.new_entry,name='new_entry'),
# 编辑条目
path("edit_entry/(?p<entry_id>\d+))",views.edit_entry, name='edit_entry'),
]
由上面的代码,我们可以看到,里面应用了正则表达式,正则表达式是几乎所有语言都会用到的,大家后续找资料好好学习吧!
简单举一个例子说一下吧:
path('',views.index, name='index') #主页下的网页,path 后面什么也没有,就表示主页,views.index 是指要调用的视图函数,由此可知,需要在views.py 内建立index函数,以供调用!name='index' 是将这个URL的名称命名为index,每当要调用这个页面的时候,我们直接提供这个名称就可以了,不用提供URL地址!
URL定义完了,现在我们要开始定义视图函数了views.py
打开views.py文件,输入以下代码:
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request,'learning_logs/index.html')
解释一下 render(request,'learning_logs/index.html')
首先是render()的使用:
render(request, template_name, context=None, content_type=None, status=None, using=None)
Returns a HttpResponse whose content is filled with the result of calling django.template.loader.render_to_string() with the passed
request: 收到的请求
template_name: templates 中网页模板. 比如’templates\learn\index.html’, 参数就要写‘learn\index.html’
context: 要传入文件中用于渲染呈现的数据, 默认是字典格式
content_type: 生成的文档要使用的MIME 类型。默认为DEFAULT_CONTENT_TYPE 设置的值。
status: http的响应代码,默认是200.
using: 用于加载模板使用的模板引擎的名称。
常见的MIME类型(通用型):
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar
任意的二进制数据 application/octet-stream
由以上可知,render就是URL匹配后,响应网页请求而做的反应,这里顾名思义,request就是请求,然后,反馈这个‘learning_logs/index.html’ 模板;
此时,我们要定义Index.html了,对于html 我们又要仔细学习了:
HTML称为超文本标记语言,是一种标识性的语言。
HTML基础,可以参考以下链接:
https://www.runoob.com/html/html-tutorial.html
下面编辑index.html模板,输入以下代码:
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
标签<p>代表段落,这里需要补一下基础HTML
课后习题18-5
在dos 环境下输入 mkdir meal_planner
进入该文件夹,输入 django-admin.py startproject food
进入meal_planner文件夹,然后输入 django-admin.py startapp meal_plans
首先在setting.py 文件中,输入app的名字,代码如下:
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = ')kt84#hb3cgv5)=h&ln!&pyg^szfh3#9jt+-hv@j3(_zg20pe3'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'meal_plans',
]
然后在models.py 文件中,输入以下代码:
from django.db import models
class food(models.Model):
name=models.CharField(max_length=200)
date_added=models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.text
在vies.py 文件中输入以下代码:
from django.shortcuts import render
def index(request):
return render(request,'index.html')
在所建项目的urls.py 文件中,输入以下代码:(我建的项目是food)
from django.contrib import admin
from django.urls import path
from meal_plans import views
app_name='meal_plans'
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index,name='index'),
]
最后,进行注册,在admin.py中输入:
from django.contrib import admin
from meal_plans.models import food
admin.site.register(food)
这里忘记添加模板了,在meal_plans文件夹下简历模板文件夹templates,然后在该文件夹下建立index.html 文件,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>food</title>
</head>
<body>
<p> Welcome to my resturant</p>
</body>
</html>
18.4 创建其它网页
18.4.1 模板继承,这里没啥可说的,base.html直接贴代码:
<p>
<a href="{% url 'learning_logs:index' %}">Learning Log</a> -
<a href="{% url 'learning_logs:topics' %}">Topics</a>
</p>
{% block content %}{% endblock %}
这里面基础也是html,将index及topics的链接贴里面,然后显示是Learning Log 和 Topics,这个代码里面体现了django的优越性,他直接找到了index的名称,这里边与url.py 中代码:path('',views.index,name='index'), 这里边name直接命名了!
上面母模板定义完了,该定义子模板了,index.html代码改为:
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Learning Log helps you keep track of your learning, for any topic you're
learning about.</p>
{% endblock content %}
learning_logs/urls.py 代码:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
]
vies.py 代码
from django.shortcuts import render
from .models import Topic
def index(request):
"""The home page for Learning Log."""
return render(request, 'learning_logs/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
topics.html代码
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}
learning_logs/urls.py代码:
from django.urls import path,include
from . import views
# from django.conf.urls import url
app_name = 'learning_logs'
urlpatterns =[#主页
path('',views.index, name='index'),
#显示所有主题
path('topics/',views.topics,name='topics'),
#特定主题的详细页面
path("topics/(?p<topic_id>\d+)/",views.topic, name='topic'),]
views.py代码:
from django.shortcuts import render
from .models import Topic
def index(request):
"""The home page for Learning Log."""
return render(request, 'learning_logs/index.html')
def topics(request):
"""Show all topics."""
topics = Topic.objects.order_by('date_added')
context = {'topics': topics}
return render(request, 'learning_logs/topics.html', context)
def topic(request, topic_id):
"""Show a single topic, and all its entries."""
topic = Topic.objects.get(id=topic_id)
entries = topic.entry_set.order_by('-date_added')
context = {'topic': topic, 'entries': entries}
return render(request, 'learning_logs/topic.html', context)
这段代码定义的topic段涉及到数据库知识了,补基础请参考以下链接:
http://www.manongjc.com/sqlite/sqlite_syntax.html
所以大家看到了,一个django带大家入了好多坑,截止目前,涉及到前端的有html,JavaScript,涉及到后端的sqlite, mysql。继续挑战!
模板topics.html
{% extends "learning_logs/base.html" %}
{% block content %}
<p>Topics</p>
<ul>
{% for topic in topics %}
<li>
<a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
</li>
{% empty %}
<li>No topics have been added yet.</li>
{% endfor %}
</ul>
{% endblock content %}