需求描述:根據 user 於網頁前端輸入的內容,filter 出符合內容的結果,並替它新增欄位並給值。
一、安裝設定
- 按照文件說明,安裝:
pip install -e git+git://github.com/mvpdev/django-eav.git#egg=django-eav
2. 編輯 settings.py 做設定:
#Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'testEav',
'eav', ]# sites setting for eav
SITE_ID = 1
3. 資料遷移:
python manage.py migrate
4. 接著想按照文件的 Usage 試一下,試到下面這段噴 Error:
Attribute.objects.create(name='Weight',datatype=Attribute.TYPE_FLOAT)
Error 訊息:
ValidationError: {'site': [u'site instance with id 1 does not exist.']}
開始尋找解決方法,看到這邊有比較詳細的討論串,問題似乎是我還沒註冊 domain,不確定該怎麼註冊,不過按照 RobM 的回答,可以把現有註冊的 domain 列出來,於是編輯了 admin.py:
from django.contrib import admin
from django.contrib.sites.models import Site
admin.site.unregister(Site)
class SiteAdmin(admin.ModelAdmin):
fields = ('id', 'name', 'domain')
readonly_fields = ('id',)
list_display = ('id', 'name', 'domain')
list_display_links = ('name',)
search_fields = ('name', 'domain')
admin.site.register(Site, SiteAdmin)
這樣就能直接在瀏覽器的後台手動新增我的 domain:
接著再回到 Usage 就可以順利通過剛才卡關的地方。
5. 試到 Usage 後面那邊,都會因為找不到 eav__ 開頭的參數而噴 Error,稍微找了一下還不知道怎麼解決,不過用前半段的內容已經能確實做到我需要的功能了,所以先略過。
6. 到資料庫確認一下,會看到 django-eav 會自動建成圖中這幾個 table,新增的欄位會放在 eav_attribute,新增的值放在 eav_value:
二、實際測試
接續前一篇的內容,加上這個 APP 的功能,最後希望達成的功能是:從前端輸入內容,然後根據內容 filter 出符合的資料,顯示在網頁前端,最後在替符合的資料新增欄位並給值。
- 編輯 models.py,在這個 model 註冊 eav,讓 django-eav 知道這個 model 要用它的東西:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models# Create your models here.
from eav.decorators import register_eav # Add
@register_eav() # Addclass Post(models.Model):
post = models.CharField(max_length=500)
2. 編輯 views.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.shortcuts import render, redirect # Create your views here.
from django.views.generic import TemplateView
from testPassValue.forms import HomeForm
from testPassValue.models import Post
from eav.models import Attribute # Addclass HomeView(TemplateView):
template_name = 'home/home.html' def get(self, request):
form = HomeForm()
return render( request, self.template_name, {'form':form}) def post(self, request):
form = HomeForm(request.POST)
if form.is_valid():
#form.save() 先註解掉
inputText = form.cleaned_data['post']
form = HomeForm()
#return redirect('home:home') 先註解掉
text = Post.objects.filter(post=inputText)
Attribute.objects.create(name='testaddnewcolumn', datatype=Attribute.TYPE_TEXT)
for unit in text:
u = Post.objects.get(pk=unit.pk)
u.eav.testaddnewcolumn = 'testsuccess'
u.save() args = {'form': form, 'text': str(text.values())}
return render(request, self.template_name, args )
這邊有一個陷阱,是新增的 column name 必須全為英文小寫,原本用了大小寫夾雜的 name,結果一直存不進去 Orz
3. runserver 看一下成果,在 Post 輸入123 Submit 之後,網頁前端會顯示 filter 後符合的結果:
4. 到資料庫確認是不是有真的新增 testaddnewcolumn 欄位跟 testsuccess 的值,首先截一部分原本的資料:
可以看到 id 為 3 跟 12 的是符合剛搜尋要的 123,再去看 eav_value:
第一個 column 是自動生成的流水號 ID,第二個是指對應的原 table id,例如剛才的 3 跟 12 都有順利塞了這個值給他們。再去確認一下 eav_attribute:
也確認了有新增一個叫做 testaddnewcolumn 的欄位,這樣就算完成了。事後如果想要整個一起看的話,還需要一段 table 之間的 mapping,裡面的 key 值給的很清楚,能夠輕鬆地 mapping 起來。