frist Django app— 二、 Model和管理界面
Django是符合MVC架构的,这里现学习M—Model,而且Django自带了一个管理model(数据库)的界面,所以一并学习。
Database 配置
编辑Django的配置文件settings.py进行配置
添加polls app,修改后如下
INSTALLED_APPS = [ 'django.contrib.admin', # 管理界面 'django.contrib.auth', # 认证系统 'django.contrib.contenttypes', # 框架的content type 'django.contrib.sessions', # session framework 'django.contrib.messages', # messages framework 'django.contrib.staticfiles', # 管理静态文件的framework 'polls.apps.PollsConfig', # 我们自己的app ]
最后一行位新添加的,表示新增一个app,类polls.apps.PoolsConfig定义了app,名称为“polls”(可以打开这个类看到)。
还可以看到很多其他的app,我们之前说过,一个project可以有多个app,一个app可以属于多个project,这个的实现方式就是这样,每个app都位于不同的包下面,如果一个project想包含一个app,只需要把这个app的包的配置写在这儿就可以了。
接下来配置数据库,修改完之后如下
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': 'polls.db', } }
Django支持大多数主流的数据库,包括postgresql,mysql,sqlite等,这里为了简单就直接用sqlite,如果使用mysql应该配置成如下(其他类似)
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', 'USER': 'root', 'PASSWORD': 'root', 'HOST': 'localhost', 'PORT': '3306', } }
数据库至此配置完成,接下来就是创建model
创建model
编辑mysite/polls/models.py
from __future__ import unicode_literals from django.db import models # Create your models here. class Question(models.Model):
# CharField:字段是字符串类型,有一个必要参数——字符串长度 question_text = models.CharField(max_length=200)
# DateField:字段是日期类型 publ_date = models.DateField('date published')
def __unicode__(self):
return self.question_text class Choice(models.Model):
# question作为choice的外键,这里是多对一关系,删除的时候进行级联,Django还支持:many-to-one, many-to-many, and one-to-one. question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)
def __unicode__(self):
return self.choice_text
每个model继承自models.Model,会继承一些常用的操作方法。每个class对应的属性都对应数据库中表中的字段——这也就是ORM
生成数据库表结构
# 告诉Django model改变了,并且保存为一个migration python manage.py makemigrations
运行该命令,输出如下内容,并在pools/migrations下生成0001_initial.py
Migrations for 'polls': 0001_initial.py: - Create model Choice - Create model Question - Add field question to choice
我们可以看看Django根据这个migration会怎么生成表结构运行
# 0001 为之前生成的0001_initial.py的前缀,表示第一个版本的migration python manage.py sqlmigrate polls 0001
输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
BEGIN; -- -- Create model Choice -- CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL); -- -- Create model Question -- CREATE TABLE "polls_question" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "question_test" varchar(200) NOT NULL, "publ_date" date NOT NULL); -- -- Add field question to choice -- ALTER TABLE "polls_choice" RENAME TO "polls_choice__old"; CREATE TABLE "polls_choice" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" integer NOT NULL REFERENCES "polls_question" ("id")); INSERT INTO "polls_choice" ("choice_text", "votes", "id", "question_id") SELECT "choice_text", "votes", "id", NULL FROM "polls_choice__old"; DROP TABLE "polls_choice__old"; CREATE INDEX "polls_choice_7aa0f6ee" ON "polls_choice" ("question_id"); COMMIT;
Django会运行上面这些语句来生成数据库表结构,我们可以看到生成两张表分别对应两个model,给question这张表添加一个外键。
现在我们可以生成数据库表结构了,这个命令就是将上面生成的migration应用到数据库
python manage.py migrate
输出
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
Operations to perform:
Apply all migrations: admin, contenttypes, polls, auth, sessions
Running migrations:
Rendering model states... DONE
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying polls.0001_initial... OK
Applying sessions.0001_initial... OK
到这儿,数据库表结构生成完毕,我们可以使用sqlite3查看生成的表结构
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
sqlite3 polls.db #以下为输出内容 SQLite version 3.8.7.1 2014-10-29 13:59:56 Enter ".help" for usage hints. sqlite> .tables auth_group django_admin_log auth_group_permissions django_content_type auth_permission django_migrations auth_user django_session auth_user_groups polls_choice auth_user_user_permissions polls_question
使用API操作model
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
# 这里用的是ipython,进入django命令行 python manage.py shell Python 2.7.9 (default, Mar 1 2015, 18:22:53) Type "copyright", "credits" or "license" for more information. IPython 2.3.0 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. # 导入model In [2]: from polls.models import Choice, Question # 查看所有的question对象 In [3]: Question.objects.all() Out[3]: [<Question: what`s up?>] # 获取id为0的对象,没有id为0的对象,所以会报错 In [5]: Question.objects.get(id=0) --------------------------------------------------------------------------- DoesNotExist Traceback (most recent call last) <ipython-input-5-bd4c3a1273f2> in <module>() ----> 1 Question.objects.get(id=0) /usr/local/lib/python2.7/dist-packages/Django-1.9.7-py2.7.egg/django/db/models/manager.pyc in manager_method(self, *args, **kwargs) 120 def create_method(name, method): 121 def manager_method(self, *args, **kwargs): --> 122 return getattr(self.get_queryset(), name)(*args, **kwargs) 123 manager_method.__name__ = method.__name__ 124 manager_method.__doc__ = method.__doc__ /usr/local/lib/python2.7/dist-packages/Django-1.9.7-py2.7.egg/django/db/models/query.pyc in get(self, *args, **kwargs) 385 raise self.model.DoesNotExist( 386 "%s matching query does not exist." % --> 387 self.model._meta.object_name 388 ) 389 raise self.model.MultipleObjectsReturned( DoesNotExist: Question matching query does not exist. # 获取id为1的对象 In [6]: Question.objects.get(id=1) Out[6]: <Question: what`s up?> In [7]: q = Question.objects.get(id=1) # 删除该对象 In [8]: q.delete() Out[8]: (4, {u'polls.Choice': 3, u'polls.Question': 1}) # 查看发现已经删除 In [9]: Question.objects.all() Out[9]: [] In [11]: from django.utils import timezone # 新建一个对象 In [13]: q = Question(question_text="What's new?", publ_date=timezone.now()) # 保存到数据库 In [15]: q.save() # 保存到数据库之后Django自动生成了id,只有在save之后才有 In [16]: q.id Out[16]: 2 # 查看字段值 In [17]: q.question_text Out[17]: "What's new?" In [18]: q.publ_date Out[18]: datetime.datetime(2016, 7, 10, 13, 12, 40, 146050, tzinfo=<UTC>) In [19]: q.question_text = "What's up?" In [20]: q.save() In [22]: q Out[22]: <Question: What's up?> In [23]: Question.objects.all() Out[23]: [<Question: What's up?>] In [24]: Question.objects.filter(id=1) Out[24]: [] # 使用filter查询 In [25]: Question.objects.filter(id=2) Out[25]: [<Question: What's up?>] In [26]: Question.objects.filter(question_text__startswith='What') Out[26]: [<Question: What's up?>] In [29]: Question.objects.get(publ_date__year=timezone.now().year) Out[29]: <Question: What's up?> # 查看question关联的choice In [30]: q.choice_set.all() Out[30]: [] # 新建一个choice关联到question In [31]: q.choice_set.create(choice_text='Not much', votes=0) Out[31]: <Choice: Not much> In [32]: q.choice_set.create(choice_text='The sky', votes=0) Out[32]: <Choice: The sky> In [33]: c = q.choice_set.create(choice_text='Just hacking again', votes=0) # 查看choice对应的question In [34]: c.question Out[34]: <Question: What's up?> In [35]: q.choice_set.all() Out[35]: [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>] In [36]: q.choice_set.count() Out[36]: 3
Django提供了很多API来操作model,包括新建、更新、删除、关联、从一个对象查询关联的对象等等,除此之外Django还提供了web界面对model进行管理。
Django Admin
使用以下命令依次输入用户名、邮箱(注意邮箱)、密码(8位以上的字母数字组成)
python manage.py createsuperuser
访问http://127.0.0.1:8000/admin/登陆,可以看到管理界面,但是现在并没有mode,接下来注册model
编辑polls/admin.py
from django.contrib import admin from polls.models import Choice, Question # Register your models here. admin.site.register(Choice) admin.site.register(Question)
再次登陆就可以看到model:Choice,Question,可以在界面上增删改查,so easy
代码位置