Domanda

When I inspect the Trac database I get:

class TicketChange(models.Model):
    ticket = models.IntegerField()
    time = models.BigIntegerField()
    author = models.TextField(blank=True)
    field = models.TextField()
    oldvalue = models.TextField(blank=True)
    newvalue = models.TextField(blank=True)
    class Meta:
        managed = False
        db_table = 'ticket_change'

With not primary key:

>>> TicketChange.objects.all()
DatabaseError: column ticket_change.id does not exist
LINE 1: SELECT "ticket_change"."id", "ticket_change"."ticket", "tick...

Because I need to specify a pk but the original primary key of ticket_change in Trac is:

Primary key (ticket, time, field)

But It's not possible in Django: Django Multi-Column Primary Key Discussion.

If I define time like pk I can't add two tickets changes in the same time.

What can I do?

È stato utile?

Soluzione

You're right. It's a known problem. So the only solutions are hacks (sort of).

Your best option is to use django-compositepks. The drawbacks are that it doesn't really support model relationships, so you will not be able to navigate to any relationship from your composite-pk model. However, looking at your TicketChange model this doesn't seem like an issue (unless you have more models with relationships to this one).

Another option would be to manually add the id column (and make sure to apply any additional changes to the db), thereby creating the new one-column primary key. A third option (and what I would probably do), pretty similar to the last one but cleaner, would be to create a new database from scratch and then populate it with a script by fetching the data from your existing legacy db.

Sorry I don't have any better solution for you, that's the way it is. Legacy dbs and django are always a headache, have gone through some similar processes myself. Hope this helps!

Altri suggerimenti

This is a use case the Django ORM simply does not support. If you're able to modify the database schema, add an additional column that will serve as the primary key for Django: An integer field with AUTO_INCREMENT (MySQL) or a SERIAL (PostgreSQL). It shouldn't desturb your other applications using the table since it will be managed by your database when new records are inserted. You can still use the actual primary key when making queries through the ORM:

ticket_change = TicketChange.objects.get(ticket=1234, time=5678, field='myfield')

If you’d like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you’ve explicitly set Field.primary_key, it won’t add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

https://docs.djangoproject.com/en/3.1/topics/db/models/#automatic-primary-key-fields

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top