(三)开发之tango_with_django和djangoByExample阅读笔记(Ubuntu下开发)

本篇详述了Django项目的搭建过程,从环境配置到数据库管理,再到视图、模板及前端展示,涵盖模型定义、表单处理、用户验证等多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

运行环境:python2.7(后期修改python3.5.2) django1.7 (后期修改django1.10)ubuntu14.10

本文糅合了tango_with_django(python2.7, django1.7)
以及djangoByExample(python3.5.2,django1.8)两本书,力求吸收两者优点的部分;

写在前面:先感受下django的目录结构,有个大概框架的概念:django首先是一个项目文件夹比如project(这是整个根目录),项目文件夹project下还有一个同名的project文件夹,里面有setting.py等文件,用来对整个项目的改变或设置参数,而通常还要在根目录下创建APP文件夹比如app1,app2,app3等等,每个app文件夹下都有对应的init.py,models.py,tests.py, views.py,admin.py,等文件。这里要注意项目包含app的概念,在project下修改的文件,作用于整个项目,当然会影响到所有app,比如对数据库的修改和建立。
(PS:所有关于setting.py的设置均可参照官方文档:https://docs.djangoproject.com/en/1.8/ref/settings/
PPS:大写序号按实际开发顺序调整步骤,数组序号是tango_with_django中的步骤

bug solved:9.4.4 写url映射的时候,‘^register/$’ 注意这里/不能丢,要不无法映射

一 1,创建django项目:

django-admin.py startproject tango_with_django_project

这样会创建一个名叫tango_with_django_project的目录标注1,目录下有两个文件,manager.py以及同名目录tango_with_django_project标注2,同名目录下有init.py,settings.py,urls.py,wsgi.p四个文件。
项目创建好了之后,可是尝试运行下:

python manage.py runserver

再用浏览器访问127.0.0.18080,怎么样是不是很简单~!
这里写图片描述

二 2,创建django的应用:

步骤一:进入工程目录,即标注1的目录,

python manager.py startapp  rango

这样就创建了名为rango的目录,目录下有5个文件:

  • init.py,和我们前面说过的功能一样.
  • models.py,一个存储你的应用中数据模型的地方 - 在这里描述数据的实体和关系.
  • tests.py,存储你应用的测试代码.
  • views.py,在这里处理用户请求和响应.
  • admin.py,在这里你可以向Django注册你的模型,它会为你创建Django的管理界面.

步骤二:在工程同名目录下即标注2,找到settings.py文件,其中的INSTALLED_APPS元组.在元祖的最后面增加rango,目的是让工程识别应用。

三 7,模型与数据库的使用(6+3步):

zero:先通过数据库管理软件手动创建一个数据库,再考虑下面的步骤连接
first:settings.py(注意这里的setting.py是在工程目录下的工程文件夹里,因为要数据库的配置是要适应整个项目的,所以在这里配置)里添加一个叫做DATABASES的字典(sqlite是django自动添加的)(PS:所有关于setting.py的设置均可参照官方文档:https://docs.djangoproject.com/en/1.8/ref/settings/):

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

这里贴上博主连本地mysql的配置:

DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        #配置使用mysql数据库
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'blogByDjango',
        'USER': 'root',
        'PASSWORD': '就不告诉你~',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

second:rango/models.py里定义模型,注意类继承models.MODEL;以及ForeignKey;还有unicode()方法(python3用的是str()方法,表示模型实例的名字),还有class Meta(写入到数据库中的表名称):
third:如果第一次用连数据库都没有创建,则创建迁移文件是可能报错:

$ python manage.py makemigrations rango
$ python manage.py migrate  #将这些改变更新到数据库中

如果报错是找不到mysqldb,处理见博主博客(亲测有效),链接:http://blog.youkuaiyun.com/happy_bigqiang/article/details/54345356

forth:如果之前已经有数据库表,只是对其改动,则:

$ python manage.py makemigrations rango  #为这些修改创建迁移文件(这里的迁移文件其实是一个记录文件,类似git的记录,并没有真正写入数据库,真正更新到数据库的是migrate命令)
$ python manage.py migrate  #将这些改变更新到数据库中

fifth:设置输入数据脚本,比如create_data.py:

import django
django.setup()
from rango.models import Category, Page
def populate():
    def add_cat(name):
        c = Category.objects.get_or_create(name=name)[0]
        return c   #get_or_create返回的是(object,created)并且代替了 c=Category(name=name)
                    #c.save() 
    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
    python_cat = add_cat('Python')

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

以上基本的数据库创建已完成,6,7步介绍创建django自带的数据库后台管理系统:
sixth:创建管理员来管理数据库:

$ python manage.py createsuperuser

根据提示输入用户名密码邮箱之后,启动django项目;然后在浏览器中输入

http://127.0.0.1:8000/admin

输入刚刚设置的用户名和密码,会发现白得一管理后台,尽管现在功能还很少,这就是django的特色吧;

seventh:设置管理界面(把数据库的表加载进来),rango/admin.py文件中:

from django.contrib import admin
from rango.models import Category, Page

admin.site.register(Category)
admin.site.register(Page)

eighth:定制你的数据库后台管理:
你需要修改rango/admin.py文件,创建PageAdmin类,这个类继承自admin.ModelAdmin;在PageAdmin类里,加入list_display = (‘title’, ‘category’, ‘url’);最后注册PageAdmin类到Django管理界面.需要修改admin.site.register(Page).在Rango的admin.py文件里修改成admin.site.register(Page, PageAdmin)
例子来自djangoByExample:

from django.contrib import admin
from .models import Post
# Register your models here.

class PostAdmin(admin.ModelAdmin):

    list_display = ('title','slug','author','publish','status')
    #后台右侧实现过滤功能
    list_filter = ('status','author','publish','created')
    #添加后台的搜索栏
    search_fields = ('title', 'body')
    #实现slug字段跟随title的输入自动填充
    prepopulated_fields = {'slug': ('title', )}
    #暂时不懂???
    raw_id_fields = ('author',)
    #在后台增加publish的日期显示
    date_hierarchy = 'publish'
    #按照publish和status字段排序记录
    ordering = ['publish','status']
admin.site.register(Post,PostAdmin)

四 3,使用视图函数和模板将数据库内容展现在前端界面:(使用视图函数3步【求快可2步】+使用模板3步【其实可以2步】)

总体思路通俗版:
a、浏览器通过用户request【客户点餐】
b、django通过url.py文件找到人(view)去处理【酒店找到对应厨师做菜】c、view.py处理玩通过render返回数据response给用户【厨师做完菜让服务员打包好送给客户】
总体思路专业版:
1、用户在浏览器点击根据html文件上的链接;(涉及xxx.html文件)
2、点击链接之后,django中的url.py文件将链接对应到对应的view.py文件中的视图函数(涉及url.py文件)
3、view.py内的视图函数读取数据库,并通过render()函数,将数据反馈给xxx.html并传给浏览器;
使用视图函数3步【求快可2步】:
步骤一:rango/views.py 写视图函数如index();

def index(request):
    # Query the database for a list of ALL categories currently stored.
    # Order the categories by no. likes in descending order.
    # Retrieve the top 5 only - or all if less than 5.
    # Place the list in our context_dict dictionary which will be passed to the template engine.
    category_list = Category.objects.order_by('-likes')[:5]
    context_dict = {'categories': category_list}

    # Render the response and send it back!
    return render(request, 'rango/index.html', context_dict)

这里djangobyexample中的view.py代码有个bug,还没解决:

from django.shortcuts import render,get_object_or_404
from blog.models import Post
# Create your views here.
def post_list(request):
    posts = Post.published.all()
    context_dict = {'posts':posts}

    return  render(request,'blog/post/list.html',context_dict)

def post_detail(request, year, month, day, post):
    post = get_object_or_404(Post, slug=post,
                                   status='published',
                                    publish__year=year,
        #这里是个bug,用月日筛选会发现找不到,这里的月传入的是英文,而数据库的是数字,造成不匹配
                                   #publish__month=month,
                                    #publish__day=day
                                    )
    return render(request, 'blog/post/detail.html', {'post': post})

步骤二:rango/urls.py 添加url()函数,使视图函数与url正则表达式链接,其中的name参数可以是模板使用这个参数标签来引用对应的url;

urlpatterns = [url(r'^$', 'views.index', name='index'),]

步骤三:tango_with_django/urls.py 添加 urls(r’rango/’,include(‘rango.urls’));目的是使应用的urls被项目识别,其实也可以直接在项目文件中直接写url,之所以不这样做是为了解耦合。

使用模板3步【其实可以2步】:
settings的设置参考官方文档:https://docs.djangoproject.com/en/1.8/ref/settings/#template-dirs
关于模板的settings这里更详细:https://docs.djangoproject.com/en/1.8/topics/templates/
比如:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',#驱动,django自带,可以改成自己喜欢的引擎,比如flask中的jin2
        'DIRS': [],#项目模板存放的位置,需要自己写,具体见下图配置
        'APP_DIRS': True,#APP模板的位置,设置为true则django会自动去加载APP下的名为templates的文件夹,并渲染,这样比较省事
        'OPTIONS': {#文件渲染的自带的处理器,使用render_to_response()渲染函数时需要用到;
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

first在工程下建立模板目录:
templates/rango,注意这里是在工程目录的第一级目录建立templates目录,不是第二级,见second图;
second 在settings中设置链接建立的模板目录:
settings>>TEMPLATES >>DIRS中添加TEMPLATE_PATH,其中TEMPLATE_PATH=os.path.join(BASE_DIR,’templates’)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(file)))
ps:BASE_DIR 其实django自己就写好了
这里解决了两个问题,os.path.join 解决了不同操作系统的路径名的不同分隔符的问题,os.path.dirname解决了硬编码问题,即建议使用相对路径,不用绝对路径,否则程序不便移植。
图片参考djangobyexample项目:
这里写图片描述
PS:其实这里不用这么麻烦,直接在APP下即blog/下新建一个templates目录,django就会自动去找,不用设置DIRS,这里就是提供一个如果想自己设置templates文件夹目录的思路
third ,在模板目录templates/rango下添加html文件,注意{{a}}是可以代表视图函数传来的变量;

PS:这里比较下

def my_view(request):
    # View code here...
    return render(request, 'myapp/index.html', {
        'foo': 'bar',})

return render_to_response('my_template.html', local(), context_instance=RequestContext(request))

的区别:
render_to_response()更方便,因为它与render()相比,包装了更多的参数,就是context_instance=RequestContext(request)的加入,这个参数引用的就是settings.py中的template中的’OPTIONS’的’context_processors’,这样你就不用自己在每个视图函数中重复写一些常用的参数,而render中只是包装了request,所以很多需要的参数要自己写,比较麻烦,其中的local()是python中的语法,可以代替所有的字典参数,非常方便,比如render上面的{‘foo’: ‘bar’,},所以建议开发中使用render_to_response()加local()函数;
PPS:囧,在1.10版本中官方取消了render_to_response()这个函数,并建议使用render()函数,我估摸着,django以后可能自动将其他参数包装放到render了。所以还是老老实实的用render吧~

5,使用静态文件,包括图片,js,css(共四步):

first:在工程目录下设置目录并放置图片,比如:static;可以在static下再设置一个目录便于区分,即static/image/rango.jpeg
second:在settings文件里告知目录位置,

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')
STATIC_PATH = os.path.join(BASE_DIR,'static')  #非必须
STATICFILES_DIRS = (         #非必须
    STATIC_PATH,
)

这里讲一下三个参数的区别(STATIC_PATH归到STATICFILES_DIRS中),首先URL与ROOT是必须参数,URL是负责供给模板html使用,如果是本地环境,其实代表127.0.0.1:5000/static;
ROOT是django将查找静态文件的功能交给服务器之后,服务器要查找的静态文件的路径,这里URL其实就是指向ROOT,在部署阶段,只要运行命令:

 python manage.py collectstatic   #先搜索再复制

django就自动搜索每个应用目录下的static文件夹里的文件,以及STATICFILES_DIRS设置的目录的文件,将所有文件复制到ROOT所指定的目录下,以便供给服务器去查找,所以这里可以看出STATICFILES_DIRS不是必须的,当然如果你如果将静态文件放在除应用目录下的static与工程目录下的static之外的其他目录,那就需要设置。
总结一下:STATICFILES_DIRS是各种源静态文件目录;
STATIC_ROOT 是目的静态文件目录,是将源静态文件集中到了一起,方便使用;
STATIC_URL 是html去使用静态文件的目录,指向STATIC_ROOT;
third:在项目里的urls利用setting里面的设置:

if not settings.DEBUG:
        urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG:
    urlpatterns += [
        url(r'^static/(?P<path>.*)$', views.static.serve, {'document_root': settings.STATIC_ROOT}, name="static"),]

forth:在html中使用静态文件:

{% load staticfiles %}
< img src = "{% static " images/rango.jpeg" %}" />

html中的load staticfiles其实指的就是django.contrib.staticfiles ,而html中static指的就是127.0.0.1:8000/static/(如果是本地情况下),其实static标签就是url中名为name=’static’的url;。
参考链接:http://m.oschina.net/blog/198768

6,静态媒体服务(大致五步):

first:在工程目录下新建media目录
second:setting设置路径:

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 

third:url使用设置的路径:

url(r'^media/(?P<path>.*)$', views.static.serve, {'document_root': settings.MEDIA_ROOT}, name="media")

forth:在model数据库模型中设置相应字段:

picture = models.ImageField(upload_to='profile_images', blank=True)

ImageField字段有一个upload_to属性.这个属性值连接着MEDIA_ROOT设置用来提供上传文档图片的路径.例如,MEDIA_ROOT设置为/tango_with_django_project/media/,那么upload_to=profile_imges将会使图片保存在/tango_with_django_project/media/profile_images/目录.
fifth:html文件里的设置:

<form id="user_form" method="post" action="/rango/register/"
                enctype="multipart/form-data">

当你希望用户通过表单上传文件时,必须把enctype设置成multipart/form-data.这个属性会让你的浏览器以特定的方式把表单数据返回给服务器.

8,将数据库的内容显示在html上(3步):

first:假设已完成7,即确保数据库中已经有数据;
second:在视图函数中导入数据库模型;实例化(c=Catotery.objects.all());将实例当做字典用render()传给前端模板。
third:在前端模板中用变量表示出来。作为模板语言,所有的命令都包含在{%和%}标签里,所有的变量都在{{和}}里.

9,在Category添加slug字段:

first:重写Category模型的save方法,我们将会调用slugify方法并更新slug字段:

from django.template.defaultfilters import slugify
class Category(models.Model):
    # 。。。。
    slug = models.SlugField(unique=True)

    def save(self, *args, **kwargs):
            self.slug = slugify(self.name)
            super(Category, self).save(*args, **kwargs)

second:视图函数中添加catetory函数:

def category(request, category_name_slug):
    #。。。
    category = Category.objects.get(slug=category_name_slug)

third:添加category.html,并修改index模板:

<li><a href="/rango/category/{{ category.slug }}">{{ category.name }}</a></li>

forth:修改rango的urls.py文件和urlpatterns元组

url(r'^category/(?P<category_name_slug>[\w\-]+)/$', views.category, name='category'),

10,使用表单,增加目录条目使用(4加1步):

first:创建表单类,django的表单类是直接跟数据库模型直接相关,在rango/forms.py中:

class CategoryForm(forms.ModelForm):
    name = forms.CharField(max_length=128, help_text="Please enter the category name.")
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
    slug = forms.CharField(widget=forms.HiddenInput(), required=False)
    class Meta:
        model = Category
        fields = ('name',)
class PageForm(forms.ModelForm):
    title = forms.CharField(max_length=128, help_text="Please enter the title of the page.")
    url = forms.URLField(max_length=200, help_text="Please enter the URL of the page.")
    views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)

    class Meta:
        model = Page
        exclude = ('category',)

