2010-06-26 20 views
13

[Aktualizacja: Zmieniono tytuł pytanie być bardziej szczegółowe]Jak zrobić auto wypełnione i autoinkrementacja pola w Django administratora

Przepraszam, jeśli nie wyraziłem się pytanie bardzo dobrze, mogę” t dowiedzieć, jak to zrobić:

class WhatEver(): 
    number = model.IntegerField('Just a Field', default=callablefunction) 
... 

Gdzie callablefunction robi to zapytanie:

from myproject.app.models import WhatEver 

def callablefunction(): 
    no = WhatEver.objects.count() 
    return no + 1 

Chcę automatycznie napisać kolejny numer, A Nie wiem, jak to zrobić.

Mam błędy z callablefunction stwierdzające, że nie można zaimportować modelu i myślę, że musi być łatwiejszy sposób na zrobienie tego. Nie trzeba nawet tego używać, ale nie wiem, jak to zrobić, używając numeru pk.

Mam google na ten temat i jedyne co znalazłem było użyć metody save() za auto zwiększając liczbę ... ale chciałem pokazać go w <textfield> przed zapisaniem ...

Co byś zrobił?

Odpowiedz

19

Gotowy! Mam nadzieję, że pomoże to wszystkim, którzy mają jakiekolwiek problemy z automatycznym wypełnianiem i automatycznym inkrementowaniem pola w django. Rozwiązaniem jest:

class Cliente(models.Model): 
    """This is the client data model, it holds all client information. This 
     docstring has to be improved.""" 
    def number(): 
     no = Cliente.objects.count() 
     if no == None: 
      return 1 
     else: 
      return no + 1 

    clientcode = models.IntegerField(_('Code'), max_length=6, unique=True, \ 
    default=number) 

    [... here goes the rest of your model ...] 

Weź udział w opiece:

  • Funkcja number nie podejmie żadnych argumentów (nawet nie self)
  • Jest napisany PRZED wszystko w modelu
  • Zostało to przetestowane na django 1.2.1

Ta zabawa ction automatycznie wypełni pole clientcode kolejnym numerem (tj.Jeśli masz 132 klientów, po dodaniu kolejnego pole będzie wypełnione numerem clientcode numer 133)

Wiem, że jest to absurdalne w większości praktycznych sytuacji, ponieważ numer PK jest również automatycznie zwiększany, ale nie ma sposobu, aby automatycznie wypełnić lub zastosować w praktyce administratora Django.

[Aktualizacja: jak stwierdziłem w moim komentarzu, istnieje sposób, aby użyć klucza podstawowego dla tego, ale to nie będzie wypełnić pole przed oszczędzania]

+5

Czy jesteś pewien, że ten kod będzie działał również z równoczesnymi transakcjami? Co się dzieje, gdy dwie prośby jednocześnie wykonują 'count()' w tym samym czasie i później zapisują tę samą wartość? – vdboor

+0

To prawda ... w moim przypadku użycia nie ma znaczenia, ponieważ nigdy nie będzie dwóch żądań na raz ... ale nawet wtedy muszę wymyślić lepszy sposób realizacji tego. Dzięki za radę! :) –

+0

Byłem w stanie wykonać coś podobnego do tego, co chcę, aby to pole: 'id = models.IntegerField (primary_key = True, puste = True)' Jedyne co jest to, że nie jest automatycznie wypełnione, ale rozwiązuje problem równoczesnych żądań (myślę) –

6

modelu Każdy Django ma już auto-generated primary key:

id = models.AutoField(primary_key=True) 

Wydaje staramy się powielać już istniejący problem, wystarczy użyć klawisza przedmiot podstawowy.

+0

Wiem o kluczach podstawowych, ale muszę pokazać ten numer na stronie administratora django. Czy istnieje jakiś sposób, aby to zrobić? –

+0

Zobacz http://stackoverflow.com/questions/2531762/edit-show-primary-key-in-django-admin –

