django-基础-后台&表单&配置&静态文件

后台

官方文档:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.history_view

每个app中的admin.py 文件与后台相关
对于zqxt_admin项目,app为blog
模型为

class Article(models.Model):
    title = models.CharField(u'标题', max_length=256)
    content = models.TextField(u'内容')
 
    pub_date = models.DateTimeField(u'发表时间', auto_now_add=True, editable = True)
    update_time = models.DateTimeField(u'更新时间',auto_now=True, null=True)

	## 如果不加这个,在后台看不到名字
	def __unicode__(self):# 在Python3中用 __str__ 代替 __unicode__
        return self.title

修改admin.py

from django.contrib import admin
from .models import Article
admin.site.register(Article)

在urls.py中开启admin
参考:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#overview

列表中显示与字段相关的其他内容

from django.contrib import admin
from .models import Article
 
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title','pub_date','update_time',)
 
admin.site.register(Article,ArticleAdmin)

list_display配置显示其他字段
也可显示非字段内容,或者字段相关的内容

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
 
    def my_property(self):
        return self.first_name + ' ' + self.last_name
    my_property.short_description = "Full name of the person"
 
    full_name = property(my_property)

在admin.py中

from django.contrib import admin
from .models import Article, Person
 
class ArticleAdmin(admin.ModelAdmin):
    list_display = ('title', 'pub_date', 'update_time',)

class PersonAdmin(admin.ModelAdmin):
    list_display = ('full_name',)
 
admin.site.register(Article, ArticleAdmin)
admin.site.register(Person, PersonAdmin)

这时候如果要修改models.py中的字段,添加状态草稿,正式发布,需要自动更改表
需要添加South插件
其他功能

搜索功能:search_fields = ('title', 'content',) 这样就可以按照 标题或内容搜索了
筛选功能:list_filter = ('status',) 这样就可以根据文章的状态去筛选,比如找出是草稿的文章
新增或修改时的布局顺序:https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets

修改admin site
定制加载的列表, 根据不同的人显示不同的内容列表,比如输入员只能看见自己输入的,审核员能看到所有的草稿,这时候就需要重写get_queryset方法
重写get_queryset

class MyModelAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = super(MyModelAdmin, self).get_queryset(request)
        if request.user.is_superuser:
            return qs
        else:
            return qs.filter(author=request.user)

该类实现的功能是如果是超级管理员就列出所有的,如果不是,就仅列出访问者自己相关的
定制搜索功能

class PersonAdmin(admin.ModelAdmin):
    list_display = ('name', 'age')
    search_fields = ('name',)
 
    def get_search_results(self, request, queryset, search_term):
        queryset, use_distinct = super(PersonAdmin, self).get_search_results(request, queryset, search_term)
        try:
            search_term_as_int = int(search_term)
            queryset |= self.model.objects.filter(age=search_term_as_int)
        except:
            pass
        return queryset, use_distinct

queryset 是默认的结果,search_term 是在后台搜索的关键词
修改保存时的一些操作,可以检查用户,保存的内容等,比如保存时加上添加人

from django.contrib import admin
class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.user = request.user
        obj.save()

其中obj是修改后的对象,form是返回的表单(修改后的),当新建一个对象时 change = False, 当修改一个对象时 change = True
如果需要获取修改前的对象的内容可以用

from django.contrib import admin
 
class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj_original = self.model.objects.get(pk=obj.pk)
        obj.user = request.user
        obj.save()

那么又有问题了,这里如果原来的obj不存在,也就是如果我们是新建的一个怎么办呢,这时候可以用try,except的方法尝试获取,当然更好的方法是判断一下这个对象是新建还是修改,是新建就没有 obj_original,是修改就有

from django.contrib import admin
 
class ArticleAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        if change:# 更改的时候
            obj_original = self.model.objects.get(pk=obj.pk)
        else:# 新增的时候
            obj_original = None
 
        obj.user = request.user
        obj.save()

删除时做一些处理

from django.contrib import admin
 
class ArticleAdmin(admin.ModelAdmin):
    def delete_model(self, request, obj):
        """
        Given a model instance delete it from the database.
        """
        # handle something here
        obj.delete()

表单

功能:

  • 模板中表单的渲染
  • 数据的验证工作,某一些输入不合法也不会丢失已经输入的数据。
  • 还可以定制更复杂的验证工作,如果提供了10个输入框,必须必须要输入其中两个以上,在 forms.py 中都很容易实现

a+b的应用