second:视图函数rango/views.py:

def add_category(request):
    if request.method == 'POST':
        form = CategoryForm(request.POST)
        if form.is_valid():
            form.save(commit=True)
            return index(request)
        else:
            print form.errors
    else:
        form = CategoryForm()
    return render(request, 'rango/add_category.html', {'form': form})

third:表格模板html的编写,templates/rango/add_category.html:

        <form id="category_form" method="post" action="/rango/add_category/">

            {% csrf_token %}
            {% for hidden in form.hidden_fields %}
                {{ hidden }}
            {% endfor %}

            {% for field in form.visible_fields %}
                {{ field.errors }}
                {{ field.help_text }}
                {{ field }}
            {% endfor %}

            <input type="submit" name="submit" value="Create Category" />
        </form>

链接模板html的编写,rango/index.html:

<a href="/rango/add_category/">Add a New Category</a><br />

forth:映射url,rango/urls.py:

url(r'^add_category/$', views.add_category, name='add_category'), 

fifth:设想有时候用户输入并不是一定正确,我们可以重写ModelForm模块里clean()方法.这个方法会在表单数据存储到模型实例之前被调用,所以它可以让我们验证甚至修改用户输入的数据.在我们上面的例子中,我们可以检查url字段的值是否以http://开头 - 如果不是我们可以在用户前面添加上http://

class PageForm(forms.ModelForm):
    ...

    def clean(self):
        cleaned_data = self.cleaned_data
        url = cleaned_data.get('url')
        if url and not url.startswith('http://'):
            url = 'http://' + url
            cleaned_data['url'] = url

        return cleaned_data

11,用户验证(登陆,登出,注册等):

两种方法,一种自己写;第二种django提供了一个插件django-registration-redux,安装这个包,可以不用写模型,直接应用,但是也要写前端,前端的描述也变得简单,详见:http://hackerxu.com/Twd/#12-drr

12,使用bootstrap模板写前端:

大体思路是在基模板中引入bootstrap的css与js文件,之后其他前端模板只要继承基模板就好了,所以基模板比较复杂,其他还好,base.html中,添加css与js文件,这样就可以用bootstrap了,这跟django没关系,前端要用bootstrap都可以这么用:

  <head>
...
    <meta name="viewport" content="width=device-width, initial-scale=1">

...
    <link href="http://getbootstrap.com/dist/css/bootstrap.min.css" rel="stylesheet">

...
  </head>
  <body>
  ...
  <script src="http://getbootstrap.com/dist/js/bootstrap.min.js"></script>
  ...
  </body>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值