2014-12-02 20 views
5

Ho problemi con l'impostazione del valore predefinito per il mio campo ForeignKey nel modello. Qui è il mio codice:Django - Esterna chiave predefinita

class Group(models.Model): 
    name = models.CharField(max_length=50) 
    event = models.ForeignKey(Event) 

def __str__(self): 
    return self.name 

class Slot(models.Model): 
    title = models.CharField(max_length=50, blank = True) 
    name = models.ForeignKey(SlotName) 
    is_taken = models.BooleanField(default=False) 
    usr = models.ForeignKey('auth.User', blank=True, null=True) 
    group = models.ForeignKey(Group) 
    event = models.ForeignKey(Event) #i would like to have something like "default=group.event" here 

    def __str__(self): 
     return self.name.name 

Si tratta di una semplice applicazione di calendario, e l'idea è che ho un evento che le persone possono iscriversi a gruppi specificati. Quindi mi piacerebbe essere in grado di creare eventi e allo stesso tempo creare alcuni gruppi e quindi aggiungere slot ai gruppi.

Ho il campo evento nel modello Slot perché devo assicurarmi che le persone non possano registrarsi per 2 slot contemporaneamente e ho anche bisogno di calcolare il numero di slot (campo nel modello Event) . Ovviamente ho bisogno di campi evento in entrambi i modelli per indicare lo stesso evento, quindi ho pensato che potevo avere qualcosa come un valore predefinito per il mio Slot.event.

Sentiti libero di inviare soluzioni alternative, posso facilmente riprogettare la mia app. Grazie in anticipo per l'aiuto.

MODIFICA: Proverò a descrivere meglio la mia app: si suppone che sia un calendario per una comunità di giochi online (il gioco è arma3). Mi aspetto che ogni evento sia seguito da non più di 40 persone, ma per le nostre sessioni di gioco abbiamo bisogno di una gerarchia. In particolare dividiamo noi stessi in gruppi, in ogni gruppo ci sono ruoli diversi (team leader, mitragliere, fuciliere ecc.). Voglio avere un calendario in cui è possibile visualizzare particolari dettagli dell'evento, compresi i gruppi e tutti i diversi slot, e iscriversi per uno specifico spazio. Spero che lo chiarisca. Per favore perdona tutti gli errori, l'inglese non è la mia prima lingua.

Ho dimenticato di dirlo in precedenza, ma sono un principiante assoluto di Django e sto eseguendo Django 1.7 su Python 3.4. La soluzione con l'utilizzo di lambda non sembra funzionare, ecco il log degli errori (scusate per nessun rientranze):

(own)[email protected]:~/Projects/own/src$ python manage.py makemigrations 
Migrations for 'cal': 
0021_auto_20141202_1913.py: 
- Remove field title from slot 
- Alter field event on slot 
Traceback (most recent call last): 
File "manage.py", line 10, in <module> 
execute_from_command_line(sys.argv) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/__init__.py", line 385, in execute_from_command_line 
utility.execute() 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/__init__.py", line 377, in execute 
self.fetch_command(subcommand).run_from_argv(self.argv) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/base.py", line 288, in run_from_argv 
self.execute(*args, **options.__dict__) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/base.py", line 338, in execute 
output = self.handle(*args, **options) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 124, in handle 
self.write_migration_files(changes) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/core/management/commands/makemigrations.py", line 152, in write_migration_files 
migration_string = writer.as_string() 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/db/migrations/writer.py", line 129, in as_string 
operation_string, operation_imports = OperationWriter(operation).serialize() 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/db/migrations/writer.py", line 86, in serialize 
arg_string, arg_imports = MigrationWriter.serialize(arg_value) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/db/migrations/writer.py", line 310, in serialize 
return cls.serialize_deconstructed(path, args, kwargs) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/db/migrations/writer.py", line 221, in serialize_deconstructed 
arg_string, arg_imports = cls.serialize(arg) 
File "/home/qwe/Projects/own/lib/python3.4/site-packages/django/db/migrations/writer.py", line 323, in serialize 
raise ValueError("Cannot serialize function: lambda") 
ValueError: Cannot serialize function: lambda 

qui rappresentati codice (ancora una volta ci potrebbero essere errori di indentazione, non riesco a ottenere la mia testa intorno questo sistema di codice qui):

class Event(models.Model): 
    author = models.CharField(max_length=200) 
    title = models.CharField(max_length=200) 
    details = models.TextField(max_length=5000) 
    slots_no = models.PositiveIntegerField(default=0, editable=False) 
    created_date = models.DateTimeField(
     auto_now=True) 
    event_date = models.DateField(
     blank=True, null=True) 
    event_time = models.TimeField(default='20:00') 
    created_by = models.ForeignKey('auth.User') 
    type = models.ForeignKey(EventType) 


    def publish(self): 
     self.save() 

    def __str__(self): 
     return self.title 

