django配置与使用

在配置Django的时候常常会出现一些问题,比如migrate无效,表单提交valid验证不过等问题,本文给出了一些解决方案

同步数据库的问题

根据不同版本有对应以下两种方法同步数据库:

1
python manage.py syncdb

(用于旧版本)

1
2
python manage.py makemigration
python manage.py migrate

(用于新版本)
其中migrate方法一般要提前建一个空的数据库,但是数据表是自动同步的

自定义数据表

一般地,django在数据库中存储的表名为model name,但是可以通过以下方式自定义表名

1
2
3
class MyModel(models.Model):
class Meta:
db_table = 'xxx'

上传文件问题

  • 上传空文件会导致is_valid不过
  • 不能在如view.py, model.py中正常地import
    这些文件的sys.path中的当前目录是manage.py所在目录,一般比这些文件本身所在的目录高一级。所以sys.path.append中的路径应当比实际高一层。
    同样因为这个原因,保存文件时路径不能以’/upload/‘开头,而应该直接以’upload/‘开头。在外部程序访问时,应当做一个路径转化。

Migrate问题

  • RuntimeError: Error creating new content types. Please make sure contenttypes is migrated before trying to migrate apps individually.
    检查Model.py
    ContentType 模型对应数据库中django_content_type表,主要用户维护django project中所安装的所有用户模型
    出现这个问题一定是模型问题,我后来发现我的原因是因为 models.XXXField 里面多了一些参数比如required什么的删掉就好,此外form也要注意
    之后一定要先drop database再migrate就可以了

  • file clean之后变成None
    摘自C:\Program Files (x86)\Python27\Lib\site-packages\Django-1.9-py2.7.egg\django\forms\forms.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    def full_clean(self):
    """
    Cleans all of self.data and populates self._errors and
    self.cleaned_data.
    """
    self._errors = ErrorDict()
    if not self.is_bound: # Stop further processing.
    return
    self.cleaned_data = {}
    # If the form is permitted to be empty, and none of the form data has
    # changed from the initial data, short circuit any validation.
    if self.empty_permitted and not self.has_changed():
    return

    self._clean_fields()
    self._clean_form()
    self._post_clean()

    def _clean_fields(self):
    for name, field in self.fields.items():
    # value_from_datadict() gets the data from the data dictionaries.
    # Each widget type knows how to retrieve its own data, because some
    # widgets split data over several HTML fields.
    if field.disabled:
    value = self.initial.get(name, field.initial)
    else:
    value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
    try:
    if isinstance(field, FileField):
    initial = self.initial.get(name, field.initial)
    value = field.clean(value, initial)
    else:
    value = field.clean(value)
    self.cleaned_data[name] = value
    if hasattr(self, 'clean_%s' % name):
    value = getattr(self, 'clean_%s' % name)()
    self.cleaned_data[name] = value
    except ValidationError as e:
    self.add_error(name, e)

    def _clean_form(self):
    try:
    cleaned_data = self.clean()
    except ValidationError as e:
    self.add_error(None, e)
    else:
    if cleaned_data is not None:
    self.cleaned_data = cleaned_data

    看了半天源码发现,

    里面的name要和Form里面的name相同

python的小坑

python是没有select/switch语句的,为了避免很麻烦的if-elif-else,可以采用{condition:value}[statement]近似替代select/switch语句,这个小坑在于,所有的condition:value都会被求值,所以一方面会降低性能,一方面要考虑副作用的问题了。

字符集的小坑

request.GET.get得到的参数是unicode,必须先转换类型才能使用哦

HttpResponse的小坑

HttpResponse不能正确处理array object的情况,例如下面的代码是不能得到正确的结果的哦:

1
2
3
4
5
6
7
8
9
return HttpResponse([
{'name':'TP', 'value':assessmodel.TP}
,{'name':'TN', 'value':assessmodel.TN}
,{'name':'FP', 'value':assessmodel.FP}
,{'name':'FN', 'value':assessmodel.FN}
,{'name':'P', 'value':assessmodel.P}
,{'name':'R', 'value':assessmodel.R}
,{'name':'F1', 'value':assessmodel.F1}
])

运行发现前端得到的是这样的数据:

解决方案是当遇到对象数组的时候使用json.dump()函数将它转化为json,然后返回application/json格式的HttpResponse,如return HttpResponse(json_stuff, content_type ="application/json"),当然千万注意前端ajax拿到data之后就不要eval了。

转义

Django和Angular等框架合用需要注意转义:
openblock { %
closeblock % }
templatetag openvariable { {
templatetag closevariable } }
openbrace {
closebrace }
opencomment { #
closecomment # }

Angular的问题

这边顺便说一下Angular和jQuery混合使用常犯的一个错误:

1
2
3
4
5
6
7
8
9
10
$.ajax({
url : ''
,data : {

}
,async : true
,success : function (data, textStatus) {
$scope.data = data
}
})

如上代码$scope是不能更新的,因为success函数不在angular的名字空间里面了。

Python urllib2的问题

使用以下代码抓取网页

1
2
3
4
5
6
def getHtml(url):
req = urllib2.Request(url)
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.2; rv:16.0) Gecko/20100101 Firefox/16.0')
page = urllib2.urlopen(req)
html = page.read()
return html

发现报502错,这时候检查一下自己的翻墙软件是不是全局代理,这边我的Shadowsocks开启了全局代理,urllib2就不能抓https://127.0.0.1:8091了,502报错

1
urllib2.HTTPError: HTTP Error 502: Server dropped connection

Django + Nginx + Https

这里有一个非常大的坑,如果使用本机调试的话,千万不要选择localhost,而应该选择127.0.0.1.
因为localhost可以是[::1]也可以是127.0.0.1,详见 这里这里
如果使用了localhost,那么会造成1min左右的加载问题,最初我以为是static files的问题,后来查看了error发现是 *24 upstream timed out (10060: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond) while connecting to upstream, client: 127.0.0.1, server: localhost ,这种问题一般都是写了localhost。
–推荐以下blog

http://www.ziqiangxuetang.com/django/django-models.html