Django06模型和数据库

首先,让我们看看Rango的需求.下面列出了Rango数据关键的几个需求.

  • Rango实际上是一个网页目录 - 一个包含其他我站链接的网站
  • 有许多不同网站的目录,每个目录中包含许多链接.我们在第二章假设1对多关系 看下面的ER图.
  • 一个目录要有名字,访问数和链接.
  • 一个页面要有目录,标题,URL和一些视图

1. 告诉Django你的数据库

在你创造任何模型之前都要对你的数据库进行设置
Django会自动在settings.py里添加一个叫做DATABASES的字典.它包含如下.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

能看到默认用SQLite3作为后端数据库.SQLite是个轻量级的数据库对我们开发很有用.我们仅仅需要设置DATABASE_PATH里的NAME键值对.其他引擎需要USER,PASSWORD,HOST和PORT等关键字

2. 创建模型

让我们为Rango创建两个数据模型.

在rango/models.py里,我们定义两个继承自djnago.db.models.Model的类.这两个类分别定义目录和页面.定义Category和Page如下

from django.db import models

# Create your models here.

class Category(models.Model):
    name = models.CharField(max_length=128, unique=True)
    def __str__(self):
        return self.name

class Page(models.Model):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=128)
    url = models.URLField()
    views = models.IntegerField(default=0)
    def __str__(self):
        return self.title

当你定义了一个模型,你需要制定可选参数的属性以及相关的类型列表.Django提供了许多内建字段.一些常用的如下.

  • CharField,存储字符数据的字段(例如字符串).max_length提供了最大长度.
  • URLField,和CharField一样,但是它存储资源的URL.你也可以使用max_length参数.
  • 'IntegerField',存储整数.
  • DateField,存储Python的datetime.date.

每个字段都有一个unique属性.如果设置为True,那么在整个数据库模型里它的字段里的值必须是唯一的.例如,我们上面定义的Category模型.name字段被设置为unique - 所以每一个目录的名字都必须是唯一的
如果你想把这个字段作为数据库的关键字会非常有用.你可以为每个字段设置一个默认值(default='value'),也可以设置成NULL(null=True).
Django也提供了连接模型/表的简单机制.这个机制封装在3个字段里,如下.

  • ForeignKey, 创建1对多关系的字段类型.
  • OneToOneField,定义一个严格的1对1关系字段类型.
  • ManyToManyFeild,当以多对多关系字段类型.
    从上面我们的例子,Page中category字段是ForeignKey类型.所以我们可以创建一个1对多关系的Category模型/表,这个Category会作为构造函数的一个参数.Django会自动的为每个模型表中创建ID字段.所以你不同为每个模型创建主键 - 它已经为你做好了!

3. 设置数据库并创建管理员

如果还没有设置数据库那么需要通过migrate命令来设立.

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, contenttypes, auth, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying sessions.0001_initial... OK

你是否还记得在settings.py文件里设置的INSTALLED_APPS列表,它会初始化创建这些app的图表,例如auth,admin等等.在你的项目根目录里会创建db.sqlite文件.

  • 现在你可以创建一个管理员来管理数据库.
    $ python manage.py createsuperuser

4. 创建/上传模型/表

当你更改模型的时候,你需要通过makemigrations进行修改,所以对于rango,我们需要:

$ python manage.py makemigrations rango
Migrations for 'rango':
  0001_initial.py:
    - Create model Category
    - Create model Page

如果你检查rango/migrations文件,你会发现会创建一个叫做0001_initial.py的python脚本.如果想要SQL命令去执行迁移,那么可以用下面的命令python manage.py sqlmigrate <app_name> <migration_no.我们上面的迁移数字是0001,所以我们输入python manage.py sqlmigrate rango 0001,让我们试试看.
现在让我们应用这些迁移(基于创建数据库图表).

$ python manage.py migrate
Operations to perform:
  Apply all migrations: admin, rango, contenttypes, auth, sessions
Running migrations:
  Applying rango.0001_initial... OK

当你添加已存在的模型,你需要重复运行python manage.py makemigrations <app_name>命令然后再运行python manage.py migrate.

