2011-01-06 12 views
5

Używam custom primary keys dla modelu w Django. (Było to bo importowania wartości w bazie danych, a oni już dołączony ID, a to miało sens zachowania istniejących wartości.)Django: tworzenie niestandardowego auto-inkrementacji PK?

class Transaction(models.Model): 
    id = models.IntegerField(primary_key=True) 
    transaction_type = models.IntegerField(choices=TRANSACTION_TYPES) 
    date_added = models.DateTimeField(auto_now_add=True) 

Jednak teraz chcę dodać nowe instancje modelu do bazy danych i chciałbym automatycznie wygenerować unikalny klucz podstawowy. Ale jeśli nie określisz identyfikator w momencie tworzenia instancji, otrzymuję błąd:

t = Transaction(transaction_type=0) 
t.save() 

otrzymujemy:

IntegrityError at /page 
(1048, "Column 'id' cannot be null") 

Jak mogę autogenerować unikatowy identyfikator, aby określić nowe wartości , bez konieczności zmiany sposobu importowania istniejących wartości?

UPDATE

Pisałem ten sposób niestandardowy, który wydaje się działać ...

class Transaction(models.Model): 
    def save(self, *args, **kwargs): 
     if not self.id: 
      i = Transaction.objects.all().order_by('-id')[0] 
      self.id = i.id+1 
     super(Transaction, self).save(*args, **kwargs) 
+0

Jestem ciekawy - jaki był problem z obsługą django klucza podstawowego podczas importowania zbiorczego? Nigdy nie miałem sytuacji, w której klucz podstawowy był problemem - chyba, że ​​importujesz do systemu produkcyjnego/działającego. –

Odpowiedz

1

Jak się importowanie istniejących wartości? Byłoby banalnie napisać coś do twojego Transaction s __init__, aby wygenerować dla ciebie nowy dowód, ale nie wiedząc, jak importujesz inne wartości, nie mogę powiedzieć na pewno, czy zmieni to sposób pracy z nimi.

+0

Nie wiem, czy to odpowiada na twoje pytanie, ale: z pliku CSV, używając niestandardowego skryptu importu i ustawiając pole Identyfikator transakcji na identyfikator w pliku CSV. (Ponadto: importuję je za pomocą obiektów Django zamiast bezpośredniego SQL.) Czy to pomaga? – AP257

+0

Tak. Zamiast pisać 'Transaction's' __init__', nadpisuj 'save()', aby najpierw sprawdzić, czy ma on ID, a następnie, jeśli nie, generuje dla ciebie nowy (a następnie wywołania zapisuj jak zwykle). – girasquid

+0

Miałem iść na przesłonięcie 'save()' i dodane jako aktualizacja powyżej - proszę mi powiedzieć, czy to wydaje się niejasno sensowne, a następnie zaakceptuję odpowiedź? dzięki! – AP257

2

Można użyć AutoField dla kolumny id zamiast IntegerField. Poniższa powinny pracować dla Ciebie:

id = models.AutoField(primary_key=True) 

id będzie teraz zwiększać automatycznie i nie będzie miał problemów współbieżności, jakie mogą napotkać w save metody.

2

ja skończyło się bardzo podobny kawałek kodu, ale sprawiły, że nieco bardziej ogólna:

def save(self, *args, **kwargs): 
    if self.id is None: 
     self.id = self.__class__.objects.all().order_by("-id")[0].id + 1 
    super(self.__class__, self).save(*args, **kwargs) 

używa self.__class__ więc można po prostu skopiować wkleić ten kod do dowolnej klasy modelu bez zmieniania czegokolwiek.

0

jeśli Twój polu Identyfikator usunąć, Django automatycznie zakładać, to:

id = models.AutoField(primary_key=True) 

W Django 1.8, inspectdb automatycznie wykryje auto_increment i użyć AutoField podczas generowania modeli.

Powiązane problemy