django复习笔记(Part1-Part7)

对 django 官网 First steps 中 7 个入门教程的复习,复习时 django 版本为 1.11。

tutorial01

1、每一个新建的 app 都应再新建一个 urls.py 文件, 管理其目录下的 views.py,在 mysite/urls.py 文件中使用 include() 方法引用 app 里的 urls;

2、urls.py 文件里的 url() 方法可以传四个参数,两个为必须,两个可选:

四个参数
url() argument:regex 正则表达式(必须)
url() argument:view views.py 中的方法(必须)
url() argument:kwargs 可以传入views.py 中的方法的字典(可选)
url() argument:name 用于给 html 页面的链接命名(可选)

tutorial02

1、models.py 可以定义任何数据模型,模型之中可以定义自己的方法或者官方自带的方法,在用此模型的时候可以调用这些添加的方法,方面理解:

class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')

    def __str__(self):  # 自带方法
        return self.question_text

    def was_published_recently(self): # 自定义方法
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

2、每次修改 models.py 里的数据模型,需要运行两个命令:
python manage.py makemigrations polls 迁移改变
python manage.py migrate 应用到数据库
其他命令:
python manage.py sqlmigrate polls 0001 查看此次迁移 sql 语法python manage.py shell 在命令行里调试数据模型​

tutorial03

1、在 urls.py 中,url(r'^(?P<question_id>[0-9]+)/$', views.detail, name='detail'),其中用括号括器的(?P<question_id>[0-9]+)会做为参数传给 views.detail这个函数,这个函数也要接受这个参数做下一步处理,可以去掉?P<question_id>,这只是为了起说明作用和提前命名,也可以在 views.detail 方法中命名;

2、views.py 中,用get_object_or_404()函数代替try···except更好,在找不到相关数据时 Django 会自动引起 Http404 错误:

# 用 try···except 查询数据
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

# 用 get_object_or_404() 查询数据
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

3、模板中使用 url,尽量不要硬编码,<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>这样的硬编码在改动 urls.py 会很费劲,正确方法是用命名空间,在多个 app 中,可能出现很多同名的 name,这很难记忆,为每一个 app 设置一个 app_name,在搭配url(r'^$', views.index, name='index')中的name,即可在改变 url 路径时不必一改全改,也方便记忆和使用:

# app/urls.py
app_name = 'polls'   # 在每一个 app 的 urls.py 下设置
urlpatterns = [
    url(r'^$', views.index, name='index'),
]
# templates/name.html
<!-- 硬编码方式 -->
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li> 

<!-- 更好的编码方式 -->
<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li> 

tutorial04

1、表单提交,如某项数据需要+1,多人同时提交时,可能会出现数据丢失,通常的代码将这个值从数据库取出来赋值给一个变量,然后执行+1操作,然后再将这个+1后的值保存会数据库,这就可能会出现数据遗漏,更有效的做法是使用 F() 函数,这个函数对数据库直接进行+1操作,而不用通过变量赋值存储:

# 有可能会出现数据遗漏的代码操作,有 Question和Choice 模型
selected_choice = question.choice_set.get(pk=request.POST['choice'])
selected_choice.votes += 1
selected_choice.save()

# 更有效的数据+1操作方法,使用 F() 函数
Choice.objects.filter(votes='hello').update(votes=F('votes')+1)

2、类的通用视图,Less code is better。在 views.py 中,初学 django 时直接用了很多函数来处理每个模板和数据,这种方法也可行,但 django 提供了通用视图使代码更简洁更友好;

