原始需求:
1、一篇文章內容分N個版塊,每篇文章的版塊數量不同。
2、有個文章搜索功能,需要同時搜索標題和內容。
實現思路:
1、由於每篇文章的內容版塊數量不同,因此將每個文章的標題和內容分開存入2張表中。
模型: #標題和屬性模型 class ArticleInfoModel(models.Model): title = models.CharField(max_length=200) summary = models.TextField(null=True) author = models.ForeignKey(User, null=True) create_time = models.DateTimeField(null=True) #文章內容模型 class ArticleContentModel(models.Model): article = models.ForeignKey('ArticleInfoModel') content = models.TextField() section = models.ForeignKey('ArticleContentSectionModel') create_time = models.DateTimeField(null=True)
邏輯實現:
def search_article(request,page=1,category_id=0): try: currentPage = int(page) categoryId = int(category_id) except: pass if request.method == 'GET': return json_result(message=u'搜索文章頁面!') else: searchWord = request.POST.get('search_word',None) if searchWord: try: searchWord = str(searchWord).replace(' ','') except:pass numPage = int(configs.PC_FRONT_NUM_PAGE) start = (currentPage - 1) * numPage end = start + numPage if categoryId: methodCategoryModel = CategoryModel.objects.filter(pk=categoryId, is_active=1).first() if methodCategoryModel: # 先過濾出符合條件的文章信息,然后在這些文章中檢索出和關鍵詞相匹配的文章 indexModel = ArticleInfoModel.objects.filter(status__in=[1,2,3],category=methodCategoryModel).all() else: return json_params_error(message=u'你嘗試查看一個不存在的分類下的文章!') else: indexModel = MethodArticleInfoModel.objects.filter(status__in=[1,2,3]).all() # 開始檢索文章標題模型 infoModel = indexModel.filter(Q(title__icontains=searchWord) | Q(summary__icontains=searchWord)).all() # 再跨表檢索文章內容模型中和關鍵詞相匹配的文章內容,並且對article去重 contentModel = ArticleInfoModel.objects.filter(methodarticlecontentmodel__content__icontains=searchWord).distinct() # 由於內容只進行關鍵詞檢索,沒有對文章其他條件進行過濾,因此需要再次計算檢索出的內容和其他條件的交集 tmp_content_list = set() if contentModel: content_list = set(contentModel) index_list = set(indexModel) tmp_content_list = content_list.intersection(index_list) #求內容模型和索引模型的交集 # 最后將符合條件的文章標題模型和文章內容模型合並返回 info_list = set() if infoModel: info_list = set(infoModel) # 在從文章標題模型中查找出最終匯總的模型返回 articleModel = info_list.union(tmp_content_list) else: return json_params_error(message=u'請輸入要搜索的關鍵詞!') if len(articleModel) > 0: ...
正常操作數據模型
...else: return json_params_error(message=u'暫無相關文章!')
這么做的緣由:
1、在django 1.10版本中,不支持在一個過濾條件中同時檢索兩張表,因此只能一張一張查詢。
比如:
indexModel = ArticleInfoModel.objects.filter( Q(title__icontains=searchWords)| Q(summary__icontains=searchWords)| Q(articlecontentmodel__content__icontains=searchWords) #這是ArticleContentModel 模型 status__in=[1,2,3], category=methodCategoryModel).all()
在官方文檔中提到,模型可以進行關聯查詢,如果沒有關聯關系的模型可以才用:模型名字小寫__字段名字 來進行查詢,
按照官方給的例子,單條過濾語句這樣寫沒有任何問題,但是如果把這種跨表查詢的語句和當前模型中需要過濾的條件寫在一個過濾語句中進行查詢,就拿不到想要的結果。
因此,就才用上面的方式,先過濾A表中的數據,然后跨表過濾B表中的數據。
之所以跨表過濾B表數據,是因為最終要將A,B表過濾的數據進行匯總。
由於在1.10以前版本中模型還不支持union()、intersection()這種交集、並集函數,這是在1.11版本中出的,mysql也不支持這種運算方式。
所以將A表中符合條件的模型集轉換成set()類型,將B表中符合條件的模型集轉換成set()類型,並計算出交集。
至此就可以實現同時檢索兩張表的問題。
