Django 拾遺

1.python_2_unicode_compatible裝飾器html

from django.db import models
from django.utils.encoding import python_2_unicode_compatible

@python_2_unicode_compatible # 當你想支持python2版本的時候才須要這個裝飾器
class Question(models.Model):
    # ...
    def __str__(self):   # 在python2版本中使用的是__unicode__
        return self.question_text

@python_2_unicode_compatible 
class Choice(models.Model):
    # ...
    def __str__(self):
        return self.choice_text

 

2.URLconf的命名空間 app_namepython

現實中很顯然會有5個、10個、更多的app同時存在一個項目中。Django用URL name區分這些app之間的關係數據庫

from django.conf.urls import url
from . import views
app_name = 'polls'  # 關鍵是這行
urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),
    url(r'^(?P<question_id>[0-9]+)/results/$', views.results, name='results'),
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]


<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

 

3.404錯誤錯誤頁django

get_object_or_404() 替代get()
app

get_list_or_404() 替代filter()函數

from django.shortcuts import get_object_or_404, render
from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

4.HttpResponseRedirect 當POST數據處理成功後,建議用此函數;編碼

  reverse 幫助咱們避免在視圖函數中硬編碼URL;url

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from .models import Choice, Question
# ...

def vote(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
        selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
        # 發生choice未找到異常時,從新返回表單頁面,並給出提示信息
        return render(request, 'polls/detail.html', {
        'question': question,
        'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes += 1
        selected_choice.save()
        # 成功處理數據後,自動跳轉到結果頁面,防止用戶連續屢次提交。
# 例如,其中的3是某個的值。重定向後將進入對應的視圖,並將傳遞給它
return HttpResponseRedirect(reverse('polls:results', args=(question.id,))) from django.shortcuts import get_object_or_404, render def results(request, question_id): question = get_object_or_404(Question, pk=question_id) return render(request, 'polls/results.html', {'question': question}) <h1>{{ question.question_text }}</h1> <ul> {% for choice in question.choice_set.all %} <li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li> {% endfor %} </ul> <a href="{% url 'polls:detail' question.id %}">Vote again?</a>'/polls/3/results/'question.idpolls:resultsquestion.id

 

5.查看一個包安裝路徑spa

python -c "import django; print(django.__path__)"

 

6.FileField upload_tocode

# 參數也能夠接收一個回調函數
# 這種回調函數,必須接收兩個參數,而後返回一個Unix風格的路徑字符串。參數表明一個定義了的模型的實例,說白了就是當前數據記錄。是本來的文件名。
def
user_directory_path(instance, filename): #文件上傳到MEDIA_ROOT/user_<id>/<filename>目錄中 return 'user_{0}/{1}'.format(instance.user.id, filename) class MyModel(models.Model): upload = models.FileField(upload_to=user_directory_path) class MyModel(models.Model): # 文件被傳至`MEDIA_ROOT/uploads`目錄,MEDIA_ROOT由你在settings文件中設置 upload = models.FileField(upload_to='uploads/') # 或者 # 被傳到`MEDIA_ROOT/uploads/2015/01/30`目錄,增長了一個時間劃分 upload = models.FileField(upload_to='uploads/%Y/%m/%d/')upload_touser_directory_pathinstaceFileFieldfilename

 

7.遞歸外鍵 self ,典型的例子就是評論系統!一條評論能夠被不少人繼續評論

class Comment(models.Model):
    title = models.CharField(max_length=128)
    text = models.TextField()
    parent_comment = models.ForeignKey('self', on_delete=models.CASCADE)

 

8.on_delete

on_delete
當一個被外鍵關聯的對象被刪除時,Django將模仿on_delete參數定義的SQL約束執行相應操做。好比,你有一個可爲空的外鍵,而且你想讓它在關聯的對象被刪除時,自動設爲null,能夠以下定義:
user = models.ForeignKey(
    User,
    models.SET_NULL,
    blank=True,
    null=True,
)
該參數可選的值都內置在django.db.models中,包括:
    CASCADE:模擬SQL語言中的ON DELETE CASCADE約束,將定義有外鍵的模型對象同時刪除!(該操做爲當前Django版本的默認操做!)
    PROTECT:阻止上面的刪除操做,可是彈出ProtectedError異常
    SET_NULL:將外鍵字段設爲null,只有當字段設置了null=True時,方可以使用該值。
    SET_DEFAULT:將外鍵字段設爲默認值。只有當字段設置了default參數時,方可以使用。
    DO_NOTHING:什麼也不作。
    SET():設置爲一個傳遞給SET()的值或者一個回調函數的返回值。注意大小寫。

 

9.related_query_name

反向關聯查詢名。用於從目標模型反向過濾模型對象的名稱。(過濾和查詢在後續章節會介紹)

class Tag(models.Model):
    article = models.ForeignKey(
        Article,
        on_delete=models.CASCADE,
        related_name="tags",
        related_query_name="tag",       # 注意這一行
    )
    name = models.CharField(max_length=255)

# 如今能夠使用‘tag’做爲查詢名了
Article.objects.filter(tag__name="important")

 

10.through(定義中間表)

若是你想自定義多對多關係的那張額外的關聯表,能夠使用這個參數!參數的值爲一箇中間模型。

最多見的使用場景是你須要爲多對多關係添加額外的數據,好比兩我的創建QQ好友的時間。

一般狀況下,這張表在數據庫內的結構是這個樣子的:

中間表的id列....模型對象的id列.....被關聯對象的id列
# 各行數據

若是自定義中間表並添加時間字段,則在數據庫內的表結構以下:

中間表的id列....模型對象的id列.....被關聯對象的id列.....時間對象列
# 各行數據

看下面的例子:

from django.db import models

class Person(models.Model):
    name = models.CharField(max_length=50)

class Group(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(
        Person,
        through='Membership',       ## 自定義中間表
        through_fields=('group', 'person'),
    )

class Membership(models.Model):  # 這就是具體的中間表模型
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    inviter = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name="membership_invites",
    )
    invite_reason = models.CharField(max_length=64)

上面的代碼中,經過class Membership(models.Model)定義了一個新的模型,用來保存Person和Group模型的多對多關係,而且同時增長了‘邀請人’和‘邀請緣由’的字段。

through參數在某些使用場景中是必須的,相當重要,請務必掌握!

through_fields

接着上面的例子。Membership模型中包含兩個關聯Person的外鍵,Django沒法肯定到底使用哪一個做爲和Group關聯的對象。因此,在這個例子中,必須顯式的指定through_fields參數,用於定義關係。

through_fields參數接收一個二元元組('field1', 'field2'),field1是指向定義有多對多關係的模型的外鍵字段的名稱,這裏是Membership中的‘group’字段(注意大小寫),另一個則是指向目標模型的外鍵字段的名稱,這裏是Membership中的‘person’,而不是‘inviter’。

再通俗的說,就是through_fields參數指定從中間表模型Membership中選擇哪兩個字段,做爲關係鏈接字段。

 

11.自定義錯誤頁面

  • handler400 —— django.conf.urls.handler400。
  • handler403 —— django.conf.urls.handler403。
  • handler404 —— django.conf.urls.handler404。
  • handler500 —— django.conf.urls.handler500。

首先,在根URLconf中額外增長下面的條目:

# 增長的條目
handler400 = views.bad_request
handler403 = views.permission_denied
handler404 = views.page_not_found
handler500 = views.page_error

而後在,views.py文件中增長四個處理視圖:

def page_not_found(request):
    return render(request, '404.html')


def page_error(request):
    return render(request, '500.html')


def permission_denied(request):
    return render(request, '403.html')

def bad_request(request):
    return render(request, '400.html')

注意:setttings 改爲 DEBUG = False ALLOWED_HOSTS = ['*']

 

12.csv文件下載

import csv
from django.http import StreamingHttpResponse
class Echo(object):
    """An object that implements just the write method of the file-like
    interface.
    """
    def write(self, value):
        """Write the value by returning it, instead of storing in a buffer."""
        return value


def some_view(request):
    # # Create the HttpResponse object with the appropriate CSV header.
    response = HttpResponse(content_type='text/csv')
    response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'

    writer = csv.writer(response)
    writer.writerow(['First row', 'Second row', 'Third row', 'Fourth row'])
    rows = (["Row {}".format(idx), str(idx + 10), str(idx + 20), str(idx + 30)] for idx in range(65536))
    for row in rows:
        writer.writerow(row)
    return response


    # rows = (["Row {}".format(idx), str(idx+10),str(idx+20),str(idx+30)] for idx in range(65536))
    # pseudo_buffer = Echo()
    # writer = csv.writer(pseudo_buffer)
    # response = StreamingHttpResponse((writer.writerow(['First row', 'Second row', 'Third row', 'Fourth row'])),
    #                                  content_type="text/csv")
    # response = StreamingHttpResponse((writer.writerow(row) for row in rows),
    #                                  content_type="text/csv")
    # response['Content-Disposition'] = 'attachment; filename="somefilename.csv"'
    # return response

 

13.

 

 

 

 

 

CP: http://www.liujiangblog.com/course/django/96

相關文章
相關標籤/搜索