class Group(models.Model): 
    name = models.CharField(max_length=50) 
    event = models.ForeignKey(Event) 

    def __str__(self): 
     return self.name 


class Slot(models.Model): 
    #title = models.CharField(max_length=50, blank = True) 
    name = models.ForeignKey(SlotName) 
    is_taken = models.BooleanField(default=False) 
    usr = models.ForeignKey('auth.User', blank=True, null=True) 
    group = models.ForeignKey(Group) 
    event = models.ForeignKey(Event) 
    def __str__(self): 
     return self.name.name 
+2

E a proposito di 'event = models.ForeignKey (Event, default = lambda: self.group.event se self.group else None)'? – danihp

+1

... o sovrascrivi '__init__' – madzohan

+1

... O legato a segnale post_init @madzohan – danihp

risposta

3

ho avuto un problema simile si cerca di aggiungere una chiave esterna per una migrazione senza un valore predefinito. Rimuovere l'espressione lambda e lasciare il valore predefinito come annullabile (Nessuno) e riprovare con il seguente esempio di codice. Ha funzionato perfettamente per me.

es:

from django.db import models              


class Slot(models.Model):              
    event = models.ForeignKey('Event', null=True)        
    group = models.ForeignKey('Group', null=True)        
    def save(self, *args, **kwargs):            
     if(self.group is not None and self.group.event is not None):    
      self.event = self.group.event          
     super(Slot, self).save(*args, **kwargs)         

class Event(models.Model):              
    name = models.CharField(max_length=100)          

class Group(models.Model):              
    name = models.CharField(max_length=100)          
    event = models.ForeignKey('Event') 

I omessi i campi non interessanti su modelli per semplicità. Spero possa aiutarti.

+0

Bene, ho abbandonato questo concetto nella mia app e sono andato in altro modo, ma grazie comunque per la tua risposta. L'ho contrassegnato come accettato nel caso in cui qualcun altro incontri questo problema. – badn3wz

+0

Prego. Apprezzerei se tu potessi condividere la soluzione che hai ottenuto rifasando la tua app. Certo, se puoi condividerlo con noi. – emanuelcds

+0

Non ho soluzione, ho appena rimosso la classe del gruppo e gli slot collegati alla classe di eventi. Poi ho aggiunto group_name charfield alla classe Slot, quindi ora ogni Slot può avere il nome del gruppo specificato. – badn3wz

0

Qualcosa di simile a ciò che daniph suggerito dovrebbe funzionare:

event = models.ForeignKey(Event, default=lambda: self.group.event if self.group else None) 

Ora, se ti capisco, gli eventi vengono fatti per gruppi specifici e quegli eventi hanno slot che gli utenti possono utilizzare per registrarsi per l'evento.

avrei gestire in questo modo:

class Event(models.Model): 
    group = models.ForeignKey(Group) 

class Group(models.Model): 
    name = models.CharField(max_length=50) 

class Slot(models.Model): 
    title = models.CharField(max_length=50, blank = True) 
    name = models.ForeignKey(SlotName) 
    is_taken = models.BooleanField(default=False) 
    usr = models.ForeignKey('auth.User', blank=True, null=True) 
    event = models.ForeignKey(Event) 

In questo modo ha più senso e non ci sono chiavi esterne ripetute. Il tuo slot sa qual è il suo evento e l'evento sa che è il gruppo proprietario.

È possibile invertire interrogare loro come:

Slot per il mio caso:

my_event.slot_set.all() 

Eventi per il mio gruppo:

my_group.event_set.all() 

Come un consiglio non correlato, non lo fanno all'utente la cruda modello utente. Il modo giusto per utilizzarlo è nello documentation.

from django.conf import settings 
from django.db import models 

class Article(models.Model): 
    author = models.ForeignKey(settings.AUTH_USER_MODEL) 

Se è necessario utilizzare un altro modello utente in futuro, l'app non si interromperà se lo si fa in questo modo.

Edit:

ho frainteso un paio di cose. Sembra che gli eventi abbiano diversi gruppi e gruppi abbiano diversi slot. Ora "avere più" può essere rappresentato con una chiave esterna.

In tal caso, il gruppo dovrebbe avere una chiave esterna per gli eventi e gli slot dovrebbero avere una chiave esterna per i gruppi. È possibile controllare che è l'evento per un certo slot machine con:

my_slot.group.event 
+0

Non mi hai capito :) I gruppi sono creati per eventi specifici e gli slot sono creati per gruppi specifici. All'inizio non avevo riferimenti dagli slot ai gruppi, ma come ho scritto sarà utile avere facilmente accesso a tutti gli slot di determinati eventi. – badn3wz

+0

Quindi, gli eventi hanno diversi gruppi e gruppi hanno diversi slot? – cdvv7788

+0

Esattamente, aggiornerò la domanda tra un minuto perché la soluzione lambda non ha funzionato per me. – badn3wz

Problemi correlati