5. Shell

shell
# Import the Category model from the Rango application
>>> from rango.models import Category
# Show all the current categories
>>> print Category.objects.all()
[] # Returns an empty list (no categories have been defined!)
# Create a new category object, and save it to the database.
>>> c = Category(name="Test")
>>> c.save()
# Now list all the category objects stored once more.
>>> print Category.objects.all()
[<Category: test>] # We now have a category called 'test' saved in the database!
# Quit the Django shell.
>>> quit()

在例子中我们首先导入我们需要操作的模型.然后打印出存在的目录,在这里因为我们的图表是空所以输出也是空.然后创建并储存一个目录,打印.

6. 设置管理界面

Django最突出的一个特性就是它提供内建的网页管理界面,用来浏览和编辑存储在模型的数据,也可以与数据库图表交互.在settings.py文件里,注意到有一个默认安装的django.contib.adminapp,而且你的urls.py里也默认增加了admin/匹配.

开启Django服务:
$ python manage.py runserver
访问127.0.0.1:8000/admin.可以用先前设置管理员账户的用户名和密码来登录Django管理界面.管理界面只包含Groups和Users图表以我们需要让Django包含rango模块.所以打开rango/admin.py输入如下代码:

from django.contrib import admin
from rango.models import Category, Page
admin.site.register(Category)
admin.site.register(Page)

上面代码会为我们在管理界面注册模型.如果我们想要其他模型,可以在admin.stie.register()函数里传递模型作为参数.

完成之后重新访问127.0.0.1:8000/admin/,你想回看到如下图案.

效果图

7. 创建Population Script

往数据库里输入数据会非常麻烦.许多开发者会随机的往数据库里输入测试数据.如果你在一个小的开发团队里,每个人都得传点数据.最好是写一个脚本而不是每个人单独的上传数据,这样就可以避免垃圾数据的产生.所以我们需要为你的数据库创建 population script.这个脚本自动的为你的数据库生成测试数据.

我们需要在Django项目的根目录里创建population script(例如<workspace>/tango_with_django_project/).创建populate_rango.py文件代码如下.

import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tango_with_django_project.settings')

import django
django.setup()

from rango.models import Category, Page


def populate():
    python_cat = add_cat('Python')

    add_page(cat=python_cat,
        title="Official Python Tutorial",
        url="http://docs.python.org/2/tutorial/")

    add_page(cat=python_cat,
        title="How to Think like a Computer Scientist",
        url="http://www.greenteapress.com/thinkpython/")

    add_page(cat=python_cat,
        title="Learn Python in 10 Minutes",
        url="http://www.korokithakis.net/tutorials/python/")

    django_cat = add_cat("Django")

    add_page(cat=django_cat,
        title="Official Django Tutorial",
        url="https://docs.djangoproject.com/en/1.5/intro/tutorial01/")

    add_page(cat=django_cat,
        title="Django Rocks",
        url="http://www.djangorocks.com/")

    add_page(cat=django_cat,
        title="How to Tango with Django",
        url="http://www.tangowithdjango.com/")

    frame_cat = add_cat("Other Frameworks")

    add_page(cat=frame_cat,
        title="Bottle",
        url="http://bottlepy.org/docs/dev/")

    add_page(cat=frame_cat,
        title="Flask",
        url="http://flask.pocoo.org")

    # Print out what we have added to the user.
    for c in Category.objects.all():
        for p in Page.objects.filter(category=c):
            print ("- {0} - {1}".format(str(c), str(p)))

def add_page(cat, title, url, views=0):
    p = Page.objects.get_or_create(category=cat, title=title, url=url, views=views)[0]
    return p

def add_cat(name):
    c = Category.objects.get_or_create(name=name)[0]
    return c

# Start execution here!
if __name__ == '__main__':
    print ("Starting Rango population script...")
    populate()

$ python populate_rango.py执行脚本

效果图

8. 基本流程

流程图

9. 练习

练习

添加views和likes的代码:

代码

populate.py的修改

修改

定制管理界面

admin

最终效果

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

推荐阅读更多精彩内容