Django with legacy database - how to work with DB

2019-09-04 19:50发布

问题:

Given a database table that was created using this SQL query:

CREATE TABLE Bill
  (
    Time DATE NOT NULL ,
    Address VARCHAR2 (60) NOT NULL ,
    ID           NUMBER NOT NULL
  ) ;

ALTER TABLE Bill ADD CONSTRAINT Bill_PK PRIMARY KEY ( ID ) ;

CREATE SEQUENCE Bill_ID_SEQ START WITH 1 NOCACHE ORDER ;
CREATE OR REPLACE TRIGGER Bill_ID_TRG BEFORE
  INSERT ON Paragony FOR EACH ROW BEGIN :NEW.ID := Bill_ID_SEQ.NEXTVAL;
END;

I have to use it with Django ORM so I have run inspectdb command. It is the autogenerated code:

class Bill(models.Model):
    time = models.DateField()
    address = models.CharField(max_length=60)
    id = models.IntegerField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'bill'

After saving it to app' models.py file and running migrations everything was fine. I could read DB like it was created using ORM. However there was a problem with creating rows in Bill table.

It is simple form for Bill model:

class BillForm(ModelForm):

    class Meta:
        model = Bill
        fields = ('time', 'address')

The problem is that I can't retrieve the ID generated with the DB sequence. Adding id field to Form won't work because we have to generate it with code and then pass as a argument. Even than database will create different ID that will not be possible to retrieve without raw queries.

回答1:

The solution is really simple. We have to remove the id field from Bill model:

class Bill(models.Model):
    time = models.DateField()
    address = models.CharField(max_length=60)
    # Remove 'id' field so the ORM can work properly.
    # id = models.IntegerField(primary_key=True)

    class Meta:
        managed = False
        db_table = 'bill'

This way the Django ORM can make all the hard work and correctly use legacy database sequences. Bill objects now can be created using BillForm and they will have proper IDs.