+0

To nie działa. Jeśli umieścisz go jako awarię Django w AutoField. A jeśli jest to IntegerField, to nie działa zgodnie z oczekiwaniami. Po prostu staje się normalnym IntegerField. Potrzebuję, aby to pole wypełniło się automatycznie kolejnym numerem (myślę, że bardzo źle się wyjaśniam). –

0

Masz błędy w kodzie, dlatego nie można go importować:

from django.db import models 
class WhatEver(models.Model): 
    number = models.IntegerField('Just a Field', default=0) 

i Yuval A jest prawo o autoinkrementacja: nawet nie trzeba zadeklarować taką pole. Wystarczy użyć pk lub id, mają na myśli to samo, chyba że jest to kompozyt pk w modelu:

> w = Whatever(number=10) 
> w 
<Whatever object> 
> w.id 
None 
> w.save() 
> w.id 
1 

[aktualizacja] No, ja nie próbowałem wywoływalnym jako domyślny. Myślę, że jeśli naprawisz te błędy, to musi działać.

+0

Myślę, że jak dla django 1.2.1 Field.default() może mieć obiekt wywoływalny, zamiast tylko numeru/ciągu znaków –

6

Ja też natknąłem się na ten problem, moja instancja była customer.number, która była względna dla klientów Store. Kusiło mnie, aby używać coś takiego:

# Don't do this: 

class Customer(models.Model): 
    # store = ... 
    number = models.IntegerField(default=0) 

    def save(self, *args, **kwargs): 
     if self.number == 0: 
      try: 
       self.number = self.store.customer_set.count() + 1 
      else: 
       self.number = 1 
     super(Customer, self).save(*args, **kwargs) 

Powyższe może spowodować wiele problemów: Say było 10 klientów, a ja usunięty numer klienta 6. następnego klienta należy doliczyć byłoby (pozornie) 10. klienta, który następnie stałby się drugim Klientem nr 10. (Może to spowodować duże błędy w get() querysets)

Co skończyło się było coś takiego:

class Store(models.Model): 
    customer_number = models.IntegerField(default=1) 

class Customer(models.Model): 
    store = models.ForeignKey(Store) 
    number = models.IntegerField(default=0) 

    def save(self, *args, **kwargs): 
     if self.number == 0: 
      self.number = self.store.customer_number 
      self.store.number += 1 
      self.store.save() 
     super(Customer, self).save(*args, **kwargs) 

PS:

Rzuciłeś się kilka razy, że chcesz to pole wypełnione "przed ". Wyobrażam sobie, że chciałeś go wypełnić przed zapisaniem, abyś mógł uzyskać do niego dostęp. W tym celu powiedziałbym: ta metoda umożliwia dostęp do store.customer_number, aby zobaczyć następny numer.

+0

Mimo to rozwiąże to duplikat problemu, ale nadal pozostaną puste miejsca, jeśli usuniemy wpis pomiędzy. Nie można go używać jako numeru indeksu dla krotek w tabeli. –

+0

Czy istnieje sposób generowania liczb takich, że są one ciągłe, a ostatnia wartość powinna być równa 'count()'. Wszystkie liczby powinny zostać zaktualizowane po usunięciu wpisu?Przypuszczam, że można to zrobić, usuwając detekcję zdarzeń i używając pętli, aby zaktualizować wszystkie wpisy. Ale nie wiem jak to zrobić w modelach django. Możesz edytować kod, aby rozwiązać ten problem .. –

+2

Metoda, którą wykonałem, działa podobnie jak auto inkrementacja, ponieważ nie używa ponownie liczb. Możesz napisać pętlę, aby przejść i zaktualizować numery, ale prawdopodobnie nie jest to warte [twojego] czasu na napisanie tej funkcji, a nie warte czasu [komputera] na jej uruchomienie. Nawet przy niewielkiej bazie danych czas, aby trafić wszystkie te rekordy, może być ogromny. –

Powiązane problemy