Django model总结(上)

Django model是django框架中处于比较核心的一个部位,准备分三个博客从不同的方面分别进行阐述,本文为《上篇》,主要对【a】Model的基本流程,比如它的创建,迁移等;默认行为,以及用定制的行为来覆盖默认的行为;迁移文件相关的操作,比如不同的创建迁移文件的方法,对迁移文件进行重命名,将多个迁移文件压缩成一个迁移文件,迁移文件中的变量的含义,以及迁移文件的回滚【b】数据类型,不同model之间的关系,以及对model的事务管理【c】一些用于减轻数据库与model之间交互作业的工具,比如用fixture文件对model数据进行备份和加载【d】支持软件observer pattern的signal【e】在默认位置以外的配置以及对多种数据库的配置及其在model中的应用。

Django model与迁移流程
Django的主要存储技术是利用关系型数据库,所以Django的model对应的是数据库中的table,该表的表名默认是<app_name>_<model_name>,而model的实例则是该表的一个记录。因为跟数据打交道,所以model经常需要不断的更改,而管理这样的变动是通过迁移文件实现的。

创建Django model
Django model是在每个app中的models.py中,这个models.py文件是当app创建时候就自动创建的。

#demo
from django.db import models
from datetime import date,timedelta
from django.utils import timezone

Create your models here.

class Stores(models.Model):
name=models.CharField(max_length=30,unique_for_date=‘date_lastupdate’,db_column=‘my_custom_name’)
#id=models.AutoField(primary_key=True)
#objects=models.Manage()
address=models.CharField(max_length=30,unique=True)
city=models.CharField(max_length=30)
state=models.CharField(max_length=2)
email=models.EmailField(help_text=‘valide email please’)
date=models.DateField(default=date.today)
datetime=models.DateTimeField(default=timezone.now)
date_lastupdate=models.DateField(auto_now=True)
date_added=models.DateField(auto_now_add=True)
timestamp_lastupdated=models.DateTimeField(auto_now=True)
timestamp_added=models.DateTimeField(auto_now_add=True)
testeditable=models.CharField(max_length=3,editable=False)
def str(self):
return self.name
以上代码就创建了一个model,其中被注释掉的id的AutoField被默认自动添加;被注释掉的objects是model的Manager,负责该Model的增删查改;还包含了很多字段如CharField,DateField等;__str__方法方便model实例的显示;以上具体内容将在下面各个位置进行总结。

最后应注意该app必须被包含在project的settings.py的INSTALLED_APPS列表中。

迁移及基本流程

Django model 数据类型
Django model中的数据类型与在两个层面有关:底层数据库层面和Django/Python层面。

当创建model后,并进行首次迁移,Django产生并执行DDL(Data definition language)来创建数据库表,这个DDL包含了model中各字段的定义,比如Django model的IntegerField被转换为底层数据库的INTEGER,这就意味着如果后面要修改该字段的类型,就必须再次进行迁移操作。

model的数据类型也有在Django/Python层面进行操作的,比如

ITEM_SIZES=(
(‘S’,‘Small’),
(‘M’,‘Medium’),
(‘L’,‘Large’),
(‘P’,‘Portion’)
)
class Menu(models.Model):
name=models.CharField(max_length=30)
def str(self):
return self.name
class Item(models.Model):
menu=models.ForeignKey(Menu,on_delete=models.CASCADE,related_name=‘menus’)
name=models.CharField(max_length=30)
description=models.CharField(max_length=100)
size=models.CharField(choices=ITEM_SIZES,max_length=1)
colories=models.IntegerField(validators=[calorie_watcher])
def str(self):
return self.name
这里,Item的size中有choices,这个限制就是在python层面进行限制的,我们可以通过python manage.py banners 0001来查看(banner 是app名字,0001是首次迁移的前缀):

(env) F:\PycharmProject\webDev\Django project\testBegin>python manage.py sqlmigrate banners 0001
BEGIN;

– Create model Item

CREATE TABLE “banners_item” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “name” varchar(30) NOT NULL, “description” varchar(100) NOT NULL, “size” varchar(1) NOT NULL, “menu_id” integer NOT NULL REFERENCES “banners_menu” (“id”) DEFERRABLE INITIALLY DEFERRED);
COMMIT;
可以发现底层SQL中关于size并没有choice的限制,也就是该限制是在python层面中实施的,即如果后续更改choices,可以不再进行数据迁移。

Data type Django model Data type Django model
Binary BinaryField Boolean BooleanField
Date/time DateField Date/time TimeField
Date/time DurationField Number AutoField
Number BigInteger Number DecimalField
Number FloatField Number IntegerField
Number PositiveIntegerField Number PositiveSmallIntegerField
Text CharField Text TextField
Text CommaSeparatedIntegerField Text EmailField
Text FileField Text FilePathField
Text(specialized) ImageField Text(specialized) GenericIPAddress
Text(specialized) SlugField Text(specialized) URLField
限值:max_length,min_value,max_value,max_digits,decimal_places
对于text-based的字段,max_length限定了最大字符数量;对于IntegerField数据类型,Django提供了min_value来限制其最小值,max_value限制其最大值;对于DecimalField,需要标明max_digits和decimal_places来限制数值的最多的位数和有效值。

Empty,Null,Not Null: Blank 和Null
所有字段默认都是数据库级别的NOT NULL限制(即默认null=False),即如果创建/更新一个NOT NULL字段,必须为该字段提供值,否则数据库拒绝接受该字段;而有时候,允许一个空字段是必要的,因为数据库中可以识别NULL,因此为了允许在数据库层面支持NULL值,可通过null=True进行设置。

除了 null,Django还支持blank选项,该选项默认为False,被用在python/Django层面的校验通过在model上的Form。如果一个字段被声明为blank=True,Django允许在form中留空,否则Django拒绝接受该值。

例如:

class Person(models.Model):
first_name=models.CharField(max_length=30)
middle_name=models.CharField(max_length=30)
last_name=models.CharField(max_length=30)
blank和null的组合 默认(blank=False,null=False) null=True blank=True null=True,blank=True,
Person.objects.create(first_name=‘john’,middle_name=None,last_name=‘Batch’) None被处理为NULL,数据库拒绝 数据库层面可以为NULL None被处理为NULL,数据库拒绝 数据库层面可以为NULL,OK
Person.objects.create(first_name=‘john’,last_name=‘Batch’) 未标明的被当作空字符,数据库层面不拒绝,空字符不是NULL 数据库层面OK 数据库层面OK 数据库层面OK
Person.objects.create(first_name=‘john’,middle_name=‘ ’,last_name=‘Batch’) 数据库层面OK 数据库层面OK 数据库层面OK 数据库层面OK
Form Validation validation error,因为blank=False validation error,因为blank=False 校验成功 校验成功
对于blank,null的参数有四种组合,分别是default(blank=False,null=False),blank=True(null=False),null=True(blank=False),blank=True& null=True,而’middle_name’有三种选择,分别是赋值为None,’’,以及不赋值(使用默认值,等同于赋值为’’),所有一共12种情况(如上表所示),但不管哪种情况,只要null=False,赋值为None在数据库层面不通过,只要blank=False,在form校验时就不通过。

预设定值(predetermined values):default,auto_now,auto_now_add,choices
可使用default对model字段进行默认值设定,该defaut参数既可以是一个值,也可以是方法的引用(method reference),该选项是完全由python/Django层面控制的。

尽管default选项对于text 字段,number字段以及boolean字段都是一样的操作,但对于DateField,DatetimeField来讲,它们有自己独特的默认值设定选项,该选项为auto_now和auto_now_add。

在#demo中,date,datetime字段均用default使用了method reference(注意到datetime的default为timezone.now,date的default用了date.today,这里都使用method reference,因为如果带上(),其实也没有错,但是将在编译阶段就调用了函数,从而得到一个值,不能动态的返回当前计算值)。

对于auto_now和auto_now_add,这两个选项与default类似的地方是都自动为字段提供了默认值,,但也有不同,不同之处在于:(1)仅对字段DateField,DateTimeField有效,对于DateField,auto_now和auto_now_add通过date.today来产生值,对于DateTimeField,auto_now和auto_now_add是通过django.utils.timezone.now来产生值(2)auto_now和auto_now_add不能被覆盖,auto_now选项每当一个record被改变,这个值就会改变,而auto_now_add选项在record存在期间保持不变,这就意味着我们可以用auto_now来追踪record的最近的一次修改,用auto_now_add来追踪record的创建时间(3)需要注意的是,在admin中,auto_now和auto_now_add不显示,因为它们会被自动取值,且不能被覆盖,所有就不显示出来。

另一个预设值是choices,它是在python/Django层面控制的。

Unique:unique,unique_for_date,unique_for_month,unique_for_year
比如name=models.CharField(max_length=30,unique=True),它告诉了Django来确保所有记录都有一个唯一的name。

unique是在数据库层执行的(通过DDL的UNIQUESQL常量),还有Pyhton/Django层面,另外除了ManyToMany,OneToOne,FileField,对于其他的字段都适用。

对于伴随着唯一时间的字段,比如name=models.CharField(max_length=30,unique_for_date=‘date_lastupdated’),不允许同一个name有相同的date_lasupdated字段,而这个validation由于其复杂性,在python/Django层面进行控制。

表单值:Editable,help_text,verbose_name,error_messages
当form的字段由models字段支撑时,form字段可能被models字段的选项所影响。

默认地,所有models字段都是可编辑的,但是可通过editable=False来告诉Django来忽略它,然后任何与它相关的validation也会被忽略。

例如:将#demo中的city改为city=models.CharField(max_length=30,editable=False),经过makemigrations后,再sqlmigrate,查看

BEGIN;

– Alter field city on store

CREATE TABLE “new__customized store” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “city” varchar(30) NOT NULL, “name” varchar(30) NOT NULL, “address” varchar(30) NOT NULL UNIQUE, “state” varchar(2) NOT NULL, “email” varchar(254) NOT NULL, “date” date NOT NULL, “datetime” datetime NOT NULL, “date_lastupdated” date NOT NULL, “date_added” date NOT NULL, “timestamp_lastupdated” datetime NOT NULL, “timestamp_added” datetime NOT NULL);
INSERT INTO “new__customized store” (“id”, “name”, “address”, “state”, “email”, “date”, “datetime”, “date_lastupdated”, “date_added”, “timestamp_lastupdated”, “timestamp_added”, “city”) SELECT “id”, “name”, “address”, “state”, “email”, “date”, “datetime”, “date_lastupdated”, “date_added”, “timestamp_lastupdated”, “timestamp_added”, “city” FROM “customized store”;
DROP TABLE “customized store”;
ALTER TABLE “new__customized store” RENAME TO “customized store”;
COMMIT;
可以发现(1)修改字段是通过新建一个表,将record移植后,删除旧表,再重新更改新表为旧表名字(2)由于设置了city为editable=False,DDL中未出现city,也说明该操作在数据库层面进行的(3)migrate后,查看admin,发现city确实不见了。

之前:

之后:

help_text在旁边给出了关于该字段的解释信息,verbose_name选项使得在表单中输出为该字段的label,error_messages可接受字典,该字典的keys代表错误代码,values是错误信息。

DDL值:db_column,db_index,db_tablespace,primary_key
默认地,Django用model的字段名作为表的column的名字,如果要改变,可以在字段里使用db_column选项,另一个就是db_index选项,但应注意以下两种情况不需要再设定db_index:

unique=True
ForeignKey
比如:修改#demo为

city=models.CharField(max_length=30,db_index=True)
state=models.CharField(max_length=2,db_column=‘customized state JOHNYANG’)
经过sqlmigrate:

CREATE TABLE “new__customized store” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “name” varchar(30) NOT NULL, “address” varchar(30) NOT NULL UNIQUE, “city” varchar(30) NOT NULL, “email” varchar(254) NOT NULL, “date” date NOT NULL, “datetime” datetime NOT NULL, “date_lastupdated” date NOT NULL, “date_added” date NOT NULL, “timestamp_lastupdated” datetime NOT NULL, “timestamp_added” datetime NOT NULL, “customized state JOHNYANG” varchar(2) NOT NULL);
INSERT INTO “new__customized store” (“id”, “name”, “address”, “city”, “email”, “date”, “datetime”, “date_lastupdated”, “date_added”, “timestamp_lastupdated”, “timestamp_added”, “customized state JOHNYANG”) SELECT “id”, “name”, “address”, “city”, “email”, “date”, “datetime”, “date_lastupdated”, “date_added”, “timestamp_lastupdated”, “timestamp_added”, “state” FROM “customized store”;
DROP TABLE “customized store”;
ALTER TABLE “new__customized store” RENAME TO “customized store”;
CREATE INDEX “customized store_city_5ed81ba0” ON “customized store” (“city”);
COMMIT;
可以发现state字段消失,增加了customized state JOHNYSNG,和最后CREATE INDEX “customized store_city_5ed81ba0” ON “customized store” (“city”)。

最后,primary_key选项允许对Model定义一个主键,如果没有一个字段定义primary_key=True,则自动创建一个名为id的AutoField字段来充当主键(系统自动执行id=models.AutoField(primary_key=True).

内置和自定义校核器:validators
除了数据类型,长度限制,预设值等之前的选项的约束限制,Django还提供了validator选项(赋值为列表),来允许进行更复杂,高级的逻辑校核。

在django.core.validators包中提供了一系列内置的校核方法。比如models.EmailField数据类型依赖django.core.validators.EmailValidator来校核email值,而models.IntegerField使用MinValueValidator和MaxValueValidator来对min_value和max_value来进行校核。

除了内置validator方法,也可以自定义validator方法,定义该方法很简单,只需要接受一个字段为输入参数,然后如果不满足某个条件就抛出django.core.exceptions.ValidatorError就可以。

ITEM_SIZE=(
(‘S’,‘Small’),
(‘M’,‘Medium’),
(‘L’,‘Large’),
(‘P’,‘Portion’)
)
from django.core.exceptions import ValidationError
def calorie_watcher(value):
if value>5000:
raise ValidationError((‘calories are %(value)s? try something less than 5000’),params={‘value’:value})
if value<0:
raise ValidationError((‘Strange calories are %(value)s’),params={‘value’:value})

class Menu(models.Model):
name=models.CharField(max_length=30)
def str(self):
return self.name

class Item(models.Model):
menu=models.ForeignKey(Menu,on_delete=models.CASCADE)
name=models.CharField(max_length=30)
description=models.CharField(max_length=100)
price=models.FloatField(blank=True,null=True)
size=models.CharField(choices=ITEM_SIZE,max_length=1)
calories=models.IntegerField(validators=[calorie_watcher])
def str(self):
return ‘Menu %s name %s’ %(self.menu,self.name )

在admin中(需要注意的是如果要在admin中管理数据库,需要在admin.py对需要管理的表进行注册,如

from django.contrib import admin

Register your models here.

from .models import Question,Choice,Store,Menu,Item
admin.site.register((Question,Choice,Store,Menu,Item))
)对Item进行添加,如果calorie小于0,可以看到报错信息:

Django model默认和定制的行为
Django对Model提供了很多函数,比如基本操作save(),delete(),还有命名惯例以及查询行为等。

Model方法
所有model都继承了一系列方法,如保存,删除,校核,加载,还有对model 数据施加特定的逻辑等。

save()
save()方法是最常见的一个操作,对一个记录进行保存。一旦创建或者获取了model instance的reference,则可以调用save()来进行创建/更新 该instance。

那么django是如何判定一个save()到底是该创建还是更新一个instance?

它是通过id来进行判断的,如果reference的id在数据库中还没有,那么创建,如果已经有了则是更新。

save()方法可接受的参数如下:

参数 默认值 描述
force_insert False 显式的告诉Django对一个记录进行创建(force_insert=True)。极少这样用,但是对于不能依靠Django来决定是否创建的情况是有用的。
force_update False 显式的告诉Django对一个记录进行更新(force_update=True)。极少这样用,但是对于不能依靠Django来决定是否更新的情况是有用的。
using DEFAULT_DB_ALLAS 允许save()对settings.py中不是默认值的数据库进行保存/更新操作(比如,using=‘oracle’,这里’oracle’必须是settings.py的’DATABASES’变量的一个key),详细用法见本文多数据库部分总结
update_fields None 接受包含多个字段的list(比如save(update_fields)=[‘name’]),仅更新list中的字段。当有比较大的model,像进行更有效率更精细的更新,可以使用该选项。
commit True 确保记录保存到了数据库。在特定情况下(比如,models forms或者关系型操作),commit被设定为False,来创建一个instance,而不将其保存到数据库。这允许基于它们的输出来进行额外的操作 。
class Store(models.Model):
name=models.CharField(max_length=30)
address=models.CharField(max_length=30)
city=models.CharField(max_length=30)
state=models.CharField(max_length=2)
def save(self,*args,**kwargs):
#Do custom logic here(e.g. validation,logging,call third party service)
#Run default save() method
super().save(*args,**kwargs)

也可以对save()method进行重写,可以在它之前或者之后做一些事情。

delete()
该方法是通过一个reference来从数据库中消除一条记录。delete()实际上是依靠id主键来移除一个记录,所以对于一个reference应该有id值来进行delete()操作。

当delete()被一个reference调用时,它的id主键被移除,但它剩余的值还保存在内存中。另外它用删除记录的数量作为回应。比如(1, {‘testapp.Item’: 1}).

与save()类似,delete()也接受两个参数:using=DEFAULT_DB_ALIAS,keep_parents=False。using允许对其他数据库进行delete操作,当delete()发生在关系型model,希望保持parent model完整或者移除,keep_parents是很有用的。

最后,也可以对delete()方法进行重写。

校验方法:clean_fields(),clean(),validate_unique,full_clean()
理解校验方法最重要的部分还是从两方面进行:数据库层面和Python/Django层面。

对于数据库层面的校验,在第一次迁移时就自动完成了,而对于Python/Django层面,必须调用校验函数来进行校验。

需要注意的是:对于sqlite3,除primary key必须是整数外,其他的数据类型并没有严格的校核,Char(10)的含义是至少占用10个字节,所以会出现,如果直接创建一个超过10个字节的记录,也是可以保持到数据库的现象。

比如:

image-20201019103900920

s=Stores.objects.create(name=‘this is a veryvery long name which exceeds 30 characters let us see if it will raise an error’,address=‘cd’,city=‘cd’,state=‘ca’,email=‘sdfkjs@qq.com’)
len(‘this is a veryvery long name which exceeds 30 characters let us see if it will raise an error’)
93
clean_fields()
尽管可以通过调用save()来让数据库校验字段的合法性(对sqlite3,数据库不对字段进行数据类型检查,除primary key外),但也可以通过clean_fields()在Python/Django层面进行字段数据类型的合法性检验。

s.clean_fields()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 1253, in clean_fields
raise ValidationError(errors)
django.core.exceptions.ValidationError: {‘name’: [‘Ensure this value has at most 30 characters (it has 93).’]}
validate_unique()
对于有unique选项的字段,可通过记录实例的validate_unique()方法进行unique检验。

p=Stores(name=‘testname’,address=‘科华北路’,city=‘cd’,state=‘ca’,email=‘sjkfd@qq.com’)
p.validate_unique()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 1013, in validate_unique
raise ValidationError(errors)
django.core.exceptions.ValidationError: {‘address’: [‘Stores with this Address already exists.’]}
除了对字段的unique选项进行unique检验,validate_unique()还对model的Meta class的unique_together属性(赋值为元组)进行检验,即多个字段组成的唯一性。

例如:

class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
class Meta:
unique_together=(‘test0’,‘test1’)
(env) F:\PycharmProject\webDev\Django project\testBegin>python manage.py sqlmigrate banners 0007
CREATE TABLE “banners_testall” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “test0” varchar(3) NOT NULL, “test1” varchar(3) NOT NULL);
CREATE UNIQUE INDEX “banners_testall_test0_test1_2f0f2688_uniq” ON “banners_testall” (“test0”, “test1”);

from banners.models import *
s=TestAll(test0=‘a’,test1=‘b’)
ss=TestAll(test0=‘a’,test1=‘b’)
ss.validate_unique()
s.validate_unique()
s.save()
ss.validate_unique()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 1013, in validate_unique
raise ValidationError(errors)
django.core.exceptions.ValidationError: {‘all’: [‘Test all with this Test0 and Test1 already exists.’]}

s.validate_unique()
ss.save()
Traceback (most recent call last):
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 84, in _execute
return self.cursor.execute(sql, params)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\sqlite3\base.py”, line 413, in execute
return Database.Cursor.execute(self, query, params)
sqlite3.IntegrityError: UNIQUE constraint failed: banners_testall.test0, banners_testall.test1

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 751, in save
force_update=force_update, update_fields=update_fields)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 789, in save_base
force_update, using, update_fields,
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 892, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 932, in _do_insert
using=using, raw=raw,
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\manager.py”, line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\query.py”, line 1249, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\sql\compiler.py”, line 1395, in execute_sql
cursor.execute(sql, params)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 98, in execute
return super().execute(sql, params)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 84, in _execute
return self.cursor.execute(sql, params)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\utils.py”, line 90, in exit
raise dj_exc_value.with_traceback(traceback) from exc_value
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\utils.py”, line 84, in _execute
return self.cursor.execute(sql, params)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\backends\sqlite3\base.py”, line 413, in execute
return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: UNIQUE constraint failed: banners_testall.test0, banners_testall.test1

sss=TestAll(test0=‘a’,test1=‘b’)
sss.validate_unique()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 1013, in validate_unique
raise ValidationError(errors)
django.core.exceptions.ValidationError: {‘all’: [‘Test all with this Test0 and Test1 already exists.’]}

可见,当s保存前,s与ss并不冲突,但是当s保存后,再调用ss.validate_unique()报错。

clean()
除了clean_fields(),还有clean(),用来提供更灵活的校验方法(比如特定的关系或者值)。

例如:

from django.core.exceptions import ValidationError
class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
def clean(self):
if self.test0==self.test1:
raise ValidationError(‘test0 shall not equil to test1’)

from banners.models import *
ss=TestAll(test0=‘c’,test1=‘c’)
ss.save()
ss.clean()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\testBegin\banners\models.py”, line 99, in clean
raise ValidationError(‘test0 shall not equil to test1’)
django.core.exceptions.ValidationError: [‘test0 shall not equil to test1’]
full_clean()
最后是full_clean(),它是依次执行clean_fields(),clean(),validate_unique().

数据加载方法:refresh_from_db()
当数据库被另一个进程更新,或者不小心改变了model instance的值,也就是想用数据库中的数据来更新model instance的值,refresh_from_db()方法就是用来做这件事的方法.

尽管一般都是不带参数的使用refresh_from_db(),但它可以接受两个参数:(1)using,该参数跟save(),delete()方法中的含义一样(2)fields,用来挑选需要refresh的字段,如果没有指定,则refresh model的所有字段.

from_db(),get_deferred_fields()用来定制加载数据过程,用的情况相对比较少,详见https://docs.djangoproject.com/en/3.1/ref/models/instances/

定制方法
例:

from django.core.exceptions import ValidationError
class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
def clean(self):
if self.test0==self.test1:
raise ValidationError(‘test0 shall not equil to test1’)
def special(self):
return self.test0,self.test1

from banners.models import *
s=TestAll.objects.all().first()
s.test0
‘a’

s.special()
(‘a’, ‘b’)
Model 管理字段:Objects
objects字段是所有Django models的默认管理字段,用来管理各种query操作(增删查改).

它是直接用在class上,而不是instance上,比如,要读取Store的id=1的记录,可以Store.objects.get(id=1),而删除所有记录则可以Store.objects.all().delete().

可以定制管理字段,比如重命名为mgr,则只需要添加类属性mgr=models.Manager().

Model Meta class及选项
Django中的Meta类是用来把model的行为作为一个整体进行定义,与数据类型不同,后者在字段上定义了更精细的行为.

比如为了避免不断的显式的声明一个model的搜索顺序,可以直接在Meta 类中定义ordering.

比如:

class Stores(models.Model):
name=models.CharField(max_length=30,unique_for_date=‘date_lastupdate’,db_column=‘my_custom_name’)
address=models.CharField(max_length=30,unique=True)
city=models.CharField(max_length=30)
state=models.CharField(max_length=2)
email=models.EmailField(help_text=‘valide email please’)
date=models.DateField(default=date.today)
datetime=models.DateTimeField(default=timezone.now)
date_lastupdate=models.DateField(auto_now=True)
date_added=models.DateField(auto_now_add=True)
timestamp_lastupdated=models.DateTimeField(auto_now=True)
timestamp_added=models.DateTimeField(auto_now_add=True)
testeditable=models.CharField(max_length=3,editable=False)
def str(self):
return self.name
class Meta:
ordering=[’-timestamp_added’]

a=Stores.objects.all()
for i in a:
… print(i.timestamp_added)

2020-10-19 02:38:22.767910+00:00
2020-09-28 07:45:12.708000+00:00
2020-09-28 05:05:08.066000+00:00
可以看到是按照timestamp_added降序排列的.

DDL table options: db_table,db_tablespace,managed,unique_together
db_table
默认地,创建表的名字为<app_name>_<model_name>,比如,app名字为’banners’,model名字为’testall’,那么创建的表名为’banners_testall’.

sqlite> .tables
auth_group banners_entry_authors
auth_group_permissions banners_item
auth_permission banners_menu
auth_user banners_question
auth_user_groups banners_stores
auth_user_user_permissions banners_testall
banners_author django_admin_log
banners_blog django_content_type
banners_choice django_migrations
banners_entry django_session
现在添加meta option:

class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
def clean(self):
if self.test0==self.test1:
raise ValidationError(‘test0 shall not equil to test1’)
def special(self):
return self.test0,self.test1
class Meta:
unique_together=(‘test0’,‘test1’)
db_table=‘specialTestAll’ #添加db_table
(env) F:\PycharmProject\webDev\Django project\testBegin>python manage.py sqlmigrate banners 0008
BEGIN;

– Rename table for testall to specialTestAll

ALTER TABLE “banners_testall” RENAME TO “specialTestAll”;
COMMIT;
可见,已经将表名进行了更改。

db_tablespace
默认地,如果Django的数据库支持(比如Oracle)tablespace的概念,Django 就用settings.py中的DEFAULT_TABLESPACE变量作为默认的tablespace.也可以通过meta的db_tablespace选项来对model设置其他的tablespace.

Django管理创建/销毁数据表,如果不需要这样的管理,可以设置meta的managed=False。

DDL index options: indexes,index_together
Index在关系型数据库记录的高效查询中是非常重要的,简单的说,它是包含了用于确保查询速度更快的包含了特定记录的column values。

Django meta类提供了2个选项来对model字段的index创建相应的DDL (如CREATE INDEX…):indexes,index_together.

对于primary key和unique的字段,不需要再进行标注为index。

index参数可接受包含多个models.Index实例的列表,models.Index实例接受fields列表,其包含了需要被index的字段名,和name,用于命名Index的名字,缺省情况下,自动为其进行命名。

from django.core.exceptions import ValidationError
class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
test2=models.CharField(max_length=3)
test3=models.CharField(max_length=3)
def clean(self):
if self.test0==self.test1:
raise ValidationError(‘test0 shall not equil to test1’)
def special(self):
return self.test0,self.test1
class Meta:
unique_together=(‘test0’,‘test1’)
db_table=‘specialTestAll’
indexes=[
models.Index(fields=[‘test0’,‘test1’]),
models.Index(fields=[‘test0’],name=‘test0_idx’)
]
index_together=[‘test2’,‘test3’]
(env) F:\PycharmProject\webDev\Django project\testBegin>python manage.py sqlmigrate banners 0009
BEGIN;
CREATE UNIQUE INDEX “specialTestAll_test0_test1_f3575fe2_uniq” ON “specialTestAll” (“test0”, “test1”);

– Alter index_together for testall (1 constraint(s))

CREATE INDEX “specialTestAll_test2_test3_20a904e7_idx” ON “specialTestAll” (“test2”, “test3”);

– Create index specialTest_test0_eb859d_idx on field(s) test0, test1 of model testall

CREATE INDEX “specialTest_test0_eb859d_idx” ON “specialTestAll” (“test0”, “test1”);

– Create index test0_idx on field(s) test0 of model testall

CREATE INDEX “test0_idx” ON “specialTestAll” (“test0”);
COMMIT;
index_together允许定义多字段index,index_together=[‘test0’,‘test1’]等效于indexes=[models.Index(fields=[‘test0’,‘test1’]) ].

命名选项:verbose_name,verbose_name_plural,label,label_lower,app_label
默认地,Django models是通过类名来refer model的,绝大多数都是可以的。但是对于有些情况,比如,做开发的时候,类名使用了缩写,但如果想要在UI上,或者admin中不这样显示,该怎么办呢?

这就是verbose_name出现的原因了,verbose_name_plural是对英语的复数,比如class Choice的复数显示是choices。

class TestAll(models.Model):
test0=models.CharField(max_length=3)
test1=models.CharField(max_length=3)
test2=models.CharField(max_length=3)
test3=models.CharField(max_length=3)
class Meta:
verbose_name=‘verboseTestAll’
verbose_name_plural=‘VerboseTestAllPlural’

在admin中:

image-20201020203055640

from testapp.models import *
TestAll._meta.verbose_name
‘verboseTestAll’

TestAll._meta.verbose_name_plural
‘VerboseTestAllPlural’

TestAll._meta.label
‘testapp.TestAll’

TestAll._meta.label_lower
‘testapp.testall’

继承 Meta option: Abstract and proxy
类似于OOP的继承,这里model 的Meta类也有类似的概念,分别是abstract和proxy。

Abstract
对于abstract,它的用法是在model的Meta class中声明abstract=True,这样该model就变成了一个类似于base class的model,它不创建表,而继承它的class自动获取它定义的所有字段。

Proxy
与abstract相反,它的用法是base class就是正常的model,在其子类的Meta class中声明proxy=True,子类不会创建新的表,子类所定义的行为选项都好像是直接作用在基类上的,但真正的基类的行为选项并没有实质被改变,可以理解为子类对基类的修修补补,但还是作用在基类的表上的。

简单总结下就是:在abstract和proxy情况下,带有meta的没有表,abstract出现在基类meta中,proxy 出现在子类的meta中。

class TestAbs(models.Model):
test=models.CharField(max_length=3)
class Meta:
abstract=True
class subAbs(TestAbs):
pass

class TestProxy(models.Model):
test=models.CharField(max_length=3)

class subPro(TestProxy):
class Meta:
proxy=True
(env) E:\programming\DjangoProject\TangleWithTheDjango\testDebug>python manage.py sqlmigrate testapp 0014
BEGIN;

– Create model subAbs

CREATE TABLE “testapp_subabs” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “test” varchar(3) NOT NULL);

– Create model TestProxy

CREATE TABLE “testapp_testproxy” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “test” varchar(3) NOT NULL);

– Create proxy model subPro

COMMIT;
Query Meta option: Ordering,order_with_respect_to,get_latest_by,default_manager_name,default_related_name,select_on_save
当进行django model query时,有很多默认的行为,如果要用非默认的query行为,则需要显式的参数显式的调用query的各种方法。然而,一次又一次的这样做,无聊且易错,所以我们可以依靠本节的query meta option来改变model query的各种默认行为。

ordering
ordering是用来定义默认的排序的,比如Store.objects.all().sort_by(’-name’)是按照name降序排列,等效为ordering=[’-name’],需要注意的是赋值为列表类型。

order_with_respect_to

按照某字段进行排序,通常是外键,这样就可以使相互关联的object允许它的parent object(parent object的id就是子object 的外键)来通过get_RELATED_order,set_RELATED_ORDER来获得及设定子object的顺序。比如:

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()-timedelta(days=1)
class Answer(models.Model):
question=models.ForeignKey(Question,on_delete=models.CASCADE)
;sqlmigrate来查看其底层SQL语句
CREATE TABLE “banners_question” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “question_text” varchar(200) NOT NULL, “pub_date” datetime NOT NULL);
CREATE TABLE “banners_answer” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “question_id” integer NOT NULL REFERENCES “banners_question” (“id”) DEFERRABLE INITIALLY DEFERRED, “_order” integer NOT NULL);
CREATE INDEX “banners_answer_question_id_b2a3fa7a” ON “banners_answer” (“question_id”);

from banners.models import *
import datetime
Question.objects.create(question_text=‘what?’,pub_date=datetime.date.today())
F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\fields_init_.py:1312: RuntimeWarning: DateTimeField Question.pub_date received a naive datetime (2020-10-21 00:00:00) while time zone support
is active.
RuntimeWarning)
<Question: what?>

s=Question.objects.get(id=1)
s
<Question: what?>

s.pub_date
datetime.datetime(2020, 10, 20, 16, 0, tzinfo=)

Answer.objects.create(question=s)
<Answer: Answer object (1)>

Answer.objects.cretae(question=s)
Traceback (most recent call last):
File “”, line 1, in
AttributeError: ‘Manager’ object has no attribute ‘cretae’

Answer.objects.create(question=s)
<Answer: Answer object (2)>

Answer.objects.create(question=s)
<Answer: Answer object (3)>

s.get_answer_order()
<QuerySet [1, 2, 3]>

s.set_answer_order([3,1,2])
a=Answer.objects.get(id=2)
a.get_next_in_order()
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\base.py”, line 981, in _get_next_or_previous_in_order
}).order_by(order)[:1].get()
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\query.py”, line 431, in get
self.model._meta.object_name
banners.models.Answer.DoesNotExist: Answer matching query does not exist.

a.get_previous_in_order()
<Answer: Answer object (1)>
get_latest_by

在Meta中,get_latest_by是DateField,DateTimeField,IntegerField的字段的名字,或包含这种字段名字的列表。这样就可以用Manager的latest()和earliest()方法。

比如:

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()-timedelta(days=1)
class Meta:
get_latest_by=‘pub_date’

;查看sqlmigrate
(env) F:\PycharmProject\webDev\Django project\testBegin>python manage.py sqlmigrate banners 0011
BEGIN;

– Change Meta options on question


– Set order_with_respect_to on answer to None

CREATE TABLE “new__banners_answer” (“id” integer NOT NULL PRIMARY KEY AUTOINCREMENT, “question_id” integer NOT NULL REFERENCES “banners_question” (“id”) DEFERRABLE INITIALLY DEFERRED);
INSERT INTO “new__banners_answer” (“id”, “question_id”) SELECT “id”, “question_id” FROM “banners_answer”;
DROP TABLE “banners_answer”;
ALTER TABLE “new__banners_answer” RENAME TO “banners_answer”;
CREATE INDEX “banners_answer_question_id_b2a3fa7a” ON “banners_answer” (“question_id”);
COMMIT;

from banners.models import *
import datetime
datetime.date(2019,8,19)
datetime.date(2019, 8, 19)

Question.objects.create(question_text=‘how?’,pub_date=datetime.date(2019,3,4))
F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\fields_init_.py:1312: RuntimeWarning: DateTimeField Question.pub_date received a naive datetime (2019-03-04 00:00:00) while time zone support
is active.
RuntimeWarning)
<Question: how?>

Question.objects.create(question_text=‘when?’,pub_date=datetime.date(2017,2,2))
F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\fields_init_.py:1312: RuntimeWarning: DateTimeField Question.pub_date received a naive datetime (2017-02-02 00:00:00) while time zone support
is active.
RuntimeWarning)
<Question: when?>

Question.objects.create(question_text=‘where?’,pub_date=datetime.day(2018,3,3))
Traceback (most recent call last):
File “”, line 1, in
AttributeError: module ‘datetime’ has no attribute ‘day’

Question.objects.create(question_text=‘where?’,pub_date=datetime.date(2018,3,3))
F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\fields_init_.py:1312: RuntimeWarning: DateTimeField Question.pub_date received a naive datetime (2018-03-03 00:00:00) while time zone support
is active.
RuntimeWarning)
<Question: where?>

Question.objects.latest()
<Question: what?>

Question.objects.earliest()
<Question: when?>

s=Question.objects.earliest()
s.pub_date
datetime.datetime(2017, 2, 1, 16, 0, tzinfo=)

Answer.objects.latest() #可以看到,没有设定get_latest_by,就不能用manager的latest方法
Traceback (most recent call last):
File “”, line 1, in
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\manager.py”, line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\query.py”, line 674, in latest
return self.reverse()._earliest(*fields)
File “F:\PycharmProject\webDev\Django project\env\lib\site-packages\django\db\models\query.py”, line 658, in _earliest
"earliest() and latest() require either fields as positional "
ValueError: earliest() and latest() require either fields as positional arguments or ‘get_latest_by’ in the model’s Meta.
default_manager_name
所有的models都将objects作为默认的model manager,但是当存在多个manager时,就必须指定哪个才是默认的manger,这时候,就需要在meta中对default_manager_name进行指定。

default_related_name
对于相互有关系的object,可以通过parent object 来反向得到子object:

from banners.models import *
q=Question.objects.get(id=1)
q.answer_set.get(id=1)
<Answer: Answer object (1)>
这里,默认是<model_name>_set,所以在本例中为answer_set.

因为对于字段的反向名字应该是唯一的.所以在abstract subclass情况下需要注意不能冲突,可以用包含’%(app_label)s’和’%(model_name)s’来规避这种冲突.
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2083
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2082
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2081
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2080
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2079
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2078
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2077
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2076
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2075
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2074
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2073
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2072
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2071
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2070
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2069
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2068
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2067
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2066
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2065
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2064
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2063
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2062
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2061
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2060
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2059
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2058
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2057
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2056
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2055
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2054
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2053
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2052
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2051
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2050
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2049
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2048
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2047
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2046
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2045
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2044
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2043
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2042
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2041
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2040
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2039
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2038
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2037
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2036
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2035
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2034
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2033
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2032
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2031
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2030
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2029
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2028
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2027
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2026
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2025
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2024
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2023
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2022
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2021
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2020
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2019
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2018
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2017
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2016
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2015
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2014
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2013
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2012
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2011
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2010
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2009
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2008
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2007
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2006
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2005
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2004
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2003
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2002
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2001
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=2000
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1999
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1998
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1997
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1996
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1995
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1994
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1993
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1992
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1991
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1990
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1989
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1988
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1987
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1986
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1985
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1984
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1983
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1982
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1981
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1980
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1979
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1978
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1977
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1976
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1975
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1974
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1973
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1972
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1971
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1970
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1969
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1968
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1967
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1966
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1965
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1964
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1963
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1962
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1961
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1960
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1959
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1958
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1957
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1956
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1955
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1954
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1953
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1952
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1951
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1950
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1949
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1948
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1947
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1946
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1945
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1944
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1943
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1942
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1941
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1940
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1939
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1938
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1937
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1936
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1935
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1934
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1933
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1932
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1931
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1930
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1929
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1928
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1927
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1926
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1925
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1924
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1923
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1922
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1921
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1920
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1919
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1918
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1917
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1916
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1915
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1914
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1913
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1912
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1911
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1910
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1909
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1908
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1907
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1906
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1905
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1904
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1903
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1902
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1901
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1900
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1899
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1898
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1897
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1896
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1895
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1894
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1893
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1892
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1891
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1890
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1889
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1888
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1887
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1886
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1885
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1884
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1883
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1882
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1881
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1880
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1879
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1878
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1877
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1876
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1875
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1874
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1873
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1872
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1871
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1870
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1869
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1868
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1867
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1866
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1865
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1864
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1863
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1862
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1861
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1860
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1859
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1858
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1857
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1856
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1855
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1854
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1853
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1852
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1851
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1850
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1849
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1848
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1847
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1846
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1845
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1844
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1843
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1842
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1841
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1840
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1839
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1838
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1837
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1836
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1835
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1834
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1833
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1832
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1831
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1830
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1829
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1828
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1827
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1826
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1825
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1824
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1823
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1822
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1821
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1820
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1819
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1818
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1817
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1816
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1815
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1814
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1813
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1812
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1811
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1810
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1809
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1808
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1807
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1806
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1805
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1804
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1803
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1802
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1801
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1800
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1799
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1798
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1797
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1796
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1795
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1794
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1793
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1792
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1791
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1790
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1789
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1788
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1787
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1786
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1785
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1784
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1783
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1782
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1781
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1780
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1779
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1778
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1777
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1776
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1775
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1774
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1773
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1772
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1771
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1770
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1769
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1768
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1767
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1766
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1765
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1764
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1763
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1762
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1761
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1760
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1759
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1758
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1757
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1756
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1755
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1754
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1753
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1752
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1751
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1750
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1749
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1748
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1747
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1746
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1745
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1744
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1743
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1742
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1741
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1740
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1739
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1738
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1737
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1736
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1735
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1734
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1733
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1732
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1731
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1730
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1729
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1728
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1727
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1726
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1725
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1724
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1723
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1722
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1721
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1720
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1719
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1718
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1717
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1716
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1715
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1714
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1713
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1712
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1711
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1710
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1709
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1708
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1707
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1706
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1705
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1704
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1703
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1702
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1701
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1700
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1699
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1698
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1697
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1696
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1695
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1694
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1693
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1692
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1691
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1690
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1689
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1688
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1687
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1686
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1685
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1684
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1683
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1682
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1681
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1680
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1679
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1678
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1677
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1676
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1675
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1674
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1673
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1672
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1671
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1670
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1669
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1668
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1667
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1666
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1665
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1664
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1663
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1662
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1661
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1660
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1659
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1658
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1657
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1656
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1655
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1654
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1653
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1652
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1651
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1650
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1649
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1648
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1647
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1646
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1645
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1644
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1643
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1642
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1641
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1640
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1639
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1638
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1637
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1636
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1635
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1634
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1633
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1632
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1631
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1630
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1629
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1628
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1627
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1626
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1625
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1624
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1623
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1622
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1621
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1620
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1619
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1618
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1617
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1616
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1615
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1614
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1613
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1612
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1611
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1610
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1609
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1608
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1607
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1606
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1605
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1604
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1603
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1602
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1601
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1600
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1599
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1598
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1597
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1596
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1595
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1594
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1593
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1592
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1591
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1590
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1589
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1588
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1587
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1586
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1585
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1584
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1583
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1582
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1581
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1580
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1579
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1578
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1577
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1576
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1575
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1574
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1573
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1572
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1571
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1570
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1569
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1568
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1567
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1566
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1565
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1564
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1563
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1562
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1561
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1560
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1559
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1558
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1557
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1556
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1555
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1554
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1553
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1552
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1551
http://xunlan.chd.edu.cn/chdbbs/forum.php?mod=viewthread&tid=1550

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值