如何为Django Model PK使用自定义Oracle序列?

时间:2016-12-12 14:49:29

标签: django oracle orm primary-key

我正在将Django与现有Oracle数据库中的表集成,该数据库已经创建了一个序列并且定义了它的PK(数字)。我想要实现的是能够使用当前定义的序列为该表创建新行。我怎么能这样做?

2 个答案:

答案 0 :(得分:0)

我基于this gist解决了这个问题,将id更改为pk表示法,以便可以一般地使用它:

# your_app/models.py

def update_pk(func):
'''A decorator for pulling a data objects PK value out of a
   user-defined sequence.  This gets around a limitation in 
   django whereby we cannot supply our own sequence names.'''

    def decorated_function(*args):
        # Grab a reference to the data object we want to update.
        data_object = args[0]

        # Only update the PK if there isnt one yet.
        if data_object.pk is None:
            # Construct the new sequence name based on the tables meta data. This might be different depending on your needs
            sequence_name = 'seq_%s' % data_object._meta.db_table

            # Query the database for the next sequence value.
            from django.db import connection
            cursor = connection.cursor()
            cursor.execute("SELECT %s.nextval FROM DUAL;" % (sequence_name))
            row = cursor.fetchone()

            # Update the data objects PK with the returned sequence value.
            data_object.pk = row[0]

         # Execute the function were decorating.
         return func(*args)

    return decorated_function


# Example model using the decorator to grab the PK.
class FAQ(models.Model):
    id = models.IntegerField(primary_key=True)
    category = models.ForeignKey(FAQCategory)
    question = models.CharField(maxlength=255)
    answer = models.TextField()
    published = models.BooleanField(default=False)
    list_ordering = models.FloatField(max_digits=6, decimal_places=2, default=9999)

    def __str__(self):
        return self.question

    @update_pk
    def save(self):
        # Now actually save the object.
        super(FAQ, self).save()

    class Meta:
        db_table = 'faqs'

答案 1 :(得分:-1)

我上周刚刚遇到这个问题。我的表在Meta中定义为managed = false,Oracle序列用于提供主键值。要在保存行之后告诉Django获取键值,请将该列声明为AutoField:

surrogate_id = models.AutoField(primary_key=True,blank=True)