しかし、何らかの理由により、テーブル定義を変えずに model を変更したい場合がある。
この場合、migrate コマンドに fake オプションを付けて実行すればよい。
> python ./manage.py makemigrations > python ./manage.py migrate --fake
> python ./manage.py makemigrations > python ./manage.py migrate --fake
from django_tables2 import SingleTableView
class ActorSingleTableView(SingleTableView):
model = Actor
table_class = ActorTable
table_pagination = {"per_page": 20}
template_name = "actorlistview.html"
このテーブルを表示する際、デフォルトのテンプレート変数は table になる。
from django_tables2 import SingleTableView
class ActorSingleTableView(SingleTableView):
model = Actor
table_class = ActorTable
context_table_name = "actors_table" # テンプレート変数が actors_table に変更される。
table_pagination = {"per_page": 20}
template_name = "actorlistview.html"
上記例の場合、Actor に格納されたデータがそのまま ActorTable の形式で表示される。
from django_tables2 import SingleTableView
class ActorSingleTableView(SingleTableView):
queryset = Actor.objects.order_by("last_name", "first_name")
table_class = ActorTable
table_pagination = {"per_page": 20}
template_name = "actorlistview.html"
get_queryset() により設定することもできる。
from django_tables2 import SingleTableView
class ActorSingleTableView(SingleTableView):
table_class = ActorTable
table_pagination = {"per_page": 20}
template_name = "actorlistview.html"
def get_queryset(self):
return Actor.objects.order_by("last_name", "first_name")
また、同様に get_table_data() により設定することができる。
from django_tables2 import SingleTableView
class ActorSingleTableView(SingleTableView):
model = Actor
table_class = ActorTable
table_pagination = {"per_page": 20}
template_name = "actorlistview.html"
def get_table_data(self):
return Actor.objects.order_by("last_name", "first_name")
def get_context_data(self, **kargs):
# データ取得するための処理...
return {取得したデータは辞書型で返す}
以下の例では、取得したデータを django-tables2 を利用して表示している。
[view.py]
class ActorTemplate(TemplateView):
template_name = "sample.html"
def get_context_data(self, **kargs):
actors = Actor.objects.order_by("first_name", "last_name")
actortable = ActorTable(actors)
RequestConfig(self.request,
paginate={"per_page": 20}).configure(actortable)
return {"title": "HOGE TITLE",
"actortable": actortable}
[models.py]
class Actor(models.Model):
actor_id = models.SmallIntegerField(primary_key=True)
first_name = models.CharField(max_length=45)
last_name = models.CharField(max_length=45)
last_update = models.DateTimeField()
[tables.py]
class ActorTable(tables.Table):
first_name = tables.Column(accessor="first_name",
verbose_name="First Name",
orderable=False,
attrs={"th": {"id": "first_name_id"}}
)
last_name = tables.Column(accessor="last_name",
verbose_name="Last Name",
orderable=False,
attrs={"th": {"id": "last_name_id"}}
)
[urls.py]
urlpatterns = [
url(r'^actors/',
ActorTemplate.as_view()),
]
[sample.html]
{% load render_table from django_tables2 %}
{% load static %}
<html>
<head>
<title>{{ title }}</title>
<link rel="stylesheet" href="{% static 'django_tables2/themes/paleblue/css/screen.css' %}" />
<style type="text/css">
th#first_name_id {width: 150px}
th#last_name_id {width: 150px}
</style>
</head>
<body>
{% render_table actortable %}
</body>
</html>
python manage.py inspectdb --database=(database name) > (output file name)
class City(models.Model):
city_id = models.SmallIntegerField(primary_key=True)
city = models.CharField(max_length=50)
country = models.ForeignKey('Country')
last_update = models.DateTimeField()
objects = CityManager()
class Meta:
managed = False
db_table = 'city'
class Country(models.Model):
country_id = models.SmallIntegerField(primary_key=True)
country = models.CharField(max_length=50)
last_update = models.DateTimeField()
class Meta:
managed = False
db_table = 'country'
table として CityTable を以下のように作成する。各行の先頭にチェックボックスを配置する。
import django_tables2 as tables
class CityTable(tables.Table):
ck = tables.CheckBoxColumn(accessor="pk")
city = tables.Column(accessor="city",
verbose_name="都市名",
orderable=True,
attrs={"th": {"id": "country"}}
)
country = tables.Column(accessor="country.country",
verbose_name="国名",
orderable=True,
attrs={"th": {"id": "country"}}
)
class Meta:
attrs = {"class": "paleblue"}
チェックがついた行の情報を取得する場合は、対応する view 関数内で request.POST.getlist 関数にて取得する。
def city_view(request):
if request.method == "POST":
pks = list(map(int, request.POST.getlist("ck")))
・・・
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'nextdb': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'nextdb.sqlite3'),
}
}
次に、データベースの切り替え条件を定義したルータの情報を記載する。なお、ここでは、project/router.py として作成する。
class Router(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == "app":
return "nextdb"
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == "app":
return "nextdb"
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == "app" and obj2._meta.app_label == "app":
return True
elif "app" not in [obj1._meta.app_label, obj2._meta.app_label]:
return True
return None
def allow_migrate(self, db, app_label, model=None, **hints):
if app_label == "app":
return db == "nextdb"
else:
return db == "default"
db_for_read および db_for_write は、与えられた model のアクセス先データベースを返す関数である。なお、戻り値が None の場合は、DATABASES の default で定義したデータベースが採用される。DATABASE_ROUTERS = ['router.Router']例として、appアプリケーションのモデル(app/model.py)と、その他のアプリケーションで共通させるモデル(core/model.py)を以下のように定義する。
[app/model.py]
from django.db import models
class Organization(models.Model):
organization_cd = models.CharField(max_length=5)
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
class Meta:
ordering = ["organization_cd"]
class User(models.Model):
staff_cd = models.CharField(max_length=7)
name = models.CharField(max_length=15)
organization = models.ForeignKey(Organization)
[core/model.py]
from django.db import models
class User(models.Model):
cd = models.CharField(max_length=7)
name = models.CharField(max_length=15)
def __str__(self):
return "%s %s" % (self.cd, self.name)
双方とも管理者画面からアクセスすると、2つのデータベースが作成されていることが確認できる。
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [(テンプレートが格納されているディレクトリ)],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.static',
],
},
},
]
class TestForm(ModelForm):
class Meta:
model = User
Django 1.8 以上は、form の項目を明示する必要があり、上記のような記述をした場合、ImproperlyConfigured 例外が送出される。
class TestForm(ModelForm):
class Meta:
model = User
fields = "__all__"
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'
users = User.object.filter(name__startswith="John") print users.query select * from core_user where name like 'John%';
empty_list = [] # <type 'list'> none_query_set = SomeModel.objects.none() # <class 'django.db.models.query.QuerySet'>
pip install django-tables2model内に格納されたデータを出力するには、対応するtableクラスを作成する。
[model.py]
class Organization(models.Model):
organization_id = models.CharField(max_length=5)
name = models.CharField(max_length=20)
class User(models.Model):
staff_id = models.CharField(max_length=7)
name = models.CharField(max_length=15)
organization = models.ForeignKey(Organization)
まず、出力項目を管理する django_tables2.Table より派生したクラスを作成する。
[tables.py]
import django_tables2 as tables
class UserTable(tables.Table):
staff_id = tables.Column(accessor="staff_id",
verbose_name="STAFF ID",
order_by=("staff_id"))
name = tables.Column(accessor="name",
verbose_name="USER NAME",
order_by=("name"))
organization = tables.Column(accessor="organization.name",
verbose_name="ORGANIZATION",
order_by=("organization.organization_id"))
class Meta:
attrs = {"class": "paleblue"}
上に記載した Column の引数を説明する。
[views.py]
from django.shortcuts render
from models import User
from tables import UsetTable
from django_tables2.config import RequestConfig
def create_table(request):
users = User.objects.all()
table = UserTable(users)
RequestConfig(request).configure(table)
return render(request, "people.html", {"table": table})
適当な url により、create_table を呼び出せば、ソート可能な表が出力される。
class Organization(models.Model):
organization_id = models.CharField(max_length = 5) # 組織ID
name = models.CharField(max_length = 20) # 組織名
def __unicode__(self):
return self.name
class User(models.Model):
staff_id = models.CharField(max_length = 7) # スタッフID
name = models.CharField(max_length = 15) # スタッフ名
organization = models.ForeignKey(Organization) # 所属組織
本来、組織ID順にソートしたいところだが、実際は組織テーブルへの登録順に表示されてしまう。
組織ID順にソートするためには、組織テーブルに Meta クラスを追加し、デフォルトの取得順序を設定する。
class Organization(models.Model):
organization_id = models.CharField(max_length = 5) # 組織ID
name = models.CharField(max_length = 20) # 組織名
def __unicode__(self):
return self.name
class Meta:
ordering = ["organization_id"]
from django.forms import ModelForm
class TicketRequestForm(ModelForm):
class Meta:
model = Ticket
モデルを利用する場合、フォームから入力する値とシステムが決定する値が混在する場合がある。entrytime = datetime.datetime.today() ticket = Ticket(entrytime = entrytime) ticketrequestform = TicketRequestForm(request.POST, instance = ticket)
wget http://www.djangoproject.com/download/1.4.5/tarball/ tar xzvf Django-1.4.5.tar.gz cd Django-1.4.5 python26 setup.py install次に、django プロジェクトを作成する。
mkdir /var/www/cgi-bin/django cd /var/www/cgi-bin/django django-admin.py startproject testproject開発用サーバを起動し、別端末より、django が動作することを確認する。
cd /var/www/cgi-bin/django/testproject python26 manage.py runserver
curl http://localhost:8000/
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE"><title>Welcome to Django</title>
・・・
<div id="explanation">
<p>
You're seeing this message because you have <code>DEBUG = True</code> in your
Django settings file and you haven't configured any URLs. Get to work!
</p>
</div>
</body></html>
apache 側の設定をpython26-mod_wsgi.conf へ記載する。
WSGIScriptAlias /django /var/www/cgi-bin/django/testproject/testproject/wsgi.py
WSGIPythonPath /var/www/cgi-bin/django/testproject
<IfModule !python_module>
<IfModule !wsgi_module>
LoadModule wsgi_module modules/python26-mod_wsgi.so
</IfModule>
</IfModule>
<Directory /var/www/cgi-bin/django/testproject/testproject>
Order deny,allow
Allow from all
</Directory>
apache を再起動し、apache経由でdjangoの動作を確認する。
service httpd restart
curl http://localhost/django/
<!DOCTYPE html>
<html lang="en"><head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="robots" content="NONE,NOARCHIVE"><title>Welcome to Django</title>
・・・
<div id="explanation">
<p>
You're seeing this message because you have <code>DEBUG = True</code> in your
Django settings file and you haven't configured any URLs. Get to work!
</p>
</div>
</body></html>