1. 爲何要作先後端分離? - 先後端交給不一樣的人來編寫,職責劃分明確。 - API (IOS,安卓,PC,微信小程序...) - vue.js等框架編寫前端時,會比以前寫jQuery更簡單快捷。 2. 簡述http協議? - 基於socket - 數據格式: "GET /index?name=123&age=19 http1.1\r\nhost:www.luffyciti.com\r\ncontent-type:application/json...\r\n\r\n" "POST /index http1.1\r\nhost:www.luffyciti.com\r\ncontent-type:application/json...\r\n\r\n{name:'alex',age:18}" "POST /index http1.1\r\nhost:www.luffyciti.com\r\ncontent-type:application/enform.....\r\n\r\nname=alex&age=18&xx=19" - 無狀態短連接 一次請求一次響應以後斷開鏈接 3. 簡述restful 規範? https://www.luffycity.com/api/v1/courses/?sub_category=0 https://www.luffycity.com/api/v1/courses/?sub_category=0 看上面一段url,能夠說出5個 1. 使用https代替http 2.在URL中體現本身寫的是API 3. 在URL中體現版本 4. 使用名詞 5.參數要合理 以後,請求方式,響應信息。能夠說後面5個 6. 根據請求方式不一樣,處理不一樣的操做 7.返回狀態碼 8.返回錯誤信息 9. 返回code 10.hyper link(超連接) 4. django rest framework組件的做用? - 快速實現符合restful 規範的api 5. 列舉django rest framework組件(10個)? - 版本 - 權限 - 認證 - 節流 - 分頁 - 解析器 - 序列化 - 視圖 - 路由 - 渲染器 6. 路飛的表結構 a. 課程分類 - 課程大類 - 課程子類 b. 學位課 - 學位課 - 獎學金 - 老師 c. 專題課 or 學位課模塊 - 專題課 or 學位課模塊 - 課程詳細 - 課程大綱 - 常見問題 - 章節 - 課時 - 做業 d. 價格 - 價格策略 7. django contenttypes組件的做用? 爲了解決一張表和多個表作外鍵關聯
上面都是面試題css
列舉django rest framework的10個組件,能夠根據django請求生命週期來記html
1. 請求路徑包含版本,請求先到達路由,2.進入組件。認證,權限,節流。3.到達視圖,獲取參數,使用解析器。4.獲取數據庫記錄,作序列化返回。
5.數據太多,要作分頁,返回給用戶以後,要作渲染,利用渲染器。前端
下面代碼:
https://github.com/987334176/luffycity/archive/v1.zipvue
修改models.pypython
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.utils.safestring import mark_safe from django.db import models import hashlib # ######################## 課程相關 ######################## class CourseCategory(models.Model): """課程大類, e.g 前端 後端...""" name = models.CharField(max_length=64, unique=True) def __str__(self): return "%s" % self.name class Meta: verbose_name_plural = "01.課程大類" class CourseSubCategory(models.Model): """課程子類, e.g python linux """ category = models.ForeignKey("CourseCategory") name = models.CharField(max_length=64, unique=True) def __str__(self): return "%s" % self.name class Meta: verbose_name_plural = "02.課程子類" class DegreeCourse(models.Model): """學位課程""" name = models.CharField(max_length=128, unique=True) course_img = models.CharField(max_length=255, verbose_name="縮略圖") brief = models.TextField(verbose_name="學位課程簡介", ) total_scholarship = models.PositiveIntegerField(verbose_name="總獎學金(貝里)", default=40000) # 2000 2000 mentor_compensation_bonus = models.PositiveIntegerField(verbose_name="本課程的導師輔導費用(貝里)", default=15000) period = models.PositiveIntegerField(verbose_name="建議學習週期(days)", default=150) # 爲了計算學位獎學金 prerequisite = models.TextField(verbose_name="課程先修要求", max_length=1024) teachers = models.ManyToManyField("Teacher", verbose_name="課程講師") # 用於GenericForeignKey反向查詢, 不會生成表字段,切勿刪除 # coupon = GenericRelation("Coupon") # 用於GenericForeignKey反向查詢,不會生成表字段,切勿刪除 degreecourse_price_policy = GenericRelation("PricePolicy") def __str__(self): return self.name class Meta: verbose_name_plural = "03.學位課" class Teacher(models.Model): """講師、導師表""" name = models.CharField(max_length=32) role_choices = ((0, '講師'), (1, '導師')) role = models.SmallIntegerField(choices=role_choices, default=0) title = models.CharField(max_length=64, verbose_name="職位、職稱") signature = models.CharField(max_length=255, help_text="導師簽名", blank=True, null=True) image = models.CharField(max_length=128) brief = models.TextField(max_length=1024) def __str__(self): return self.name class Meta: verbose_name_plural = "04.導師或講師" class Scholarship(models.Model): """學位課程獎學金""" degree_course = models.ForeignKey("DegreeCourse") time_percent = models.PositiveSmallIntegerField(verbose_name="獎勵檔位(時間百分比)", help_text="只填百分值,如80,表明80%") value = models.PositiveIntegerField(verbose_name="獎學金數額") def __str__(self): return "%s:%s" % (self.degree_course, self.value) class Meta: verbose_name_plural = "05.學位課獎學金" class Course(models.Model): """專題課/學位課模塊表""" name = models.CharField(max_length=128, unique=True) course_img = models.CharField(max_length=255) sub_category = models.ForeignKey("CourseSubCategory") course_type_choices = ((0, '付費'), (1, 'VIP專享'), (2, '學位課程')) course_type = models.SmallIntegerField(choices=course_type_choices) # 不爲空;學位課的某個模塊 # 爲空;專題課 degree_course = models.ForeignKey("DegreeCourse", blank=True, null=True, help_text="如果學位課程,此處關聯學位表") brief = models.TextField(verbose_name="課程概述", max_length=2048) level_choices = ((0, '初級'), (1, '中級'), (2, '高級')) level = models.SmallIntegerField(choices=level_choices, default=1) pub_date = models.DateField(verbose_name="發佈日期", blank=True, null=True) period = models.PositiveIntegerField(verbose_name="建議學習週期(days)", default=7) # order = models.IntegerField("課程順序", help_text="從上一個課程數字日後排") attachment_path = models.CharField(max_length=128, verbose_name="課件路徑", blank=True, null=True) status_choices = ((0, '上線'), (1, '下線'), (2, '預上線')) status = models.SmallIntegerField(choices=status_choices, default=0) template_id = models.SmallIntegerField("前端模板id", default=1) # coupon = GenericRelation("Coupon") # 用於GenericForeignKey反向查詢,不會生成表字段,切勿刪除 price_policy = GenericRelation("PricePolicy") asked_question = GenericRelation("OftenAskedQuestion") def __str__(self): return "%s(%s)" % (self.name, self.get_course_type_display()) def save(self, *args, **kwargs): if self.course_type == 2: if not self.degree_course: raise ValueError("學位課程必須關聯對應的學位表") super(Course, self).save(*args, **kwargs) class Meta: verbose_name_plural = "06.專題課或學位課模塊" class CourseDetail(models.Model): """課程詳情頁內容""" course = models.OneToOneField("Course") hours = models.IntegerField("課時") course_slogan = models.CharField(max_length=125, blank=True, null=True) video_brief_link = models.CharField(verbose_name='課程介紹', max_length=255, blank=True, null=True) why_study = models.TextField(verbose_name="爲何學習這門課程") what_to_study_brief = models.TextField(verbose_name="我將學到哪些內容") career_improvement = models.TextField(verbose_name="此項目如何有助於個人職業生涯") prerequisite = models.TextField(verbose_name="課程先修要求", max_length=1024) recommend_courses = models.ManyToManyField("Course", related_name="recommend_by", blank=True) teachers = models.ManyToManyField("Teacher", verbose_name="課程講師") def __str__(self): return "%s" % self.course class Meta: verbose_name_plural = "07.課程或學位模塊詳細" class OftenAskedQuestion(models.Model): """常見問題""" content_type = models.ForeignKey(ContentType) # 關聯course or degree_course object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') question = models.CharField(max_length=255) answer = models.TextField(max_length=1024) def __str__(self): return "%s-%s" % (self.content_object, self.question) class Meta: unique_together = ('content_type', 'object_id', 'question') verbose_name_plural = "08. 常見問題" class CourseOutline(models.Model): """課程大綱""" course_detail = models.ForeignKey("CourseDetail") title = models.CharField(max_length=128) # 前端顯示順序 order = models.PositiveSmallIntegerField(default=1) content = models.TextField("內容", max_length=2048) def __str__(self): return "%s" % self.title class Meta: unique_together = ('course_detail', 'title') verbose_name_plural = "09. 課程大綱" class CourseChapter(models.Model): """課程章節""" course = models.ForeignKey("Course") chapter = models.SmallIntegerField(verbose_name="第幾章", default=1) name = models.CharField(max_length=128) summary = models.TextField(verbose_name="章節介紹", blank=True, null=True) pub_date = models.DateField(verbose_name="發佈日期", auto_now_add=True) class Meta: unique_together = ("course", 'chapter') verbose_name_plural = "10. 課程章節" def __str__(self): return "%s:(第%s章)%s" % (self.course, self.chapter, self.name) class CourseSection(models.Model): """課時目錄""" chapter = models.ForeignKey("CourseChapter") name = models.CharField(max_length=128) order = models.PositiveSmallIntegerField(verbose_name="課時排序", help_text="建議每一個課時之間空1至2個值,以備後續插入課時") section_type_choices = ((0, '文檔'), (1, '練習'), (2, '視頻')) section_type = models.SmallIntegerField(default=2, choices=section_type_choices) section_link = models.CharField(max_length=255, blank=True, null=True, help_text="如果video,填vid,如果文檔,填link") video_time = models.CharField(verbose_name="視頻時長", blank=True, null=True, max_length=32) # 僅在前端展現使用 pub_date = models.DateTimeField(verbose_name="發佈時間", auto_now_add=True) free_trail = models.BooleanField("是否可試看", default=False) class Meta: unique_together = ('chapter', 'section_link') verbose_name_plural = "11. 課時" def __str__(self): return "%s-%s" % (self.chapter, self.name) class Homework(models.Model): chapter = models.ForeignKey("CourseChapter") title = models.CharField(max_length=128, verbose_name="做業題目") order = models.PositiveSmallIntegerField("做業順序", help_text="同一課程的每一個做業以前的order值間隔1-2個數") homework_type_choices = ((0, '做業'), (1, '模塊通關考覈')) homework_type = models.SmallIntegerField(choices=homework_type_choices, default=0) requirement = models.TextField(max_length=1024, verbose_name="做業需求") threshold = models.TextField(max_length=1024, verbose_name="踩分點") recommend_period = models.PositiveSmallIntegerField("推薦完成周期(天)", default=7) scholarship_value = models.PositiveSmallIntegerField("爲該做業分配的獎學金(貝里)") note = models.TextField(blank=True, null=True) enabled = models.BooleanField(default=True, help_text="本做業若是後期不須要了,不想讓學員看到,能夠設置爲False") class Meta: unique_together = ("chapter", "title") verbose_name_plural = "12. 章節做業" def __str__(self): return "%s - %s" % (self.chapter, self.title) # class CourseReview(models.Model): # """課程評價""" # enrolled_course = models.OneToOneField("EnrolledCourse") # about_teacher = models.FloatField(default=0, verbose_name="講師講解是否清晰") # about_video = models.FloatField(default=0, verbose_name="內容實用") # about_course = models.FloatField(default=0, verbose_name="課程內容通俗易懂") # review = models.TextField(max_length=1024, verbose_name="評價") # disagree_number = models.IntegerField(default=0, verbose_name="踩") # agree_number = models.IntegerField(default=0, verbose_name="贊同數") # tags = models.ManyToManyField("Tags", blank=True, verbose_name="標籤") # date = models.DateTimeField(auto_now_add=True, verbose_name="評價日期") # is_recommend = models.BooleanField("熱評推薦", default=False) # hide = models.BooleanField("不在前端頁面顯示此條評價", default=False) # # def __str__(self): # return "%s-%s" % (self.enrolled_course.course, self.review) # # class Meta: # verbose_name_plural = "13. 課程評價(購買課程後才能評價)" # # # class DegreeCourseReview(models.Model): # """學位課程評價 # 爲了之後能夠定製單獨的評價內容,因此不與普通課程的評價混在一塊兒,單獨建表 # """ # enrolled_course = models.ForeignKey("EnrolledDegreeCourse") # course = models.ForeignKey("Course", verbose_name="評價學位模塊", blank=True, null=True, # help_text="不填寫即表明評價整個學位課程", limit_choices_to={'course_type': 2}) # about_teacher = models.FloatField(default=0, verbose_name="講師講解是否清晰") # about_video = models.FloatField(default=0, verbose_name="視頻質量") # about_course = models.FloatField(default=0, verbose_name="課程") # review = models.TextField(max_length=1024, verbose_name="評價") # disagree_number = models.IntegerField(default=0, verbose_name="踩") # agree_number = models.IntegerField(default=0, verbose_name="贊同數") # tags = models.ManyToManyField("Tags", blank=True, verbose_name="標籤") # date = models.DateTimeField(auto_now_add=True, verbose_name="評價日期") # is_recommend = models.BooleanField("熱評推薦", default=False) # hide = models.BooleanField("不在前端頁面顯示此條評價", default=False) # # def __str__(self): # return "%s-%s" % (self.enrolled_course, self.review) # # class Meta: # verbose_name_plural = "14. 學位課評價(購買課程後才能評價)" class PricePolicy(models.Model): """價格與有課程效期表""" content_type = models.ForeignKey(ContentType) # 關聯course or degree_course object_id = models.PositiveIntegerField() content_object = GenericForeignKey('content_type', 'object_id') # course = models.ForeignKey("Course") valid_period_choices = ((1, '1天'), (3, '3天'), (7, '1周'), (14, '2周'), (30, '1個月'), (60, '2個月'), (90, '3個月'), (180, '6個月'), (210, '12個月'), (540, '18個月'), (720, '24個月'), ) valid_period = models.SmallIntegerField(choices=valid_period_choices) price = models.FloatField() class Meta: unique_together = ("content_type", 'object_id', "valid_period") verbose_name_plural = "15. 價格策略" def __str__(self): return "%s(%s)%s" % (self.content_object, self.get_valid_period_display(), self.price)
下載數據庫使用(務必下載,上面的壓縮包數據庫是空的!!!)linux
https://github.com/987334176/luffycity/blob/master/db.sqlite3webpack
修改api應用下的api_urls.pyios
from django.conf.urls import url from api import views urlpatterns = [ url(r'index/$', views.CheckView.as_view()), ]
查看全部學位課並打印學位課名稱以及授課老師git
修改api應用下的views.pygithub
from django.shortcuts import render,HttpResponse from api import models from django.views import View # Create your views here. class CheckView(View): """ 練習題相關 """ def get(self, request): # a.查看全部學位課並打印學位課名稱以及授課老師 degree_list = models.DegreeCourse.objects.all().values('name', 'teachers__name') print(degree_list) return HttpResponse('ok')
訪問網頁:http://127.0.0.1:8000/api/index/
查看控制檯輸出:
<QuerySet [{'teachers__name': '李泳誼', 'name': 'Linux自動化運維 · 中級'}, {'teachers__name': 'Alex 金角大王', 'name': 'Python全棧開發 · 中級'}]>
第二種寫法:
class CheckView(View): """ 練習題相關 """ def get(self, request): # a.查看全部學位課並打印學位課名稱以及授課老師 queryset = models.DegreeCourse.objects.all() for row in queryset: print(row.name,row.teachers.all()) return HttpResponse('ok')
查看控制檯輸出:
<QuerySet [{'teachers__name': '李泳誼', 'name': 'Linux自動化運維 · 中級'}, {'teachers__name': 'Alex 金角大王', 'name': 'Python全棧開發 · 中級'}]>
查看全部學位課並打印學位課名稱以及學位課的獎學金
class CheckView(View): """ 練習題相關 """ def get(self, request): # b.查看全部學位課並打印學位課名稱以及學位課的獎學金 c_obj=models.DegreeCourse.objects.all() for i in c_obj: # 利用degreecourse_price_policy字段進行反向查詢 print(i.name,i.degreecourse_price_policy.all().values('price')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
Python全棧開發 · 中級 <QuerySet [{'price': 10.0}]> Linux自動化運維 · 中級 <QuerySet [{'price': 50.0}]>
第二種寫法:
class CheckView(View): """ 練習題相關 """ def get(self, request): # b.查看全部學位課並打印學位課名稱以及學位課的獎學金 degree_list = models.DegreeCourse.objects.all() for row in degree_list: print(row.name) scholarships = row.scholarship_set.all() for item in scholarships: print('------>',item.time_percent,item.value)
執行輸出:
Python全棧開發 · 中級 ------> 50 1000 Linux自動化運維 · 中級 ------> 50 1000
展現全部的專題課
class CheckView(View): """ 練習題相關 """ def get(self, request): # c. 展現全部的專題課 c_obj = models.Course.objects.filter(degree_course__isnull=True) print(c_obj) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [<Course: Linux基礎(付費)>]>
查看id=1的學位課對應的全部模塊名稱
class CheckView(View): """ 練習題相關 """ def get(self, request): # d. 查看id=1的學位課對應的全部模塊名稱 obj = models.DegreeCourse.objects.filter(id=1).values('course__name') print(obj) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [<Course: Linux基礎(付費)>]>
獲取id = 1的專題課,並打印:課程名、級別(中文)、why_study、what_to_study_brief、全部recommend_courses
class CheckView(View): """ 練習題相關 """ def get(self, request): # e. 獲取id = 1的專題課,並打印:課程名、級別(中文)、why_study、what_to_study_brief、全部recommend_courses c_obj = models.Course.objects.filter(id=1) print(c_obj.values('name')) print(c_obj.first().get_level_display()) print(c_obj.values('coursedetail__why_study')) print(c_obj.values('coursedetail__what_to_study_brief')) print(c_obj.values('coursedetail__recommend_courses')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [{'name': 'Python開發入門7天特訓營'}]> 初級 <QuerySet [{'coursedetail__why_study': '適合零基礎學編程的小白,語言簡潔高效,爲進入人工智能、數據分析和網站開發作好準備;若是你準備敲下你人生的第一行代碼、寫出你的第一個程序,路飛學城的入門特訓營會是最好的選擇'}]> <QuerySet [{'coursedetail__what_to_study_brief': '一、Python如何才能掌握真正的要領;\r\n二、看完理論課程本身怎麼開始動手寫出代碼;\r\n三、什麼纔是專業的代碼;\r\n四、最流行Python編程工具使用技巧;\r\n五、如何系統且高效的學習Python,遇到問題該如何入手分析\r\n六、能夠自主開發各類小程序(如分數打印、猜年齡、用戶登陸程序、三級菜單等)'}]> <QuerySet [{'coursedetail__recommend_courses': 1}]>
第二種寫法:
Python開發入門7天特訓營 適合零基礎學編程的小白,語言簡潔高效,爲進入人工智能、數據分析和網站開發作好準備;若是你準備敲下你人生的第一行代碼、寫出你的第一個程序,路飛學城的入門特訓營會是最好的選擇 初級 7 適合零基礎學編程的小白,語言簡潔高效,爲進入人工智能、數據分析和網站開發作好準備;若是你準備敲下你人生的第一行代碼、寫出你的第一個程序,路飛學城的入門特訓營會是最好的選擇 <QuerySet [<Course: Python開發入門7天特訓營(付費)>]>
刷新網頁,查看控制檯輸出:
Python開發入門7天特訓營 適合零基礎學編程的小白,語言簡潔高效,爲進入人工智能、數據分析和網站開發作好準備;若是你準備敲下你人生的第一行代碼、寫出你的第一個程序,路飛學城的入門特訓營會是最好的選擇 初級 7 適合零基礎學編程的小白,語言簡潔高效,爲進入人工智能、數據分析和網站開發作好準備;若是你準備敲下你人生的第一行代碼、寫出你的第一個程序,路飛學城的入門特訓營會是最好的選擇 <QuerySet [<Course: Python開發入門7天特訓營(付費)>]>
注意:顯示choices的中文,使用get_字段名_display() 就能夠了!
獲取id = 1的專題課,並打印該課程相關的全部常見問題
class CheckView(View): """ 練習題相關 """ def get(self, request): # f. 獲取id = 1的專題課,並打印該課程相關的全部常見問題 c_obj = models.Course.objects.filter(id=1).first() # 利用asked_question字段進行反向查詢 print(c_obj.asked_question.all().values('question')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [{'question': '我是零基礎,能學會嗎?'}, {'question': '須要學習多長時間?'}]>
第二種寫法:
class CheckView(View): """ 練習題相關 """ def get(self, request): # f. 獲取id = 1的專題課,並打印該課程相關的全部常見問題 obj = models.Course.objects.get(id=1) ask_list = obj.asked_question.all() for item in ask_list: print(item.question) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
我是零基礎,能學會嗎?
須要學習多長時間?
獲取id = 1的專題課,並打印該課程相關的課程大綱
class CheckView(View): """ 練習題相關 """ def get(self, request): # g.獲取id = 1的專題課,並打印該課程相關的課程大綱 c_obj = models.Course.objects.filter(id=1) print(c_obj.values('coursedetail__courseoutline__title')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [{'coursedetail__courseoutline__title': 'Python基礎知識'}, {'coursedetail__courseoutline__title': 'Python數據類型初識'}]>
第二種寫法:
class CheckView(View): """ 練習題相關 """ def get(self, request): # g.獲取id = 1的專題課,並打印該課程相關的課程大綱 obj = models.Course.objects.get(id=1) outline_list = obj.coursedetail.courseoutline_set.all() for item in outline_list: print(item.title,item.content) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
Python基礎知識 Python基礎知識、開營直播課
Python數據類型初識 Python數據類型初識、流程控制
獲取id = 1的專題課,並打印該課程相關的全部章節
class CheckView(View): """ 練習題相關 """ def get(self, request): # h.獲取id = 1的專題課,並打印該課程相關的全部章節 c_obj = models.Course.objects.filter(id=1) print(c_obj.values('coursechapter__name')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
<QuerySet [{'coursechapter__name': 'Python基礎知識'}, {'coursechapter__name': 'Python數據類型初識'}]>
第二種寫法,使用反向查詢
class CheckView(View): """ 練習題相關 """ def get(self, request): # h.獲取id = 1的專題課,並打印該課程相關的全部章節 obj = models.Course.objects.get(id=1) chapter_list = obj.coursechapter_set.all() # 默認obj.表名_set.all() for item in chapter_list: print(item.name) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
Python基礎知識
Python數據類型初識
獲取id = 1的專題課,並打印該課程相關的全部課時
class CheckView(View): """ 練習題相關 """ def get(self, request): # i.獲取id = 1的專題課,並打印該課程相關的全部課時 c_obj = models.Course.objects.filter(id=1) for i in c_obj.values('coursechapter__chapter','coursechapter__name'): print(i.get('coursechapter__chapter'),i.get('coursechapter__name')) a_obj=models.CourseChapter.objects.filter(name=i.get('coursechapter__name')) for j in a_obj.values('coursesection__name'): print(' ',j.get('coursesection__name')) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
1 Python基礎知識 python基礎 2 Python數據類型初識 數據類型
第二種寫法:
class CheckView(View): """ 練習題相關 """ def get(self, request): # i.獲取id = 1的專題課,並打印該課程相關的全部課時 obj = models.Course.objects.get(id=1) chapter_list = obj.coursechapter_set.all() for chapter in chapter_list: print(chapter.name,chapter.coursesection_set.all()) return HttpResponse('ok')
刷新網頁,查看控制檯輸出:
Python數據類型初識 <QuerySet [<CourseSection: Python開發入門7天特訓營(付費):(第2章)Python數據類型初識-數據類型>]>
全部視圖都集中在views.py中,擴展不方便。
刪除views.py,並建立目錄views
在views目錄裏面建立course.py,它表示和課程相關的視圖
注意:視圖名最好加上View,這是約定俗成的
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView class CourseView(APIView): def get(self,request,*args,**kwargs): return HttpResponse('ok')
修改api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'course/$', course.CourseView.as_view()), ]
訪問網頁:http://127.0.0.1:8000/api/course/
在Django rest-framework中提供了5中version設置方式
好比:/course?version=v1
settings.py,最後一行添加。這裏面規定了版本爲v1和v2,若是是其餘版本,會報404錯誤!
REST_FRAMEWORK = { 'DEFAULT_VERSION': 'v1', # 默認版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 容許的版本 'VERSION_PARAM': 'version' # URL中獲取值的key }
api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'course/$', course.CourseView.as_view(),name='test'), ]
course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.versioning import QueryParameterVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 versioning_class = QueryParameterVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse('test', request=request) print(reverse_url) return Response('GET請求,響應內容')
訪問網頁: http://127.0.0.1:8000/api/course/
查看Pycharm控制檯輸出:
v1 <rest_framework.versioning.QueryParameterVersioning object at 0x000001AAE5245F28> http://127.0.0.1:8000/api/course/?version=v1
好比:/v1/users/
settings.py,保持不變
api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/course/$', course.CourseView.as_view(), name='test'), ]
course.py,修改versioning_class
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.versioning import URLPathVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 versioning_class = URLPathVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse('test', request=request) print(reverse_url) return Response('GET請求,響應內容')
訪問網頁: http://127.0.0.1:8000/api/v1/course/
注意要帶版本,不然報錯
查看Pycharm控制檯輸出:
v1 <rest_framework.versioning.URLPathVersioning object at 0x00000200F0F2E4A8> http://127.0.0.1:8000/api/v1/course/
好比:Accept: application/json; version=1.0
老外喜歡用這種方法,由於比較安全
settings.py,保持不變
api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'^course/$', course.CourseView.as_view(), name='test'), ]
course.py,修改versioning_class
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.versioning import AcceptHeaderVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 versioning_class = AcceptHeaderVersioning def get(self, request, *args, **kwargs): # 獲取版本 HTTP_ACCEPT頭 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse('test', request=request) print(reverse_url) return Response('GET請求,響應內容')
使用postman發送get請求,增長一個頭version
查看Pycharm控制檯輸出:
v1 <rest_framework.versioning.AcceptHeaderVersioning object at 0x000001AEA89206D8> http://127.0.0.1:8000/api/course/
好比:v1.example.com
settings.py,容許全部主機訪問
ALLOWED_HOSTS = ['*']
api_urls.py,保持不變
course.py,修改versioning_class
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.versioning import HostNameVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 versioning_class = HostNameVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse('test', request=request) print(reverse_url) return Response('GET請求,響應內容')
修改本機的hosts文件,增長2條記錄
127.0.0.1 v1.example.com
127.0.0.1 v2.example.com
訪問url: http://v1.example.com:8000/api/course/
查看Pycharm控制檯輸出:
v1 <rest_framework.versioning.HostNameVersioning object at 0x000001DE71A00470> http://127.0.0.1:8000/api/course/
訪問url: http://v2.example.com:8000/api/course/
查看Pycharm控制檯輸出:
v2 <rest_framework.versioning.HostNameVersioning object at 0x000001B31D5C3E48> http://v2.example.com:8000/api/course/
好比:example.com/v1/users/
settings.py,保持不變
api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'^v1/', ([url(r'course/', course.CourseView.as_view(), name='test'), ], None, 'v1')), url(r'^v2/', ([url(r'course/', course.CourseView.as_view(), name='test'), ], None, 'v2')), ]
course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.versioning import NamespaceVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 versioning_class = NamespaceVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse('test', request=request) print(reverse_url) return Response('GET請求,響應內容')
訪問url: http://127.0.0.1:8000/api/v1/course/
查看Pycharm控制檯輸出:
v1 <rest_framework.versioning.NamespaceVersioning object at 0x0000020BC5FAFDA0> http://127.0.0.1:8000/api/v1/course/
settings.py
REST_FRAMEWORK = { 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_VERSION': 'v1', 'ALLOWED_VERSIONS': ['v1', 'v2'], 'VERSION_PARAM': 'version' }
api_urls.py
from django.conf.urls import url from api.views import course urlpatterns = [ url(r'^course/', course.CourseView.as_view(), name='test'), ]
course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView # from rest_framework.versioning import NamespaceVersioning from rest_framework.response import Response class CourseView(APIView): # 開啓版本支持功能 # versioning_class = NamespaceVersioning def get(self, request, *args, **kwargs): # 獲取版本 print(request.version) # 獲取版本管理的類 print(request.versioning_scheme) # # 反向生成URL # reverse_url = request.versioning_scheme.reverse('test', request=request) # print(reverse_url) return Response('GET請求,響應內容')
訪問url: http://127.0.0.1:8000/api/course/
查看Pycharm控制檯輸出:
v1
<rest_framework.versioning.URLPathVersioning object at 0x000001FF069907F0>
默認版本爲v1
源碼分析,請參考連接:
http://www.cnblogs.com/derek1184405959/p/8724270.html
總結:在認證,權限,節流以前作了版本處理
先作專題課
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response import json class CourseView(APIView): def get(self, request, *args, **kwargs): """ 獲取全部專題課信息 :param request: :param args: :param kwargs: :return: """ # 方式一: course_list = list(models.Course.objects.all().values('id','name')) return HttpResponse(json.dumps(course_list,ensure_ascii=False))
訪問頁面: http://127.0.0.1:8000/api/course/
在api應用目錄下建立serializers文件夾,在裏面建立course.py
from rest_framework import serializers class CourseSerializer(serializers.Serializer): id = serializers.IntegerField() name = serializers.CharField()
修改views目錄下的course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer class CourseView(APIView): def get(self, request, *args, **kwargs): """ 獲取全部專題課信息 :param request: :param args: :param kwargs: :return: """ # 方式二: course_list = models.Course.objects.all() ser = CourseSerializer(instance=course_list,many=True) return Response(ser.data)
刷新頁面,效果以下:
若是當數據量特別大的時候,須要使用分頁
REST框架支持自定義分頁風格,若是使用的是APIView,你就須要本身調用分頁API,確保返回一個分頁後的響應。
修改views目錄下course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer from rest_framework.pagination import PageNumberPagination class CourseView(APIView): def get(self, request, *args, **kwargs): # 從數據庫中獲取數據 queryset = models.Course.objects.all() # 分頁 page = PageNumberPagination() # paginate_queryset 接收3參數,分別是queryset對象,request,視圖 # 這裏的self就是CourseView視圖 course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = CourseSerializer(instance=course_list,many=True) return Response(ser.data)
修改settings.py,指定每頁大小。這裏表示每頁一條數據
REST_FRAMEWORK = { 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_VERSION': 'v1', 'ALLOWED_VERSIONS': ['v1', 'v2'], 'VERSION_PARAM': 'version', 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'PAGE_SIZE':1 }
訪問網頁: http://127.0.0.1:8000/api/course/
效果以下:
怎麼獲取下一頁呢?在url上面加一個參數page=頁碼數,好比:
http://127.0.0.1:8000/api/course/?page=2
效果以下
爲何參數是page呢?而不是其餘的呢?看下面的源碼
class PageNumberPagination(BasePagination): """ A simple page number based style that supports page numbers as query parameters. For example: http://api.example.org/accounts/?page=4 http://api.example.org/accounts/?page=4&page_size=100 """ # The default page size. # Defaults to `None`, meaning pagination is disabled. page_size = api_settings.PAGE_SIZE django_paginator_class = DjangoPaginator # Client can control the page using this query parameter. page_query_param = 'page' page_query_description = _('A page number within the paginated result set.') # Client can control the page size using this query parameter. # Default is 'None'. Set to eg 'page_size' to enable usage. page_size_query_param = None page_size_query_description = _('Number of results to return per page.') # Set to an integer to limit the maximum page size the client may request. # Only relevant if 'page_size_query_param' has also been set. max_page_size = None last_page_strings = ('last',) template = 'rest_framework/pagination/numbers.html' invalid_page_message = _('Invalid page.')
看這一行
page_query_param = 'page'
它指定了url參數爲page
這裏有一個問題,若是鏈接不上數據,就會報錯
因此須要使用異常判斷,定義一個字典,返回code
1000表示成功,500表示錯誤。備註:這個是本身定義的,看你的心情了!
修改views下的course.py
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer from rest_framework.pagination import PageNumberPagination class CourseView(APIView): def get(self, request, *args, **kwargs): response = {'code':1000,'data':None,'error':None} try: # 從數據庫中獲取數據 queryset = models.Course.objects.all() # 分頁 page = PageNumberPagination() # paginate_queryset 接收3參數,分別是queryset對象,request,視圖 # 這裏的self就是CourseView視圖 course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = CourseSerializer(instance=course_list,many=True) response['data'] = ser.data except Exception as e: response['code'] = 500 response['error'] = '獲取數據失敗' return Response(response)
訪問頁面,發現數據多了幾個key
修改views下的course.py,將ORM語句故意改錯
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer from rest_framework.pagination import PageNumberPagination class CourseView(APIView): def get(self, request, *args, **kwargs): response = {'code':1000,'data':None,'error':None} try: # 從數據庫中獲取數據 queryset = models.Course.objects.allxx() # 模擬錯誤 # 分頁 page = PageNumberPagination() # paginate_queryset 接收3參數,分別是queryset對象,request,視圖 # 這裏的self就是CourseView視圖 course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = CourseSerializer(instance=course_list,many=True) response['data'] = ser.data except Exception as e: response['code'] = 500 response['error'] = '獲取數據失敗' return Response(response)
刷新頁面,提示失敗
注意:每個接口,必定要加try,防止程序崩潰
在公司裏面寫代碼,必須這樣。由於線上環境比較複雜,有各自攻擊行爲存在。因此,必須寫異常判斷。
並且,須要將異常信息寫入日誌。方便後續的排錯,由於線上的代碼,不能直接print,影響業務!
這個視圖定義了一個字典,用來作初始狀態返回。那麼其餘視圖,也須要返回code,再定義一遍?
若是有100個呢?因此,須要爲這個功能,單獨定義一個類。
這種是通用類,咱們通常會放在應用(這裏指的是api)下的utils(工具)文件夾中。
在api目錄下建立utils文件夾,新建文件response.py
class BaseResponse(object): def __init__(self): self.code = 1000 self.data = None self.error = None @property # 負責把一個方法變成屬性調用 def dict(self): return self.__dict__
python中的類,都會從object裏繼承一個__dict__屬性,這個屬性中存放着類的屬性和方法對應的鍵值對
修改views下的course.py,導入response
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer from rest_framework.pagination import PageNumberPagination from api.utils.response import BaseResponse class CourseView(APIView): def get(self, request, *args, **kwargs): # response = {'code':1000,'data':None,'error':None} ret = BaseResponse() try: # 從數據庫中獲取數據 queryset = models.Course.objects.all() # 分頁 page = PageNumberPagination() # paginate_queryset 接收3參數,分別是queryset對象,request,視圖 # 這裏的self就是CourseView視圖 course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = CourseSerializer(instance=course_list,many=True) ret.data = ser.data except Exception as e: ret.code = 500 ret.error = '獲取數據失敗' return Response(ret.__dict__)
刷新頁面,效果以下:
第二版,到這裏,就結束了。推薦使用第二種!
一般你會想要與Django模型相對應的序列化類。
ModelSerializer
類可以讓你自動建立一個具備模型中相應字段的Serializer
類。
這個ModelSerializer
類和常規的Serializer
類同樣,不一樣的是:
.create()
方法和.update()
方法。
查看serializers目錄下course.py,這裏我是手動指定了要序列化的字段,好比id和name
可是,還有更方便的方法。使用ModelSerializer,它會自動和ORM表關聯。
修改serializers目錄下course.py
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # id = serializers.IntegerField() # name = serializers.CharField() class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name'] # 指定序列化的字段
默認狀況下,全部的模型的字段都將映射到序列化器上相應的字段。
模型中任何關聯字段好比外鍵都將映射到PrimaryKeyRelatedField
字段。默認狀況下不包括反向關聯,除非像serializer relations文檔中規定的那樣顯示包含。
刷新頁面,效果同上!
查看官方文檔
https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display
對於具備選擇集的每一個字段,該對象將具備一個get_FOO_display()方法,其中FOO是該字段的名稱。 此方法返回字段的「可讀」值。
查看models.py裏面的Course類,看下面這2行
level_choices = ((0, '初級'), (1, '中級'), (2, '高級')) level = models.SmallIntegerField(choices=level_choices, default=1)
level_choices 它只是一個變量而已,上面2行,能夠合併爲一行
level = models.SmallIntegerField(choices=((0, '初級'), (1, '中級'), (2, '高級')), default=1)
真正在數據庫中,生成字段的是level。choices=xxx,表示它是一個選擇集。真正在數據庫存儲的是1,後面的中文,主要是在前端展現的。這樣作的目的,是爲了節省磁盤空間。通常數據庫用utf-8,一箇中文佔用3字節。而數字只佔用1字節!
那麼前端如何顯示中文呢?使用get_level_display() ,注意:level是數據庫的字段,值的類型必須是choices
修改serializers目錄下course.py
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn'] # 指定序列化的字段
注意:level_cn只是一個變量名而已,約定俗成會定義爲字段名。這裏的get_level_display不須要加括號,它會自動執行!
刷新頁面,效果以下:
Course和CourseDetail是一對一關係
如今須要顯示課時,可是課時在另一個表(CourseDetail課程詳情表)中,能夠用雙下方法嗎?
fields = ['id','name','level_cn','coursedetail__hours']
刷新頁面,會報錯
針對一對一的跨表查詢,可使用表名小寫.字段名
修改serializers目錄下course.py
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours'] # 指定序列化的字段
重啓django項目,刷新頁面
在Pycharm控制檯,會有一個警告信息
UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list:
百度翻譯一下:
unOrdEdObjistList警告:分頁可能與無序的對象列表產生不一致的結果:
啥意思呢?大概意思就是分頁時,沒有給它指定排序規則
修改views下的course.py,增長一個order_by就能夠了
order_by('pk'),表示以主鍵排序,默認是升序
from django.shortcuts import render,HttpResponse from api import models from rest_framework.views import APIView from rest_framework.response import Response from api.serializers.course import CourseSerializer from rest_framework.pagination import PageNumberPagination from api.utils.response import BaseResponse class CourseView(APIView): def get(self, request, *args, **kwargs): # response = {'code':1000,'data':None,'error':None} ret = BaseResponse() try: # 從數據庫中獲取數據 queryset = models.Course.objects.all().order_by('pk') # 分頁 page = PageNumberPagination() # paginate_queryset 接收3參數,分別是queryset對象,request,視圖 # 這裏的self就是CourseView視圖 course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = CourseSerializer(instance=course_list,many=True) ret.data = ser.data except Exception as e: ret.code = 500 ret.error = '獲取數據失敗' return Response(ret.__dict__)
重啓django項目,刷新頁面。再次查看Pycharm控制檯,就沒有警告了!
CourseDetail表的recommend_courses字段和Course表,是多對多的關係
若是要顯示recommend_courses(推薦課程)呢?可使用表名小寫.字段名嗎?測試一下
修改serializers目錄下course.py
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') recommend_courses = serializers.CharField(source='coursedetail.recommend_courses') class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses'] # 指定序列化的字段
刷新頁面,效果以下:
發現recommend_courses字段,並非咱們想要的結果
再加一個.all
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') recommend_courses = serializers.CharField(source='coursedetail.recommend_courses.all') class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses'] # 指定序列化的字段
刷新頁面,效果以下:
發現它是一個queryset對象,如何獲取對象裏面的屬性呢?
它是用來獲取別的表字段的。
查看serializers目錄下course.py,點擊CharField。搜索關鍵字get_{field_name},看源碼
def bind(self, field_name, parent): # In order to enforce a consistent style, we error if a redundant # 'method_name' argument has been used. For example: # my_field = serializer.SerializerMethodField(method_name='get_my_field') default_method_name = 'get_{field_name}'.format(field_name=field_name) assert self.method_name != default_method_name, ( "It is redundant to specify `%s` on SerializerMethodField '%s' in " "serializer '%s', because it is the same as the default method name. " "Remove the `method_name` argument." % (self.method_name, field_name, parent.__class__.__name__) ) # The method name should default to `get_{field_name}`. if self.method_name is None: self.method_name = default_method_name super(SerializerMethodField, self).bind(field_name, parent)
修改serializers目錄下course.py,專門定義一個方法,用來獲取recommend_courses
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') # 顯示推薦課程,對於多對多,使用def_字段名 # SerializerMethodField表示序列化字段,使用方法獲取 recommend_courses = serializers.SerializerMethodField() class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses'] # 指定序列化的字段 def get_recommend_courses(self,row): recommend_list = [] # 空列表 # row表示一行數據, .all()表示取全部關聯的書籍 for item in row.coursedetail.recommend_courses.all(): recommend_list.append({'id':item.id,'name':item.name}) return recommend_list
重啓2遍django項目,刷新頁面,效果以下:
上面代碼中的,列表裏面添加字典數據,能夠改爲列表生成
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') # 顯示推薦課程,對於多對多,使用def_字段名 # SerializerMethodField表示序列化字段,使用方法獲取 recommend_courses = serializers.SerializerMethodField() class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses'] # 指定序列化的字段 def get_recommend_courses(self,row): recommend_list = row.coursedetail.recommend_courses.all() return [{'id': item.id, 'name': item.name} for item in recommend_list]
重啓django項目,刷新頁面,效果同上!
看下圖中的代碼
這個名字,必須一一對應,不然報錯
由於源碼裏面定義了,它是取get_字段名方法的。
SerializerMethodField 拆分紅3個單詞:Serializer Method Field。能夠理解爲序列化,方法,字段
Course表的degree_course字段和DegreeCourse表示一對多關係
要顯示總獎學金
修改serializers目錄下course.py
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') # 顯示推薦課程,對於多對多,使用def_字段名 # SerializerMethodField表示序列化字段,使用方法獲取 recommend_courses = serializers.SerializerMethodField() # 顯示總獎學金,使用表名.字段 total_scholarship = serializers.CharField(source='degree_course.total_scholarship') class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses','total_scholarship'] # 指定序列化的字段 def get_recommend_courses(self,row): recommend_list = row.coursedetail.recommend_courses.all() return [{'id': item.id, 'name': item.name} for item in recommend_list]
刷新頁面,效果以下:
Course表的price_policy字段和PricePolicy表,是用contenttypes關聯的
from rest_framework import serializers from api import models class CourseSerializer(serializers.ModelSerializer): # 顯示choices裏面的中文 level_cn = serializers.CharField(source='get_level_display') # 顯示課時,對於一對一,使用表名.字段 hours = serializers.CharField(source='coursedetail.hours') # 顯示推薦課程,對於多對多,使用def_字段名 # SerializerMethodField表示序列化字段,使用方法獲取 recommend_courses = serializers.SerializerMethodField() # 顯示總獎學金,使用表名.字段 total_scholarship = serializers.CharField(source='degree_course.total_scholarship') # 顯示價格策略,contenttypes反向查詢,使用def_字段名 price_strategy = serializers.SerializerMethodField() class Meta: # 配置項 model = models.Course # Course表 fields = ['id','name','level_cn','hours','recommend_courses','total_scholarship','price_strategy'] # 指定序列化的字段 def get_recommend_courses(self,row): recommend_list = row.coursedetail.recommend_courses.all() return [{'id': item.id, 'name': item.name} for item in recommend_list] def get_price_strategy(self,row): # .all 表示查詢關聯的價格策略 price_list = row.price_policy.all() return [{'id': item.id, 'valid_period': item.valid_period,'price': item.price} for item in price_list]
重啓django項目,刷新頁面,效果以下:
總結:
序列化類
一對一,使用 表名小寫.字段名
一對多,使用 表名小寫.字段名
多對多,使用def_字段名。注意字段必須先聲明爲serializers.SerializerMethodField()。字段名和def_字段名必須一一對應!
contenttypes反向查詢,使用def_字段名。利用contenttypes字段,也是要聲明serializers.SerializerMethodField()...
# a.查看全部學位課並打印學位課名稱以及授課老師 # b.查看全部學位課並打印學位課名稱以及學位課的獎學金 # c.展現全部的專題課 # d. 查看id=1的學位課對應的全部模塊名稱 # e.獲取id = 1的專題課,並打印:課程名、級別(中文)、why_study、what_to_study_brief、全部recommend_courses # f.獲取id = 1的專題課,並打印該課程相關的全部常見問題 # g.獲取id = 1的專題課,並打印該課程相關的課程大綱 # h.獲取id = 1的專題課,並打印該課程相關的全部章節
將上面幾個查詢改爲接口方式,返回json格式。
注意:每個查詢,都是一個獨立的接口
經過axios向API發送ajax請求,並顯示結果(展現全部的專題課)。
注意:會出現跨域問題。請自行百度!提示:搜索關鍵字cors
修改api_urls.py
from django.conf.urls import url from api.views import course,degreecourse urlpatterns = [ url(r'courses/$',course.CoursesView.as_view()), url(r'courses/(?P<pk>\d+)/$',course.CourseDetailView.as_view()), url(r'courses/thematic/$',course.CourseThematicView.as_view()), url(r'courses/module/(?P<pk>\d+)/$',course.CourseModuleView.as_view()), url(r'courses/faq/(?P<pk>\d+)/$',course.CourseFAQView.as_view()), url(r'courses/outline/(?P<pk>\d+)/$',course.CourseOutlineView.as_view()), url(r'courses/chapter/(?P<pk>\d+)/$',course.CourseChapterView.as_view()), url(r'degreecourse/$',degreecourse.DegreeCourseView.as_view()), url(r'degreecourse/teachers/$',degreecourse.DegreeCourseTeachersView.as_view()), url(r'degreecourse/scholarship/$',degreecourse.DegreeCourseScholarshipView.as_view()), ]
修改serializers目錄下的course.py
from rest_framework import serializers from api import models class CourseModelSerializer(serializers.ModelSerializer): # 全部課程 level_name = serializers.CharField(source='get_level_display') hours = serializers.CharField(source='coursedetail.hours') course_slogan = serializers.CharField(source='coursedetail.course_slogan') recommend_courses = serializers.SerializerMethodField() class Meta: model = models.Course fields = ['id','name','level_name','hours','course_slogan','recommend_courses'] def get_recommend_courses(self,row): recommend_list = row.coursedetail.recommend_courses.all() return [ {'id':item.id,'name':item.name} for item in recommend_list] class CourseThematicModelSerializer(serializers.ModelSerializer): # 全部的專題課 level_name = serializers.CharField(source='get_level_display') course_type = serializers.CharField(source='get_course_type_display') status = serializers.CharField(source='get_status_display') degree_course = serializers.CharField(source='degree_course.total_scholarship') class Meta: model = models.Course fields = '__all__' class CourseModuleModelSerializer(serializers.ModelSerializer): # 全部的專題課 degree_course = serializers.CharField(source='degree_course.name') class Meta: model = models.Course fields = ['id','degree_course'] class CourseDetailModelSerializer(serializers.ModelSerializer): # 具體id的學位課對應的全部模塊名稱 level_name = serializers.CharField(source='get_level_display') why_study = serializers.CharField(source='coursedetail.why_study') what_to_study_brief = serializers.CharField(source='coursedetail.what_to_study_brief') recommend_courses = serializers.SerializerMethodField() price_strategy = serializers.SerializerMethodField() class Meta: model = models.Course fields = ['id','name','level_name','why_study','what_to_study_brief','recommend_courses','price_strategy'] def get_recommend_courses(self,row): recommend_list = row.coursedetail.recommend_courses.all() return [ {'id':item.id,'name':item.name} for item in recommend_list] def get_price_strategy(self,row): price_list = row.price_policy.all() return [{'id': item.id, 'valid_period': item.valid_period,'price': item.price} for item in price_list] class CourseFAQModelSerializer(serializers.ModelSerializer): # 具體id專題課程相關的全部常見問題 asked_question = serializers.SerializerMethodField() class Meta: model = models.Course fields = ['id','name', 'asked_question'] def get_asked_question(self, row): faq_list = row.asked_question.all() return [{'id': item.id, 'question': item.question, 'answer': item.answer} for item in faq_list] class CourseOutlineModelSerializer(serializers.ModelSerializer): # 具體id課程相關的課程大綱 asked_question = serializers.SerializerMethodField() class Meta: model = models.Course fields = ['id', 'name', 'asked_question'] def get_asked_question(self, row): outline_list = row.coursedetail.courseoutline_set.all() return [{'id': item.id, 'title': item.title, 'content': item.content} for item in outline_list] class CourseChapterModelSerializer(serializers.ModelSerializer): # 具體id課程相關的全部章節 chapter = serializers.SerializerMethodField() class Meta: model = models.Course fields = ['id', 'name', 'chapter'] def get_chapter(self, row): chapter_list = row.coursechapter_set.all() return [{'id': item.id, 'name': item.name} for item in chapter_list]
修改serializers目錄下的degreecourse.py
from rest_framework import serializers from api import models class DegreeCourseModelSerializer(serializers.ModelSerializer): # 學位課全部信息 class Meta: model = models.DegreeCourse fields = '__all__' class DegreeCourseTeachersModelSerializer(serializers.ModelSerializer): # 學位課的老師 teachers = serializers.SerializerMethodField() class Meta: model = models.DegreeCourse fields = ['name','teachers'] def get_teachers(self,row): teachers_list = row.teachers.all() return [ {'id':item.id,'name':item.name} for item in teachers_list] class DegreeCourseScholarshipModelSerializer(serializers.ModelSerializer): # 學位課的獎學金 degreecourse_price_policy = serializers.SerializerMethodField() class Meta: model = models.DegreeCourse fields = ['name','degreecourse_price_policy'] def get_degreecourse_price_policy(self,row): scholarships = row.scholarship_set.all() return [ {'id':item.id,'time_percent':item.time_percent,'value':item.value} for item in scholarships]
在api目錄下utils文件夾,建立文件serialization_general.py
from api.utils.response import BaseResponse from rest_framework.pagination import PageNumberPagination class SerializedData(object): # 序列化通用格式數據 def __init__(self,request,queryset,serializer_class): self.request = request self.queryset = queryset self.serializer_class = serializer_class def get_data(self): ret = BaseResponse() try: # 從數據庫獲取數據 queryset = self.queryset.order_by('id') # 分頁 page = PageNumberPagination() course_list = page.paginate_queryset(queryset, self.request, self) # 分頁以後的結果執行序列化 ser = self.serializer_class(instance=course_list, many=True) ret.data = ser.data except Exception as e: print(e) ret.code = 500 ret.error = '獲取數據失敗' return ret.dict
修改views目錄下的course.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import URLPathVersioning from rest_framework.pagination import PageNumberPagination from api import models from api.serializers.course import CourseModelSerializer, CourseThematicModelSerializer, CourseModuleModelSerializer, \ CourseDetailModelSerializer,CourseFAQModelSerializer,CourseOutlineModelSerializer,CourseChapterModelSerializer from api.utils.response import BaseResponse from api.utils.serialization_general import SerializedData class CoursesView(APIView): # 全部課程,分頁展現,每頁1個 def get(self, request, *args, **kwargs): # response = {'code':1000,'data':None,'error':None} queryset = models.Course.objects.all() serializer_class = CourseModelSerializer data = SerializedData(request,queryset,serializer_class).get_data() return Response(data) class CourseDetailView(APIView): # 課程詳情 def get(self, request, pk, *args, **kwargs): queryset = models.Course.objects.filter(id=pk) serializer_class = CourseDetailModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data) class CourseThematicView(APIView): # 全部的專題課 def get(self, request, *args, **kwargs): queryset = models.Course.objects.all() serializer_class = CourseThematicModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data) class CourseModuleView(APIView): # 具體id的學位課對應的全部模塊名稱 def get(self, request, pk, *args, **kwargs): queryset = models.Course.objects.filter(degree_course_id=pk) serializer_class = CourseModuleModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data) class CourseFAQView(APIView): # 具體id的課程相關的全部常見問題 def get(self, request, pk, *args, **kwargs): queryset = models.Course.objects.filter(id=pk) serializer_class = CourseFAQModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data) class CourseOutlineView(APIView): # 具體id課程相關的課程大綱 def get(self, request, pk, *args, **kwargs): queryset = models.Course.objects.filter(id=pk) serializer_class = CourseOutlineModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data) class CourseChapterView(APIView): # 具體id課程相關的全部章節 def get(self, request, pk, *args, **kwargs): queryset = models.Course.objects.filter(id=pk) serializer_class = CourseChapterModelSerializer data = SerializedData(request, queryset, serializer_class).get_data() return Response(data)
在views目錄下建立文件degreecourse.py
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import URLPathVersioning from rest_framework.pagination import PageNumberPagination from api import models from api.serializers.degreecourse import DegreeCourseModelSerializer,DegreeCourseTeachersModelSerializer from api.serializers.degreecourse import DegreeCourseScholarshipModelSerializer from api.utils.response import BaseResponse class DegreeCourseView(APIView): # 全部學位課 def get(self,request,*args,**kwargs): # response = {'code':1000,'data':None,'error':None} ret = BaseResponse() try: # 從數據庫獲取數據 queryset = models.DegreeCourse.objects.all() # 分頁 page = PageNumberPagination() course_list = page.paginate_queryset(queryset,request,self) # 分頁以後的結果執行序列化 ser = DegreeCourseModelSerializer(instance=course_list,many=True) ret.data = ser.data except Exception as e: ret.code = 500 ret.error = '獲取數據失敗' return Response(ret.dict) class DegreeCourseTeachersView(APIView): # 學位課對應的老師 def get(self, request, *args, **kwargs): ret = BaseResponse() try: # 從數據庫獲取數據 # 防止出現UnorderedObjectListWarning: Pagination may yield... queryset = models.DegreeCourse.objects.get_queryset().order_by('id') print(queryset) # 分頁 page = PageNumberPagination() course_list = page.paginate_queryset(queryset, request, self) # 分頁以後的結果執行序列化 ser = DegreeCourseTeachersModelSerializer(instance=course_list, many=True) print(ser.data) ret.data = ser.data except Exception as e: print(e) ret.code = 500 ret.error = '獲取數據失敗' return Response(ret.dict) class DegreeCourseScholarshipView(APIView): # 學位課對應的老師 def get(self, request, *args, **kwargs): ret = BaseResponse() try: # 從數據庫獲取數據 # 防止出現UnorderedObjectListWarning: Pagination may yield... queryset = models.DegreeCourse.objects.get_queryset().order_by('id') print(queryset) # 分頁 page = PageNumberPagination() course_list = page.paginate_queryset(queryset, request, self) # 分頁以後的結果執行序列化 ser = DegreeCourseScholarshipModelSerializer(instance=course_list, many=True) print(ser.data) ret.data = ser.data except Exception as e: print(e) ret.code = 500 ret.error = '獲取數據失敗' return Response(ret.dict)
訪問如下url:
查看全部學位課並打印學位課名稱以及授課老師
http://127.0.0.1:8000/api/v1/degreecourse/teachers/
查看全部學位課並打印學位課名稱以及學位課的獎學金
http://127.0.0.1:8000/api/v1/degreecourse/scholarship/
展現全部的專題課
http://127.0.0.1:8000/api/v1/courses/thematic/
查看id=1的學位課對應的全部模塊名稱
http://127.0.0.1:8000/api/v1/courses/module/1/
獲取id = 1的專題課,並打印:課程名、級別(中文)、why_study、what_to_study_brief、全部recommend_courses
http://127.0.0.1:8000/api/v1/courses/1/
獲取id = 1的專題課,並打印該課程相關的全部常見問題
http://127.0.0.1:8000/api/v1/courses/faq/1/
coursedetail獲取id = 1的專題課,並打印該課程相關的課程大綱
http://127.0.0.1:8000/api/v1/courses/outline/1/
獲取id = 1的專題課,並打印該課程相關的全部章節
http://127.0.0.1:8000/api/v1/courses/chapter/1/
在cmd中進入一個空目錄,輸入下面的命令,建立一個項目mysite
vue init webpack mysite
執行以後有不少選項,詳情請參考:
http://www.javashuo.com/article/p-zyfjcyjn-by.html
執行2個命令,啓動vue項目
cd mysite
npm run dev
訪問vue的網頁:http://localhost:8080
進入vue項目,裏面有一個index.html,它是最大的母版。
裏面定義了一個div,id爲app
進入src目錄,修改App.vue。刪除圖片和css樣式
<template> <div id="app"> <router-view/> </div> </template> <script> export default { name: 'App' } </script> <style> </style>
進入src-->components,修改HelloWorld.vue,刪除多餘的a標籤
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: '歡迎使用路飛學城' } } } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
關閉vue項目,安裝axios
npm install axios --save
從新啓動vue項目
npm run dev
修改main.js,導入axios,並定義一個全局變量$axios
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import axios from 'axios' //導入axios Vue.prototype.$axios = axios //聲明全局變量 Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, components: { App }, template: '<App/>' })
進入src-->components,修改HelloWorld.vue。讓頁面加載完成後,使用axios發送請求
<template> <div class="hello"> <h1>{{ msg }}</h1> </div> </template> <script> export default { name: 'HelloWorld', data () { return { msg: '歡迎使用路飛學城' } }, mounted(){ //頁面加載完成後 this.initCourse(); //執行此方法 }, methods:{ initCourse:function () { //向後臺發送ajax請求 this.$axios.request({ url:'http://127.0.0.1:8000/api/v1/courses/', method:'GET', responseType:'json', }).then(function (arg) { //成功以後 console.log(arg); }).catch(function (err) { //發生錯誤 console.log(err); }) } }, } </script> <!-- Add "scoped" attribute to limit CSS to this component only --> <style scoped> h1, h2 { font-weight: normal; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
刷新網頁,查看Console,提示不容許訪問
只要看到了Access-Control-Allow-Origin,就表示出現跨域了
關於跨域問題,如何解決。請訪問下一篇文章: