From: erickson Date: Wed, 28 Mar 2007 21:42:32 +0000 (+0000) Subject: changed file layout and settings file to support the django multiple-database layout... X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=15cb9d4d45af044cdffe63551604401053201d58;p=Evergreen.git changed file layout and settings file to support the django multiple-database layout code. django tables now go into the (default) sqlite3 database, while the ILS files are still loaded from the (alternate) evergreen postgress database git-svn-id: svn://svn.open-ils.org/ILS/trunk@7120 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- diff --git a/Open-ILS/admin/ils_admin/README b/Open-ILS/admin/ils_admin/README index e8cf014a07..59ccf2c6e1 100644 --- a/Open-ILS/admin/ils_admin/README +++ b/Open-ILS/admin/ils_admin/README @@ -1,38 +1,15 @@ 1. Set up the database params in settings.py -2. Comment out the following item in the INSTALLED_APPS variable in settings.py (around line 80): 'ils_admin.setup', - * If this is not commented out, Django will attempt to create tables for the ILS models, which - could cause the creation of duplicate tables with slightly different names/layouts * -3. Run "python manage.py syncdb". This will install the necessary Django tables in the database -4. Uncomment the line commented out in #2. +2. Run "python manage.py syncdb" from within OpenILS/admin/ils_admin directory. + This will install the necessary Django tables in the database. - To test the base Django app installation, you can run "python manage.py shell" to access the models directly. - Also, see http://www.djangoproject.com/documentation/tutorial1/ +see http://www.djangoproject.com/documentation/ for more. -5. Add an Apache config similar to the one below (requires mod_python): - - - # Protect this sensitive sight - Order deny,allow - Deny from all - Allow from 10.0.0.0/8 - SetHandler mod_python - - # set up the python/django handlers - PythonHandler django.core.handlers.modpython - SetEnv DJANGO_SETTINGS_MODULE ils_admin.settings - PythonPath "['/openils/var/admin/', '/usr/lib/python2.4/site-packages/'] +sys.path" - - # set up some good development settings - PythonAutoReload On - PythonDebug On - - -6. Add a symlink to "media" in your document root (e.g /openils/var/web) to the admin media dir: +3. If you use Apache2/mod_python, create a symlink to "media" in your document root (e.g /openils/var/web) to the admin media dir: e.g. /usr/lib/python2.4/site-packages/django/contrib/admin/media/ This can also be accomplished with an Alias directive in Apache config -7. Start apache +... should we create a default django.db to distribute? diff --git a/Open-ILS/admin/ils_admin/settings.py b/Open-ILS/admin/ils_admin/settings.py index 1cdbba4e92..b9b9bf2aca 100644 --- a/Open-ILS/admin/ils_admin/settings.py +++ b/Open-ILS/admin/ils_admin/settings.py @@ -9,14 +9,31 @@ ADMINS = ( MANAGERS = ADMINS -DATABASE_ENGINE = 'postgresql' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. -DATABASE_NAME = '' # Or path to database file if using sqlite3. -DATABASE_SCHEMAS = 'public, permission, actor' # Only used with postgresq to support multiple schemas +DATABASE_ENGINE = 'sqlite3' # 'postgresql', 'mysql', 'sqlite3' or 'ado_mssql'. +DATABASE_NAME = '/openils/var/data/django.db' # Or path to database file if using sqlite3. +DATABASE_SCHEMAS = '' DATABASE_USER = '' # Not used with sqlite3. DATABASE_PASSWORD = '' # Not used with sqlite3. DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. +""" +2007-03-28: the "django" user in the primary ILS database needs to have +the following schemas set in the default search path: actor, permission, public, config +""" + +OTHER_DATABASES = { + 'ils_data': { + 'DATABASE_ENGINE' : 'postgresql', + 'DATABASE_NAME' : 'evergreen', + 'DATABASE_HOST' : '127.0.0.1', + 'DATABASE_PORT' : '5432', + 'DATABASE_USER' : 'django', + 'DATABASE_PASSWORD' : '', + 'MODELS': ['ils_data'] + }, +} + # Local time zone for this installation. All choices can be found here: # http://www.postgresql.org/docs/current/static/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE TIME_ZONE = 'America/New_York' @@ -76,7 +93,8 @@ INSTALLED_APPS = ( 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', - 'django.contrib.admin', - 'ils_admin.setup', + 'django.contrib.admin', + 'ils_admin.setup', + 'ils_admin.setup.ils_data', # load the ILS models ) diff --git a/Open-ILS/admin/ils_admin/setup/ils_data/__init__.py b/Open-ILS/admin/ils_admin/setup/ils_data/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Open-ILS/admin/ils_admin/setup/ils_data/models.py b/Open-ILS/admin/ils_admin/setup/ils_data/models.py new file mode 100644 index 0000000000..3b9b63e6d6 --- /dev/null +++ b/Open-ILS/admin/ils_admin/setup/ils_data/models.py @@ -0,0 +1,298 @@ +from django.db import models +from django.db.models import signals +from django.dispatch import dispatcher + +# ?i18n? +INTERVAL_HELP_TEXT = 'examples: "1 hour", "14 days", "3 months", "DD:HH:MM:SS.ms"' + + +#PG_SCHEMAS = "actor, permission, public, config" + + + +class GrpTree(models.Model): + name = models.CharField(maxlength=100) + parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent') + description = models.CharField(blank=True, maxlength=200) + perm_interval = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT) + application_perm = models.CharField(blank=True, maxlength=100) + usergroup = models.BooleanField() + class Admin: + list_display = ('name', 'description') + list_filter = ['parent_id'] + search_fields = ['name', 'description'] + class Meta: + db_table = 'grp_tree' + ordering = ['name'] + verbose_name = 'User Group' + def __str__(self): + return self.name + +class OrgUnitType(models.Model): + name = models.CharField(maxlength=100) + opac_label = models.CharField(maxlength=100) + depth = models.IntegerField() + parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent') + can_have_vols = models.BooleanField() + can_have_users = models.BooleanField() + class Meta: + db_table = 'org_unit_type' + verbose_name = 'Library Type' + class Admin: + list_display = ('name', 'depth') + list_filter = ['parent_id'] + ordering = ['depth'] + def __str__(self): + return self.name + +class OrgUnitSetting(models.Model): + org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit') + name = models.CharField(maxlength=200) + value = models.CharField(maxlength=200) + class Admin: + list_display = ('org_unit_id', 'name', 'value') + search_fields = ['name', 'value'] + list_filter = ['name', 'org_unit_id'] + class Meta: + db_table = 'org_unit_setting' + ordering = ['org_unit_id', 'name'] + verbose_name = 'Library Setting' + def __str__(self): + return "%s:%s=%s" % (self.org_unit_id.shortname, self.name, self.value) + + +class PermList(models.Model): + code = models.CharField(maxlength=100) + description = models.CharField(blank=True, maxlength=200) + class Admin: + list_display = ('code','description') + search_fields = ['code'] + class Meta: + db_table = 'perm_list' + ordering = ['code'] + verbose_name = 'Permission' + def __str__(self): + return self.code + +class GrpPermMap(models.Model): + grp_id = models.ForeignKey(GrpTree, db_column='grp') + perm_id = models.ForeignKey(PermList, db_column='perm') + depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth') + grantable = models.BooleanField() + class Admin: + list_filter = ['grp_id'] + list_display = ('perm_id', 'grp_id', 'depth_id') + class Meta: + db_table = 'grp_perm_map' + ordering = ['perm_id', 'grp_id'] + verbose_name = 'Permission Setting' + def __str__(self): + return str(self.grp_id)+' -> '+str(self.perm_id) + + + + +""" There's no way to do user-based mangling given the size of the data without custom handling. + When you try to create a new permission map, it tries to load all users into a dropdown selector :( + +class User(models.Model): + card_id = models.ForeignKey('Card', db_column='card') + profile_id = models.ForeignKey(GrpTree, db_column='profile') + usrname = models.CharField(blank=False, null=False, maxlength=200) + def __str__(self): + return "%s (%s)" % ( str(self.card_id), str(self.usrname)) + class Meta: + db_table = 'usr' + verbose_name = 'User' + +class UsrPermMap(models.Model): + usr_id = models.ForeignKey(User, db_column='usr') + perm_id = models.ForeignKey(PermList, db_column='perm') + depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth') + grantable = models.BooleanField() + class Admin: + search_fields = ['usr_id', 'perm_id'] # we need text fields to search... + class Meta: + db_table = 'usr_perm_map' + verbose_name = 'User Permission' + def __str__(self): + return "%s -> %s" % ( str(self.usr_id), str(self.perm_id) ) + + +class Card(models.Model): + usr_id = models.ForeignKey(User, db_column='usr') + barcode = models.CharField(blank=False, null=False, maxlength=200) + active = models.BooleanField() + def __str__(self): + return self.barcode + class Meta: + db_table = 'card' + verbose_name = 'Card' +""" + + + + +class OrgAddress(models.Model): + valid = models.BooleanField() + org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit') + address_type = models.CharField(blank=False, maxlength=200, default='MAILING') + street1 = models.CharField(blank=False, maxlength=200) + street2 = models.CharField(maxlength=200) + city = models.CharField(blank=False, maxlength=200) + county = models.CharField(maxlength=200) + state = models.CharField(blank=False, maxlength=200) + country = models.CharField(blank=False, maxlength=200) + post_code = models.CharField(blank=False, maxlength=200) + class Admin: + search_fields = ['street1', 'city', 'post_code'] + list_filter = ['org_unit_id'] + list_display = ('street1', 'street2', 'city', 'county', 'state', 'post_code') + class Meta: + ordering = ['city'] + db_table = 'org_address' + verbose_name = 'Library Address' + def __str__(self): + return self.street1+' '+self.city+', '+self.state+' '+self.post_code + +class OrgUnit(models.Model): + parent_ou_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent_ou') + ou_type_id = models.ForeignKey(OrgUnitType, db_column='ou_type') + shortname = models.CharField(maxlength=200) + name = models.CharField(maxlength=200) + email = models.EmailField(null=True, blank=True) + phone = models.CharField(maxlength=200, null=True, blank=True) + opac_visible = models.BooleanField(blank=True) + ill_address_id = models.ForeignKey(OrgAddress, + db_column='ill_address', related_name='ill_addresses', null=True, blank=True) + holds_address_id = models.ForeignKey(OrgAddress, + db_column='holds_address', related_name='holds_addresses', null=True, blank=True) + mailing_address_id = models.ForeignKey(OrgAddress, + db_column='mailing_address', related_name='mailing_addresses', null=True, blank=True) + billing_address_id = models.ForeignKey(OrgAddress, + db_column='billing_address', related_name='billing_addresses', null=True, blank=True) + class Admin: + search_fields = ['name', 'shortname'] + list_display = ('shortname', 'name') + class Meta: + db_table = 'org_unit' + ordering = ['shortname'] + verbose_name = 'Library' + def __str__(self): + return self.shortname + + +class RuleCircDuration(models.Model): + name = models.CharField(maxlength=200) + extended = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); + normal = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); + shrt = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); + max_renewals = models.IntegerField() + class Admin: + search_fields = ['name'] + list_display = ('name','extended','normal','shrt','max_renewals') + class Meta: + db_table = 'rule_circ_duration' + ordering = ['name'] + verbose_name = 'Circ Duration Rule' + def __str__(self): + return self.name + + +class RuleMaxFine(models.Model): + name = models.CharField(maxlength=200) + amount = models.FloatField(max_digits=6, decimal_places=2) + class Admin: + search_fields = ['name'] + list_display = ('name','amount') + class Meta: + db_table = 'rule_max_fine' + ordering = ['name'] + verbose_name = 'Circ Max Fine Rule' + def __str__(self): + return self.name + +class RuleRecurringFine(models.Model): + name = models.CharField(maxlength=200) + high = models.FloatField(max_digits=6, decimal_places=2) + normal = models.FloatField(max_digits=6, decimal_places=2) + low = models.FloatField(max_digits=6, decimal_places=2) + class Admin: + search_fields = ['name'] + list_display = ('name','high', 'normal', 'low') + class Meta: + db_table = 'rule_recuring_fine' + ordering = ['name'] + verbose_name = 'Circ Recurring Fine Rule' + def __str__(self): + return self.name + +class IdentificationType(models.Model): + name = models.CharField(maxlength=200) + class Admin: + search_fields = ['name'] + class Meta: + db_table = 'identification_type' + ordering = ['name'] + verbose_name = 'Identification Type' + def __str__(self): + return self.name + + +class RuleAgeHoldProtect(models.Model): + name = models.CharField(maxlength=200) + age = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT) + prox = models.IntegerField() + class Admin: + search_fields = ['name'] + class Meta: + db_table = 'rule_age_hold_protect' + ordering = ['name'] + verbose_name = 'Hold Age Protection Rule' + def __str__(self): + return self.name + +class MetabibField(models.Model): + field_class_choices = ( + ('title', 'Title'), + ('author', 'Author'), + ('subject', 'Subject'), + ('series', 'Series'), + ('keyword', 'Keyword'), + ) + field_class = models.CharField(maxlength=200, choices=field_class_choices, null=False, blank=False) + name = models.CharField(maxlength=200, null=False, blank=False) + xpath = models.TextField(null=False, blank=False) + weight = models.IntegerField(null=False, blank=False) + format = models.CharField(maxlength=200, null=False, blank=False) + class Admin: + search_fields = ['name', 'format', 'field_class'] + list_display = ('field_class', 'name', 'format') + class Meta: + db_table = 'metabib_field' + ordering = ['field_class', 'name'] + verbose_name = 'Metabib Field' + def __str__(self): + return self.name + + +# register the alternate DB +""" +settings.OTHER_DATABASES['main_db']['MODELS'] = [ + 'GrpTree', + 'OrgUnitType', + 'OrgUnitSetting', + 'PermList', + 'GrpPermMap', + 'User', + 'UsrPermMap', + 'Card', + 'OrgAddress', + 'OrgUnit', + 'RuleCircDuration', + 'RuleMaxFine', + 'RuleRecurringFine', + 'IdentificationType', + 'RuleAgeHoldProtect' ] +""" + diff --git a/Open-ILS/admin/ils_admin/setup/models.py b/Open-ILS/admin/ils_admin/setup/models.py deleted file mode 100644 index e3032b82bc..0000000000 --- a/Open-ILS/admin/ils_admin/setup/models.py +++ /dev/null @@ -1,287 +0,0 @@ -from django.db import models -from django.db.models import signals -from django.dispatch import dispatcher - -# Create your models here. - -INTERVAL_HELP_TEXT = 'examples: "1 hour", "14 days", "3 months", "DD:HH:MM:SS.ms"' -PG_SCHEMAS = "actor, permission, public, config" - - -# --------------------------------------------------------------------- -# Here we run some SQL to manually set the postgres schema search-paths -# --------------------------------------------------------------------- -def setSearchPath(): - from django.db import connection - cursor = connection.cursor() - cursor.execute("SET search_path TO %s" % PG_SCHEMAS) -dispatcher.connect(setSearchPath, signal=signals.class_prepared) -dispatcher.connect(setSearchPath, signal=signals.pre_init) - - -class GrpTree(models.Model): - name = models.CharField(maxlength=100) - parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent') - description = models.CharField(blank=True, maxlength=200) - perm_interval = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT) - application_perm = models.CharField(blank=True, maxlength=100) - usergroup = models.BooleanField() - class Admin: - list_display = ('name', 'description') - list_filter = ['parent_id'] - search_fields = ['name', 'description'] - class Meta: - db_table = 'grp_tree' - ordering = ['name'] - verbose_name = 'User Group' - def __str__(self): - return self.name - -class OrgUnitType(models.Model): - name = models.CharField(maxlength=100) - opac_label = models.CharField(maxlength=100) - depth = models.IntegerField() - parent_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent') - can_have_vols = models.BooleanField() - can_have_users = models.BooleanField() - class Meta: - db_table = 'org_unit_type' - verbose_name = 'Library Type' - class Admin: - list_display = ('name', 'depth') - list_filter = ['parent_id'] - ordering = ['depth'] - def __str__(self): - return self.name - -class OrgUnitSetting(models.Model): - org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit') - name = models.CharField(maxlength=200) - value = models.CharField(maxlength=200) - class Admin: - list_display = ('org_unit_id', 'name', 'value') - search_fields = ['name', 'value'] - list_filter = ['name', 'org_unit_id'] - class Meta: - db_table = 'org_unit_setting' - ordering = ['org_unit_id', 'name'] - verbose_name = 'Library Setting' - def __str__(self): - return "%s:%s=%s" % (self.org_unit_id.shortname, self.name, self.value) - - -class PermList(models.Model): - code = models.CharField(maxlength=100) - description = models.CharField(blank=True, maxlength=200) - class Admin: - list_display = ('code','description') - search_fields = ['code'] - class Meta: - db_table = 'perm_list' - ordering = ['code'] - verbose_name = 'Permission' - def __str__(self): - return self.code - -class GrpPermMap(models.Model): - grp_id = models.ForeignKey(GrpTree, db_column='grp') - perm_id = models.ForeignKey(PermList, db_column='perm') - depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth') - grantable = models.BooleanField() - class Admin: - list_filter = ['grp_id'] - list_display = ('perm_id', 'grp_id', 'depth_id') - class Meta: - db_table = 'grp_perm_map' - ordering = ['perm_id', 'grp_id'] - verbose_name = 'Permission Setting' - def __str__(self): - return str(self.grp_id)+' -> '+str(self.perm_id) - - - - -""" There's no way to do user-based mangling given the size of the data without custom handling. - When you try to create a new permission map, it tries to load all users into a dropdown selector :( - -class User(models.Model): - card_id = models.ForeignKey('Card', db_column='card') - profile_id = models.ForeignKey(GrpTree, db_column='profile') - usrname = models.CharField(blank=False, null=False, maxlength=200) - def __str__(self): - return "%s (%s)" % ( str(self.card_id), str(self.usrname)) - class Meta: - db_table = 'usr' - verbose_name = 'User' - -class UsrPermMap(models.Model): - usr_id = models.ForeignKey(User, db_column='usr') - perm_id = models.ForeignKey(PermList, db_column='perm') - depth_id = models.ForeignKey(OrgUnitType, to_field='depth', db_column='depth') - grantable = models.BooleanField() - class Admin: - search_fields = ['usr_id', 'perm_id'] # we need text fields to search... - class Meta: - db_table = 'usr_perm_map' - verbose_name = 'User Permission' - def __str__(self): - return "%s -> %s" % ( str(self.usr_id), str(self.perm_id) ) - - -class Card(models.Model): - usr_id = models.ForeignKey(User, db_column='usr') - barcode = models.CharField(blank=False, null=False, maxlength=200) - active = models.BooleanField() - def __str__(self): - return self.barcode - class Meta: - db_table = 'card' - verbose_name = 'Card' -""" - - - - -class OrgAddress(models.Model): - valid = models.BooleanField() - org_unit_id = models.ForeignKey('OrgUnit', db_column='org_unit') - address_type = models.CharField(blank=False, maxlength=200, default='MAILING') - street1 = models.CharField(blank=False, maxlength=200) - street2 = models.CharField(maxlength=200) - city = models.CharField(blank=False, maxlength=200) - county = models.CharField(maxlength=200) - state = models.CharField(blank=False, maxlength=200) - country = models.CharField(blank=False, maxlength=200) - post_code = models.CharField(blank=False, maxlength=200) - class Admin: - search_fields = ['street1', 'city', 'post_code'] - list_filter = ['org_unit_id'] - list_display = ('street1', 'street2', 'city', 'county', 'state', 'post_code') - class Meta: - ordering = ['city'] - db_table = 'org_address' - verbose_name = 'Library Address' - def __str__(self): - return self.street1+' '+self.city+', '+self.state+' '+self.post_code - -class OrgUnit(models.Model): - parent_ou_id = models.ForeignKey('self', null=True, related_name='children', db_column='parent_ou') - ou_type_id = models.ForeignKey(OrgUnitType, db_column='ou_type') - shortname = models.CharField(maxlength=200) - name = models.CharField(maxlength=200) - email = models.EmailField(null=True, blank=True) - phone = models.CharField(maxlength=200, null=True, blank=True) - opac_visible = models.BooleanField(blank=True) - ill_address_id = models.ForeignKey(OrgAddress, - db_column='ill_address', related_name='ill_addresses', null=True, blank=True) - holds_address_id = models.ForeignKey(OrgAddress, - db_column='holds_address', related_name='holds_addresses', null=True, blank=True) - mailing_address_id = models.ForeignKey(OrgAddress, - db_column='mailing_address', related_name='mailing_addresses', null=True, blank=True) - billing_address_id = models.ForeignKey(OrgAddress, - db_column='billing_address', related_name='billing_addresses', null=True, blank=True) - class Admin: - search_fields = ['name', 'shortname'] - list_display = ('shortname', 'name') - class Meta: - db_table = 'org_unit' - ordering = ['shortname'] - verbose_name = 'Library' - def __str__(self): - return self.shortname - - -class RuleCircDuration(models.Model): - name = models.CharField(maxlength=200) - extended = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); - normal = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); - shrt = models.CharField(maxlength=200, help_text=INTERVAL_HELP_TEXT); - max_renewals = models.IntegerField() - class Admin: - search_fields = ['name'] - list_display = ('name','extended','normal','shrt','max_renewals') - class Meta: - db_table = 'rule_circ_duration' - ordering = ['name'] - verbose_name = 'Circ Duration Rule' - def __str__(self): - return self.name - - -class RuleMaxFine(models.Model): - name = models.CharField(maxlength=200) - amount = models.FloatField(max_digits=6, decimal_places=2) - class Admin: - search_fields = ['name'] - list_display = ('name','amount') - class Meta: - db_table = 'rule_max_fine' - ordering = ['name'] - verbose_name = 'Circ Max Fine Rule' - def __str__(self): - return self.name - -class RuleRecurringFine(models.Model): - name = models.CharField(maxlength=200) - high = models.FloatField(max_digits=6, decimal_places=2) - normal = models.FloatField(max_digits=6, decimal_places=2) - low = models.FloatField(max_digits=6, decimal_places=2) - class Admin: - search_fields = ['name'] - list_display = ('name','high', 'normal', 'low') - class Meta: - db_table = 'rule_recuring_fine' - ordering = ['name'] - verbose_name = 'Circ Recurring Fine Rule' - def __str__(self): - return self.name - -class IdentificationType(models.Model): - name = models.CharField(maxlength=200) - class Admin: - search_fields = ['name'] - class Meta: - db_table = 'identification_type' - ordering = ['name'] - verbose_name = 'Identification Type' - def __str__(self): - return self.name - - -class RuleAgeHoldProtect(models.Model): - name = models.CharField(maxlength=200) - age = models.CharField(blank=True, maxlength=100, help_text=INTERVAL_HELP_TEXT) - prox = models.IntegerField() - class Admin: - search_fields = ['name'] - class Meta: - db_table = 'rule_age_hold_protect' - ordering = ['name'] - verbose_name = 'Hold Age Protection Rule' - def __str__(self): - return self.name - -class MetabibField(models.Model): - field_class_choices = ( - ('title', 'Title'), - ('author', 'Author'), - ('subject', 'Subject'), - ('series', 'Series'), - ('keyword', 'Keyword'), - ) - field_class = models.CharField(maxlength=200, choices=field_class_choices, null=False, blank=False) - name = models.CharField(maxlength=200, null=False, blank=False) - xpath = models.TextField(null=False, blank=False) - weight = models.IntegerField(null=False, blank=False) - format = models.CharField(maxlength=200, null=False, blank=False) - class Admin: - search_fields = ['name', 'format', 'field_class'] - list_display = ('field_class', 'name', 'format') - class Meta: - db_table = 'metabib_field' - ordering = ['field_class', 'name'] - verbose_name = 'Metabib Field' - def __str__(self): - return self.name - -