# urls.py     通用视图默认变量为pk,所以使用pk
from django.views.generic import TemplateView
urlpatterns = [
    url(r'^$', views.IndexView.as_view(), name='index'),
    url(r'^(?P<pk>[0-9]+)/$', views.DetailView.as_view(), name='detail'),
    url(r'^(?P<pk>[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
    url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
    url(r'^about/$', TemplateView.as_view(template_name="about.html")),# 没有数据查询时可以直接返回模板,这是一种简写方式
]
# views.py
def index():   # 普通函数,与通用视图对比
     latest_question_list = Question.objects.order_by('-pub_date')[:5]
     context = {
         'latest_question_list': latest_question_list,
     }
     return render(request, 'polls/index.html', context)

class IndexView(generic.ListView): #通用视图
    template_name = 'polls/index.html' #指定渲染的模板
    context_object_name = 'latest_question_list' #模板中的变量名,类似 context 上下文 
    def get_queryset(self): # 重写 ListView 方法,查询数据
        """Return the last five published questions."""
        return Question.objects.order_by('-pub_date')[:5]
      
class DetailView(generic.DetailView):# DetailView
    model = Question   # 指定要查询的数据模型
    template_name = 'polls/detail.html' # 指定渲染模板

    
class ResultsView(generic.DetailView):
    model = Question 
    template_name = 'polls/results.html

通用视图除了可以查询指定模型、渲染指定模板外(像上面那样,使用指定参数),还可以添加额外的上下文(也就是context),只需重写 get_context_data() 方法:

class PublisherDetail(DetailView):
    model = Publisher
    def get_context_data(self, **kwargs):  
           context = super(PublisherDetail, self).get_context_data(**kwargs)
          # Add in a QuerySet of all the books
           context['book_list'] = Book.objects.all()
           return context
常用字段解释
context_object_name 指定模板内的变量名,默认为 object_list
model 要查询的模型名称 (简写)
query 是上面的完全写法 ,不一定是 all(),也可以是其他,filter() 等
template_name 指定渲染哪一个模板
常用方法解释
get_queryset(self) 模型查询处理
get_context_data(self, **kwargs) 添加额外上下文

tutorial05

1、自动化测试可以发现工程中隐藏的 bug,可以优化代码、保证项目的安全。在每个 app 下都有一个 tests.py 文件用来测试所在 app 是否有 bug,测试方法以 test 开头类以 Tests 结尾

# app/tests.py
import datetime
from django.test import TestCase # 用于测试的工具
from django.urls import reverse
from django.utils import timezone
from .models import Question

class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
        time = timezone.now() + datetime.timedelta(days=30)
        future_question = Question(pub_date=time)
        self.assertIs(future_question.was_published_recently(), False)
        
class QuestionIndexViewTests(TestCase):
    def test_no_questions(self):
        response = self.client.get(reverse('polls:index'))
        self.assertEqual(response.status_code, 200)
        self.assertContains(response, 'no polls are available')
        self.assertQuerysetEqual(response.context['latest_question_list'], [])

    def test_past_question(self):
        create_question(question_text='Past question.', days=-30)
        response = self.client.get(reverse('polls:index'))
        self.assertQuerysetEqual(
            response.context['latest_question_list'],
            ['<Question: Past question.>']
        )
断言介绍
assertIs 判断真假
assertEqual 判断是否相等
assertContains 内容是否包含在内
assertQuerysetEqual Queryset是否相等

tutorial06

1、添加静态文件支持,根目录下新建 static 文件夹管理 css、js、image 资源,在 settings.py 文件中设置 STATIC_URLSTATICFILES_DIRS,django 会自动搜寻 INSTALLED_APPS 下的 app 并找到 static 文件夹:

# settings.py
STATIC_URL = '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "static")
]

编写 css 文件:

/* style.css */
li a {
    color: green;
}
body {
    background: white url("images/background.gif") no-repeat right bottom;
}

html 中引用:

{# index.html #}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}" />

tutorial07

1、后台管理优化,可以在后台帮助数据模型显示详情信息:

字段解释
fields fields = ['pub_date', 'question_text'] 设置模型中字段的顺序及是否显示
fieldsets fieldsets = [ (None, {'fields': ['question_text']}), ('Date information', {'fields': ['pub_date']}), ] 将模型中的每个字段分栏
inlines inlines = [ChoiceInline] 将有关联的模型引入,可直接操作该引入模型
list_display list_display = ('question_text', 'pub_date') 模型列表详情
search_fields search_fields = ['question_text'] 添加后台对指定字段的搜索功能
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容