<!DOCTYPE html>
<html>
<body>
<p>请输入两个数字</p>
<form action="/add/" method="get">
    a: <input type="text" name="a"> <br>
    b: <input type="text" name="b"> <br>
     
    <input type="submit" value="提交">
</form>
</body>
</html>

服务端接收

from django.http import HttpResponse
from django.shortcuts import render
 
def index(request):
    return render(request, 'index.html')
     
def add(request):
    a = request.GET['a']
    b = request.GET['b']
    a = int(a)
    b = int(b)
    return HttpResponse(str(a+b))

request.GET可看成字典
GET方法的值都会保存在其中,可以通过request.GET.get('key', None)取值,没有时不报错

django的forms

新建一个 zqxt_form2 项目
django-admin.py startproject zqxt_form2
# 进入到 zqxt_form2 文件夹,新建一个 tools APP
python manage.py startapp tools

在tools文件夹中新建一个 forms.py 文件

from django import forms
class AddForm(forms.Form):
    a = forms.IntegerField()
    b = forms.IntegerField()

我们的视图函数 views.py 中

# coding:utf-8
from django.shortcuts import render
from django.http import HttpResponse

# 引入我们创建的表单类
from .forms import AddForm
 
def index(request):
    if request.method == 'POST':# 当提交表单时
     
        form = AddForm(request.POST) # form 包含提交的数据
         
        if form.is_valid():# 如果提交的数据合法
            a = form.cleaned_data['a']
            b = form.cleaned_data['b']
            return HttpResponse(str(int(a) + int(b)))
     
    else:# 当正常访问时
        form = AddForm()
    return render(request, 'index.html', {'form': form})

对应的模板文件 index.html

<form method='post'>
{% csrf_token %}
{{ form }}
<input type="submit" value="提交">
</form>

再在 urls.py 中对应写上这个函数

from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
    # 注意下面这一行
    url(r'^$', 'tools.views.index', name='home'),
    url(r'^admin/', include(admin.site.urls)),
)

配置

创建项目后会生成一系列文件,1.6以后的版本settings.py中有如下语句

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

os.path.dirname(__file__)得到当前文件所在目录,再次调用os.path.dirname获取上一级目录
BASE_DIR为项目路径

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True

ALLOWED_HOSTS设置哪些域名可以访问,ALLOW_HOSTS = ['*']是允许所有的

ALLOWED_HOSTS = ['*.besttome.com','www.ziqiangxuetang.com']

static配置

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'static')

static 是静态文件所有目录,比如 jquery.js, bootstrap.min.css 等文件;
我们只要把静态文件放在APP的static目录下,部署时用python manage.py collectstatic
就会把静态文件都收集到STATIC_ROOT目录中
但是,如果有一些公用的静态文件,需要设置STATICFILES_DIRS另外再弄一个文件夹,如下

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "common_static"),
    '/var/www/static/',
)

这样我们就可以把静态文件放在 common_static 和 /var/www/static/中了,Django也能找到它们

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

media文件夹用来存放用户上传的文件,与权限有关
有时候一些模板不属于app,比如baidutongji.html, share.html
Django 1.5 - Django 1.7

TEMPLATE_DIRS = (
    os.path.join(BASE_DIR, 'templates').replace('\\', '/'),
    os.path.join(BASE_DIR, 'templates2').replace('\\', '/'),
    # ...
)

Django 1.8 及以上版本

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            os.path.join(BASE_DIR,'templates').replace('\\', '/'),
            os.path.join(BASE_DIR,'templates2').replace('\\', '/'),
        ],
        'APP_DIRS': True,
]

静态文件

开发时
1.4在project/urls.py底部加上

from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()

Django 1.5 - Django 1.8不需要添加
settings.py静态文件相关代码

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.8/howto/static-files/
 
STATIC_URL = '/static/'
 
# 当运行 python manage.py collectstatic 的时候
# STATIC_ROOT 文件夹 是用来将所有STATICFILES_DIRS中所有文件夹中的文件,以及各app中static中的文件都复制过来
# 把这些文件放到一起是为了用apache等部署的时候更方便
STATIC_ROOT = os.path.join(BASE_DIR, 'collected_static')
 
# 其它 存放静态文件的文件夹,可以用来存放项目中公用的静态文件,里面不能包含 STATIC_ROOT
# 如果不想用 STATICFILES_DIRS 可以不用,都放在 app 里的 static 中也可以
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "common_static"),
    '/path/to/others/static/',  # 用不到的时候可以不写这一行
)
 
# 这个是默认设置,Django 默认会在 STATICFILES_DIRS中的文件夹 和 各app下的static文件夹中找文件
# 注意有先后顺序,找到了就不再继续找了
STATICFILES_FINDERS = (
    "django.contrib.staticfiles.finders.FileSystemFinder",
    "django.contrib.staticfiles.finders.AppDirectoriesFinder"
)

静态文件放在对应的 app 下的 static 文件夹中 或者 STATICFILES_DIRS 中的文件夹中;
当 DEBUG = True 时,Django 就能自动找到放在里面的静态文件;
Django 通过 STATICFILES_FINDERS 中的“查找器”,找到符合的就停下来;
例子

dj18static
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── static # 应用 blog 下的 static, 默认会找这个文件夹
│   │   └── 【zqxt.png】
│   ├── tests.py
│   │
│   └── views.py
├── common_static # 已经添加到了 STATICFILES_DIRS 的文件夹
│   └── js
│       └── 【jquery.js】
│
├── dj18static
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

当 settings.py 中的 DEBUG = True 时,打开开发服务器 python manage.py runserver 直接访问 /static/zqxt.png 就可以找到这个静态文件;
也可以在 settings.py 中指定所有 app 共用的静态文件,比如 jquery.js 等

STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "common_static"),
)

把 jquery.js 放在 common_static/js/ 下,这样就可以 在 /static/js/jquery.js 中访问到它!
其他,如果静态文件分配多个网址

# static files
import os
from django.conf.urls.static import static
from django.conf import settings
if settings.DEBUG:
    media_root = os.path.join(settings.BASE_DIR,'media2')
    urlpatterns += static('/media2/', document_root=media_root)

或者

from django.conf.urls.static import static
urlpatterns = ...
urlpatterns += static('/media2/', document_root=media_root)

部署时
收集静态文件

python manage.py collectstatic

这一句话就会把以前放在app下static中的静态文件全部拷贝到 settings.py 中设置的 STATIC_ROOT 文件夹中
用 apache2 或 nginx 示例代码

Alias /static/ /path/to/collected_static/
 
<Directory /path/to/collected_static>
    Require all granted
</Directory>

nginx 示例代码

location /media  {
    alias /path/to/project/media;
}
 
location /static {
    alias /path/to/project/collected_static;
}

Apache 完整的示例代码:

<VirtualHost *:80>
        ServerName www.ziqiangxuetang.com
        ServerAlias ziqiangxuetang.com
        ServerAdmin tuweizhong@163.com
 
        Alias /media/ /path/to/media/
        Alias /static/ /path/to/collected_static/
 
        <Directory /path/to/media>
                Require all granted
        </Directory>
 
        <Directory /path/to/collected_static>
                Require all granted
        </Directory>
 
        WSGIScriptAlias / /path/to/prj/prj/wsgi.py
        <Directory /path/to/prj/prj>
        <Files wsgi.py>
                Require all granted
        </Files>
        </Directory>
</VirtualHost>

如何把静态文件放在任意位置呢

<VirtualHost *:80>
    ServerName www.ziqiangxuetang.com
    ServerAdmin tuweizhong@163.com
 
    AliasMatch "(?i)^/(.+)\.ico$" "/path/to/project/$1.ico"
    AliasMatch "(?i)^/(.+)\.js$" "/path/to/project/$1.js"
    AliasMatch "(?i)^/(.+)\.css$" "/path/to/project/$1.css"
    AliasMatch "(?i)^/(.+)\.jpg$" "/path/to/project/$1.jpg"
    AliasMatch "(?i)^/(.+)\.jpeg$" "/path/to/project/$1.jpeg"
    AliasMatch "(?i)^/(.+)\.png$" "/path/to/project/$1.png"
    AliasMatch "(?i)^/(.+)\.gif$" "/path/to/project/$1.gif"
    AliasMatch "(?i)^/(.+)\.xml$" "/path/to/project/$1.xml"
    AliasMatch "(?i)^/(.+)\.xsl$" "/path/to/project/$1.xsl"
    AliasMatch "(?i)^/(.+)\.txt$" "/path/to/project/$1.txt"
    AliasMatch "(?i)^/(.+)\.zip$" "/path/to/project/$1.zip"
    AliasMatch "(?i)^/(.+)\.rar$" "/path/to/project/$1.txt"
 
    <Directory /path/to/project>
        Require all granted
    </Directory>
 
    WSGIScriptAlias / /path/to/project/project/wsgi.py
 
    ErrorLog /path/to/project/error.log
    CustomLog /path/to/project/access.log common
</VirtualHost>
posted @ 2017-01-13 16:32  zhangshihai1232  阅读(145)  评论(0)    收藏  举报