赞
踩
想搞清楚Django跟后台数据库是如何交互的。在网上找了好多,不是太麻烦就是觉得不靠谱,对我都不适合,找了好久,最后看到一个自强学堂的网站,很喜欢里面的内容。照着教程搭了一遍,还剩一些bug没解决。我想先弄清楚django跟后台怎么交互的再说,先分着说,然后最后总结一下吧。
使用得环境是Centos7+python3+django1.8。
1 virtaulenv
官方解释:virtualenv是一个创建隔离的python环境的一个工具,额。。。按照我现在的理解我是粗略得把它理解成windows里面的虚拟机。每个虚拟机都是一个单独的环境,与别得虚拟机没有关系。如果后续有更深得理解,再更。
2 安装和使用virtualenv
pip install virtualenv virtualwrapper
编辑root用户家目录下的.bash_profile文件(如果不是root用户,并且需要使用sudo命令的话,应在sudo的配置文件中加上此用户),加上:
export WORKON_HOME=$HOME/.virtualenvs
source /usr/python3/bin/virtualenvwrapper.sh
wirtualwrapper.sh脚本文件会帮我们在.virtualenvs目录下创建虚拟环境必要的文件和目录,然后就可以使用啦。
我使用到的命令:
mkvirtualenv mic:创建mic项目和运行环境mic
当退出虚拟环境后还想再次运行,workon mic即可
注:这个地方写virtualenvwrapper.sh的路径即可。如果你的linux系统中同时装了python2和python3,那么要在这个脚本文件中声 明python3的路径,就像这样export VIRTUALENVWRAPPER_VIRTUALENV=/usr/python3/bin/virtualenv
3 数据库的模板和脚本文件(列出主要的)
以下脚本文件内容来自于自强学堂。
数据库的模板文件在$YOUAPP_PATH/models.py :
- class Column(models.Model):
- name = models.CharField('栏目名称', max_length=256)
- slug = models.CharField('栏目网站', max_length=256, db_index=True)
- intro = models.TextField('栏目介绍', default='')
-
- def __str__(self):
- return self.name
-
- def get_absolute_url(self):
- return reverse('column', args=(self.slug, ))
-
- class Meta:
- verbose_name = '程序'
- verbose_name_plural = '程序'
-
- ordering = ['name']
-
-
-
- class Article(models.Model):
- column = models.ManyToManyField(Column, verbose_name='ofpro')
- title = models.CharField('标题', max_length=256)
- pub_date = models.DateTimeField('发表时间', auto_now_add=True, editable=True)
- update_time = models.DateTimeField('更新时间', auto_now=True, null=True)
- slug = models.CharField('网站', max_length=256, db_index=True)
- author = models.ForeignKey('auth.User', blank=True, null=True, verbose_name='作者')
- published = models.BooleanField('最后发布', default=True)
-
- content = UEditorField('内容', height=300, width=1000, default=u'', blank=True, imagePath='uploads/images/',toolbars='besttome', filePath='uploads/files/')
-
- # UEditor是google的编辑器, 还没研究具体怎么用
-
-
-
- def __str__(self):
- return self.title
-
-
-
- def get_absolute_url(self):
- return reverse('article', args=(self.slug, ))
-
- # reverse函数获取路径,在前端页面中调用get_absolute_url跳转到这个页面
- class Meta:
-
- verbose_name = '教程'
- verbose_name_plural = '教程'
数据库脚本文件 :
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- # @Date : 2015-07-28 20:38:38
- # @Author : Weizhong Tu (mail@tuweizhong.com)
- # @Link : http://www.tuweizhong.com
-
- '''
- create some records for demo database
- '''
-
- from minicms.wsgi import *
- from news.models import Column, Article
-
-
- def main():
- columns_urls = [
- ('体育新闻', 'sports'),
- ('社会新闻', 'society'),
- ('科技新闻', 'tech'),
- ]
-
- for column_name, url in columns_urls:
- c = Column.objects.get_or_create(name=column_name, slug=url)[0]
-
- # 创建 10 篇新闻
- for i in range(1, 11):
- article = Article.objects.get_or_create(
- title='{}_{}'.format(column_name, i),
- slug='article_{}'.format(i),
- content='新闻详细内容: {} {}'.format(column_name, i)
- )[0]
-
- article.column.add(c)
-
-
- if __name__ == '__main__':
- main()
- print("Done!")
urls.py文件(部分) :
- urlpatterns = [
- url(r'^admin/', include(admin.site.urls)),
- url(r'^ueditor/', include(DjangoUeditor_urls)),
- url(r'^$', 'news.views.index', name='index'),
- # name是正则表达式的别名,在.html文件中使用这个>匹配条件时,
- # 只用写上index,即使正则表达式匹配规则更改也没>关系。
- url(r'^column/(?P<awm>[^/]+)/$', 'news.views.column_detail', name='column'),
- # ?P<awm>这个awm相当于一个变量,[^/]不匹配/,+匹配前面的正则一次或多次,
- # http://192.168.80.126:8080/column/tech/a/ : tech就是这个awm变量的值,
- # 由于后面有不匹配tech后的/, 因此后面的a参数不被匹配,就报错.
- # 这个变量是在views中传递给函数的,因此在返回给 户端后,可以在页面打印出来.
- url(r'^news/(?P<article_slug>[^/]+)/$', 'news.views.article_detail', name='article'),
- ]
views.py文件 :
- from django.shortcuts import render
- from django.http import HttpResponse
- from .models import Column, Article
-
- def index(request):
- columns = Column.objects.all()
- return render(request, 'index.html', {'columns': columns})
- # awm参数是从urls中传递过来的
- def column_detail(request, awm):
- column= Column.objects.get(slug=awm)
- return render(request, 'news/column.html', {'column': column})
-
- def article_detail(request, article_slug):
- # article = Article.objects.get(slug=article_slug)[0]
- article = Article.objects.filter(slug=article_slug)[0]
- return render(request, 'news/article.html', {'article': article})
index模板文件 :
- {% extends "base.html" %}
- {% block title %} 首页 {% endblock title %}
- {% block content %}
-
- <ul>
- {% for column in columns %}
- <li>
- <a href="{{ column.get_absolute_url }}">{{ column.name }}</a>
- </li>
- {% endfor %}
- </ul>
- {% endblock content %}
column模板文件 :
- {% extends "base.html" %}
- {% block title %}
- {{ column.title }}
- {% endblock title %}
-
- {% block content %}
- <p>栏目名称: {{ column.name }}</p>
- 栏目简介: {{ column.intro }}
- 栏目文章列表:
- <ul>
- {% for article in column.article_set.all %}
- <li>
- <a href="{{ article.get_absolute_url }}">
- {{ article.title }}
- </a>
- </li>
- {% endfor %}
-
- </ul>
- {% endblock content %}
article模板文件 :
- {% extends "base.html" %}
- {% block title %}
- {{ article.title }}
- {% endblock title %}
-
- {% block content %}
- <h1>文章标题: {{ article.title }}</h1>
- <div id="main">
- {{ article.content }}
- </div>
- {% endblock content %}
分析:
url(r'^$', 'news.views.index', name='index')这条规则, 此时django会去news(app名)下的views(视图)文件中的index函数。
下面的代码是视图中的index函数的部分 :
- def index(request):
- columns = Column.objects.all()
- return render(request, 'index.html', {'columns': columns})
不清楚Column.objects.all()的值 :
- 打开python3 manage.py shell
- >>> from .models import Column, Article
- >>> columns = Column.objests.all()
- >>> columns
- [<Column: 体育新闻>, <Column: 社会新闻>, <Column: 科技新闻>]
index函数返回被渲染后的index.html文件, 然后就是打开网页看到的内容 :
index.html文件部分内容 :
- {% for column in columns %}
- <li>
- <a href="{{ column.get_absolute_url }}">{{ column.name }}</a>
- </li>
- {% endfor %}
网页显示column.name,column.name是之前插入的column_name, 也就是体育新闻,社会新闻,科技新闻三个字段.
- 数据库脚本文件部分
- columns_urls = [
- ('体育新闻', 'sports'),
- ('社会新闻', 'society'),
- ('科技新闻', 'tech'),
- ]
- for column_name, url in columns_urls:
- c = Column.objects.get_or_create(name=column_name, slug=url)[0]
然后在index.html文件中可以看到, 这三个字段分别连接到get_absolute_url这个函数的返回值中, 于是去models.py文件中(模型)中找到这个函数:
- def get_absolute_url(self):
- return reverse('column', args=(self.slug, ))
这个返回值是/column/SLUG, 这里的SLUG也就是前面数据库脚本文件中的url变量的值, 由数据库脚本看出体育新闻对应的SLUG是sports, 社会新闻对应的SLUG是soceity, 科技新闻对应的SLUG是tech, 即当我点击体育新闻时, 会请求/column/sports页面. 这一步完成了前端到后台数据库取数的步骤. url控制器会查看url模式, 发现匹配 :
url(r'^column/(?P<awm>[^/]+)/$', 'news.views.column_detail', name='column'),
于是去视图中找column_detail函数:
- def column_detail(request, awm):
- column= Column.objects.get(slug=awm)
- return render(request, 'news/column.html', {'column': column}
于是找到模板目录的news下的column.html :
- <p>栏目名称: {{ column.name }}</p>
- 栏目简介: {{ column.intro }}
- 栏目文章列表:
- <ul>
- {% for article in column.article_set.all %}
- <li>
- <a href="{{ article.get_absolute_url }}">
- {{ article.title }}
- </a>
- </li>
- {% endfor %}
-
- </ul>
页面内容 :
不是很清楚column.article_set.all和 article.title的值,打开shell, 可以看到column.article_set.all的值 :
- >>> from news.models import Article, Column
- >>> column = Column.objects.get(slug='sports')
- >>> column
- <Column: 体育新闻>
- >>> column.article_set.all
- <bound method BaseManager.all of <django.db.models.fields.related.create_many_related_manager.<locals>.ManyRelatedManager object at 0x7f91b517db38>>
- >>> column.article_set.all()[<Article: 体育新闻_1>, <Article: 体育新闻_2>, <Article: 体育新闻_3>, <Article: 体育新闻_4>, <Article: 体育新闻_5>, <Article: 体育新闻_6>, <Article: 体育新闻_7>, <Article: 体育新闻_8>, <Article: 体育新闻_9>, <Article: 体育新闻_10>, <Article: 体育新闻_1>, <Article: 体育新闻_2>, <Article: 体育新闻_3>, <Article: 体育新闻_4>, <Article: 体育新闻_5>, <Article: 体育新闻_6>, <Article: 体育新闻_7>, <Article: 体育新闻_8>, <Article: 体育新闻_9>, <Article: 体育新闻_10>, '...(remaining elements truncated)...']
- >>> column.article_set.all()[0].title
- '体育新闻_1'
也就是上图中看到的体育新闻1-10.
总结: django大致的工作流程是: 当有请求到达时, 先去url控制器查找匹配规则, 匹配成功去view视图中找到相应的方法(函数), 然后去对应的模板目录找到html文件, 在html中获取models(模型)中相应的变量值, 然后将结果返回给客户端. 数据库脚本文件中涉及到数据库表的多对多关系, 没有做说明, 文中一些bug也没说明.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。