1. 准备
首先下载安装django
pip3 install django
pycharm可以直接建立django的项目,也可以执行命令
django-admin startproject mysite
这样就建立了一个mysite的django项目。
下面是新建项目的目录文件列表
mysite/
manage.py
mysite/
__init__.py
settings.py
urls.py
wsgi.py
其中,
settings.py是项目各种配置的文件
urls.py是url目录文件
manage.py是管理工具
尝试运行(pycharm可以直接点击Django项目运行)
也可以shell运行命令
python manage.py runserver
运行成功后的输出
Performing system checks...
System check identified no issues (0 silenced).
You have unapplied migrations; your app may not work properly until they are applied.
Run 'python manage.py migrate' to apply them.
六月 01, 2018 - 15:50:53
Django version 2.0, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
2.创建一个应用
python manage.py startapp polls
创建完成后会在mysite目录下看到一个polls文件目录
polls/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
应用创建完成了不过,等下模型的学习中还要使用
3.视图
现在创建我们的第一个视图应用
from django.http import HttpResponse,request
# Create your views here.
def hello(request):
html = '<html><body>hello world</body></heml>'
return HttpResponse(html)
同时配置我们的polls/urls.py
添加:
path("",views.hello,name='index')
完成后是这个样子:
from django.urls import path,include
from . import views
urlpatterns =[
#首页设置
path("",views.hello,name='index'),
]
这仅仅是polls下的配置,mysite还无法知道这是什么意思,所以我们还要配置mysite/urls.py
打开mysite/urls.py后里面已经有内容了,在其中添加
path('polls/',include('polls.urls')),
配置好以后的样子
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/',include('polls.urls')),
]
然后就可以打开浏览器输入链接:
http://127.0.0.1:8000/polls/
这里面用到了include
在官方文档中是这样写的:
函数 include() 允许引用其它 URLconfs。每当 Django 遇到 :func:~django.urls.include
时,它会截断与此项匹配的 URL 的部分,并将剩余的字符串发送到 URLconf 以供进一步处理。 我们设计 include()
的理念是使其可以即插即用。因为投票应用有它自己的 URLconf( polls/urls.py ),他们能够被放在 “/polls/” ,
“/fun_polls/” ,”/content/polls/”,或者其他任何路径下,这个应用都能够正常工作。
接下来理解一下path:
def _path(route, view, kwargs=None, name=None, Pattern=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
pattern = Pattern(route, is_endpoint=False)
urlconf_module, app_name, namespace = view
return URLResolver(
pattern,
urlconf_module,
kwargs,
app_name=app_name,
namespace=namespace,
)
elif callable(view):
pattern = Pattern(route, name=name, is_endpoint=True)
return URLPattern(pattern, view, kwargs, name)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')
这是path的函数,我们可以看到传递进去的参数:
**route:**route 是一个匹配 URL 的准则(类似正则表达式)。当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。这些准则不会匹配 GET 和 POST 参数或域名。例如,URLconf 在处理请求 https://www.example.com/myapp/ 时,它会尝试匹配 myapp/ 。处理请求 https://www.example.com/myapp/?page=3 时,也只会尝试匹配 myapp/。
view:当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个 HttpRequest 对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入。
kwargs=None:任意个关键字参数可以作为一个字典传递给目标视图函数
name=None:为你的 URL 取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式。
Pattern=None:官方文档并没有给解释
其中,博主也只知道使用route和view,设置name之后怎么使用name博主也不知道,如果哪位大大翻了博主的牌,望告知
4.数据库配置
python默认使用的是SQLite,但是博主使用的是mysql,所以接下来都是mysql的配置,如果是其他数据库请看官方文档
在此之前,请确认:
1.安装好mysql数据库
2.已经下载好了mysqlclient(pip/pip3 install mysqlclient)
3.设置好时间在mysite/settings.py
TIME_ZONE = ‘Asia/Shanghai’
看到下面的内容, 我们打开mysite/settings.py
sqlite:’django.db.backends.sqlite3’
postgresql:’django.db.backends.postgresql’
mysql:’django.db.backends.mysql‘
oracle:’django.db.backends.oracle’
找到DATABASES这个设置,填写以下内容
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'polls',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
NAME: 数据库名字
USER:用户名
PASSWORD:用户密码
HOST:ip
PORT:端口
在创建自己的模型之前,我们先运行
python manage.py migrate
这是为为我们的admin应用创建数据库表格
接下来编写我们的模型:
打开polls/models.py,填写以下代码:
from django.db import models
# Create your models here.
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_data = 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.db.modles.Model的子类,每个模型都有一些变量, 这是表示模型里面的数据库的字段
每个字段我们都设置了一个类型, 比如CharField,DateTImeFIeld,用来告诉django处理数据的类型。其中我们定义了一个Field名字,在官方文档中, 他是这样解释的:
你可以使用可选的选项来为 Field 定义一个人类可读的名字。这个功能在很多 Django
内部组成部分中都被使用了,而且作为文档的一部分。如果某个字段没有提供此名称,Django
将会使用对机器友好的名称,也就是变量名。在上面的例子中,我们只为 Question.pub_date
定义了对人类友好的名字。对于模型内的其它字段,它们的机器友好名也会被作为人类友好名使用。
Field中有些参数,例如 max_length 这个浅显易懂,就是长度设置,当然也可以设置默认值,例如 :default = 0
最后我们定义了ForeignKey,这是一对一关系, 告诉我们每个choice都对应了一个question,后面的参数是:
models.CASCADE:对就对象删除后,包含ForeignKey的字段也会被删除
models.PROTECT:删除时会引起ProtectedError
models.SET_NULL:注意只有当当前字段设置null设置为True才有效,此情况会将ForeignKey字段设置为null
models.SET_DEFAULT :同样,当前字段设置了default才有效,此情况会将ForeignKey 字段设置为default 值
moels.SET:此时需要指定set的值
models.DO_NOTHING :什么也不做
写好模型之后我们要去激活我们的模型,在mysite/settings.py中找到这个INSTALLED_APPS
在里面添加
#因为PollsConfig类写在了polls/apps中
’polls.apps.PollsConfig‘
接着,我们运行以下命令:
#通过运行 makemigrations 命令,Django 会检测你对模型文件的修改(在这种情况下,你已经取得了新的),并且把修改的部分储存为一次 迁移。
python manage.py makemigrations polls
#输出
Migrations for 'polls':
polls/migrations/0001_initial.py:
- Create model Choice
- Create model Question
- Add field question to choice
#查看迁移执行的命令
python manage.py sqlmigrate polls 0001
#输出
BEGIN;
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL);
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_data` datetime(6) NOT NULL);
--
-- Add field question to choice
--
ALTER TABLE `polls_choice` ADD COLUMN `question_id` integer NOT NULL;
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
COMMIT;
关于迁移和官方文档的提醒要点:
1、迁移是 Django 对于模型定义(也就是你的数据库结构)的变化的储存形式 - 没那么玄乎,它们其实也只是一些你磁盘上的文件。如果你想的话,你可以阅读一下你模型的迁移数据,它被储存在 polls/migrations/0001_initial.py 里。别担心,你不需要每次都阅读迁移文件,但是它们被设计成人类可读的形式,这是为了便于你手动修改它们。
2、注意要点:
- 输出的内容和你使用的数据库有关,上面的输出示例使用的是 PostgreSQL。
- 数据库的表名是由应用名(polls)和模型名的小写形式( question 和 choice)连接而来。(如果需要,你可以自定义此行为。)
- 主键(IDs)会被自动创建。(当然,你也可以自定义。)
- 默认的,Django 会在外键字段名后追加字符串 “_id” 。(同样,这也可以自定义。)
- 外键关系由 FOREIGN KEY 生成。你不用关心 DEFERRABLE 部分,它只是告诉 PostgreSQL,请在事务全都执行完之后再创建外键关系。
- 生成的 SQL 语句是为你所用的数据库定制的,所以那些和数据库有关的字段类型,比如 auto_increment (MySQL)、 serial (PostgreSQL)和 integer primary key autoincrement (SQLite),Django 会帮你自动处理。那些和引号相关的事情 - 例如,是使用单引号还是双引号 - 也一样会被自动处理。
- 这个 sqlmigrate 命令并没有真正在你的数据库中的执行迁移 - 它只是把命令输出到屏幕上,让你看看 Django 认为需要执行哪些 SQL 语句。这在你想看看 Django 到底准备做什么,或者当你是数据库管理员,需要写脚本来批量处理数据库时会很有用。
再次执行命令:
python manage.py migrate
#输出
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Rendering model states... DONE
Applying polls.0001_initial... OK
这样,数据库中就自动创建了表格
总结:
编辑 models.py 文件,改变模型。
运行 python manage.py makemigrations 为模型的改变生成迁移文件。
运行 python manage.py migrate 来应用数据库迁移。
5.API使用
*此段直接引用于官方文档
$ python manage.py shell
>>> from polls.models import Choice, Question # Import the model classes we just wrote.
# No questions are in the system yet.
>>> Question.objects.all()
<QuerySet []>
# Create a new Question.
# Support for time zones is enabled in the default settings file, so
# Django expects a datetime with tzinfo for pub_date. Use timezone.now()
# instead of datetime.datetime.now() and it will do the right thing.
>>> from django.utils import timezone
>>> q = Question(question_text="What's new?", pub_date=timezone.now())
# Save the object into the database. You have to call save() explicitly.
>>> q.save()
# Now it has an ID.
>>> q.id
1
# Access model field values via Python attributes.
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Change values by changing the attributes, then calling save().
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() displays all the questions in the database.
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
Question object(1)对于我们了解这个对象的细节没什么帮助。让我们通过编辑 Question 模型的代码(位于 polls/models.py 中)来修复这个问题。给 Question 和 Choice 增加 str() 方法。
polls/models.py
from django.db import models
class Question(models.Model):
# ...
def __str__(self):
return self.question_text
class Choice(models.Model):
# ...
def __str__(self):
return self.choice_text
给模型增加 str() 方法是很重要的,这不仅仅能给你在命令行里使用带来方便,Django 自动生成的 admin 里也使用这个方法来表示对象。
注意:这些都是常规的 Python方法。让我们添加一个自定义的方法,这只是为了演示:
polls/models.py
import datetime
from django.db import models
from django.utils import timezone
class Question(models.Model):
# ...
def was_published_recently(self):
return self.pub_date >= timezone.now() - datetime.timedelta(days=1)
新加入的 import datetime 和 from django.utils import timezone 分别导入了 Python 的标准 datetime 模块和 Django 中和时区相关的 django.utils.timezone 工具模块。如果你不太熟悉 Python 中的时区处理,看看 时区支持文档 吧。
保存文件然后通过 python manage.py shell 命令再次打开 Python 交互式命令行:
>>> from polls.models import Choice, Question
# Make sure our __str__() addition worked.
>>> Question.objects.all()
<QuerySet [<Question: What's up?>]>
# Django provides a rich database lookup API that's entirely driven by
# keyword arguments.
>>> Question.objects.filter(id=1)
<QuerySet [<Question: What's up?>]>
>>> Question.objects.filter(question_text__startswith='What')
<QuerySet [<Question: What's up?>]>
# Get the question that was published this year.
>>> from django.utils import timezone
>>> current_year = timezone.now().year
>>> Question.objects.get(pub_date__year=current_year)
<Question: What's up?>
# Request an ID that doesn't exist, this will raise an exception.
>>> Question.objects.get(id=2)
Traceback (most recent call last):
...
DoesNotExist: Question matching query does not exist.
# Lookup by a primary key is the most common case, so Django provides a
# shortcut for primary-key exact lookups.
# The following is identical to Question.objects.get(id=1).
>>> Question.objects.get(pk=1)
<Question: What's up?>
# Make sure our custom method worked.
>>> q = Question.objects.get(pk=1)
>>> q.was_published_recently()
True
# Give the Question a couple of Choices. The create call constructs a new
# Choice object, does the INSERT statement, adds the choice to the set
# of available choices and returns the new Choice object. Django creates
# a set to hold the "other side" of a ForeignKey relation
# (e.g. a question's choice) which can be accessed via the API.
>>> q = Question.objects.get(pk=1)
# Display any choices from the related object set -- none so far.
>>> q.choice_set.all()
<QuerySet []>
# Create three choices.
>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.create(choice_text='The sky', votes=0)
<Choice: The sky>
>>> c = q.choice_set.create(choice_text='Just hacking again', votes=0)
# Choice objects have API access to their related Question objects.
>>> c.question
<Question: What's up?>
# And vice versa: Question objects get access to Choice objects.
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
>>> q.choice_set.count()
3
# The API automatically follows relationships as far as you need.
# Use double underscores to separate relationships.
# This works as many levels deep as you want; there's no limit.
# Find all Choices for any question whose pub_date is in this year
# (reusing the 'current_year' variable we created above).
>>> Choice.objects.filter(question__pub_date__year=current_year)
<QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]>
# Let's delete one of the choices. Use delete() for that.
>>> c = q.choice_set.filter(choice_text__startswith='Just hacking')
>>> c.delete()
6.Django管理页面
首先创建一个管理员
python manage.py createsuperuser
接下来会让你输入用户名、邮箱、密码、验证密码
完成后启动项目进入http://127.0.0.1:8000/admin/ ,输入你刚刚设置的账户密码
进去后,我们可以通过这个页面进行管理。
如果需要管理,我们要告诉他管理什么东西:
进入polls/admin
from django.contrib import admin
from .models import Question
admin.site.register(Question)
现在可以通过admin管理question的内容