{"id":178,"date":"2010-10-22T17:21:14","date_gmt":"2010-10-22T21:21:14","guid":{"rendered":"http:\/\/dashdrum.com\/blog\/?p=178"},"modified":"2010-10-22T17:21:14","modified_gmt":"2010-10-22T21:21:14","slug":"fun-with-oracle-and-external-data","status":"publish","type":"post","link":"https:\/\/dashdrum.com\/blog\/2010\/10\/fun-with-oracle-and-external-data\/","title":{"rendered":"Fun with Oracle and External Data"},"content":{"rendered":"<p>I&#8217;m playing around today with Django and Oracle, connecting my application to data from another application.<\/p>\n<p>First thing I realized is that I cannot use a table or view that does not have a single column primary key. \u00c2\u00a0Without a primary key, the Django Admin system complains loudly. \u00c2\u00a0For those that do have a good key, it&#8217;s pretty easy to declare it to Django:<\/p>\n<pre>id_number = models.CharField(max_length=10,primary_key=True)<\/pre>\n<p>This will override Django&#8217;s default behavior of using &#8216;ID&#8217; as the primary key field name.<\/p>\n<p>Next, there&#8217;s a specific way that one declares the schema and table\/view name for the existing structure. \u00c2\u00a0Each has to be in quotes, with the entire name also in quotes. \u00c2\u00a0Something like this:<\/p>\n<pre>    class Meta:\r\n        db_table = u'\"SCHEMA\".\"TABLE\"'<\/pre>\n<p>Something else that I needed to do was to not allow changes to the external data. \u00c2\u00a0This is enforced by Oracle security, but I also wanted to make it clear in my code that saves and deletes are not going to happen. \u00c2\u00a0To do this, I create an abstract class upon which my other models are based, which includes the redefined save() and delete() methods that raise a NotImplemeted error. \u00c2\u00a0These produce a nice, big error page when DEBUG=TRUE.<\/p>\n<pre>class AdvanceBase(models.Model):\r\n    \"\"\"\r\n    Abstract base class for accessing tables and views in the external schema\r\n    \"\"\"\r\n\r\n    class Meta:\r\n        abstract = True\r\n\r\n    def save(self): # No saving allowed\r\n        raise NotImplementedError\r\n\r\n    def delete(self): # No deletes allowed\r\n        raise NotImplementedError<\/pre>\n<p>I decided to try setting up a relationship between two of the external tables. \u00c2\u00a0This wasn&#8217;t really different than any other foreign key, with one exception. \u00c2\u00a0I wanted to rename the field to follow Django conventions. \u00c2\u00a0Orginally called SCHOOL_CODE, I changed it to SCHOOL &#8211; same as the foreign key object. \u00c2\u00a0In order to still map to the correct DB column, the db_column attribute is used to declare the original name:<\/p>\n<pre>school = models.ForeignKey(School,blank=True,null=True,db_column='SCHOOL_CODE')<\/pre>\n<p>One more experiment &#8211; using a manager. \u00c2\u00a0In this case I wanted to filter a table to include only living people. \u00c2\u00a0 The fact that I was using an external table did not change the method for this:<\/p>\n<pre>class PersonManager(models.Manager):\r\n    def get_query_set(self):\r\n        return super(PersonManager, self).get_query_set().filter(status='A')<\/pre>\n<p>Something else I learned was that the Django Admin will use the first manager listed for a model. \u00c2\u00a0By placing the reference to the PersonManager ahead of the normal objects, the Admin only showed living people.<\/p>\n<p>I&#8217;m sure there will be more later as I dig deeper into using external data. \u00c2\u00a0I have an actual application related goal driving my interest, so I should get this solved soon.<\/p>\n<p>As always, leave your comments below.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m playing around today with Django and Oracle, connecting my application to data from another application. First thing I realized is that I cannot use a table or view that does not have a single column primary key. \u00c2\u00a0Without a primary key, the Django Admin system complains loudly. \u00c2\u00a0For those that do have a good &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/dashdrum.com\/blog\/2010\/10\/fun-with-oracle-and-external-data\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Fun with Oracle and External Data&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-178","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/comments?post=178"}],"version-history":[{"count":2,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/178\/revisions"}],"predecessor-version":[{"id":180,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/posts\/178\/revisions\/180"}],"wp:attachment":[{"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/media?parent=178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/categories?post=178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dashdrum.com\/blog\/wp-json\/wp\/v2\/tags?post=178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}