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[0-9]+)/$', views.detail, name='detail'),其中用括号括器的(?P[0-9]+)会做为参数传给 views.detail这个函数,这个函数也要接受这个参数做下一步处理,可以去掉?P,这只是为了起说明作用和提前命名,也可以在 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,尽量不要硬编码,

  • {{ question.question_text }}
  • 这样的硬编码在改动 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
    
    
  • {{ question.question_text }}
  • {{ question.question_text }}
  • 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[0-9]+)/$', views.DetailView.as_view(), name='detail'),
        url(r'^(?P[0-9]+)/results/$', views.ResultsView.as_view(), name='results'),
        url(r'^(?P[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'],
                ['']
            )
    
    断言介绍
    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 %}
    
    

    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'] 添加后台对指定字段的搜索功能

    你可能感兴趣的:(django复习笔记(Part1-Part7))