2014-12-02 19 views
5

Ich habe ein Problem mit dem Festlegen von Standardwert für mein ForeignKey-Feld im Modell. Hier ist mein Code:Django - Foreign Key Standard

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 

Dies ist ein einfacher Kalender-App, und die Idee ist, dass ich ein Ereignis haben, dass die Menschen in bestimmten Gruppen anmelden können. Daher möchte ich in der Lage sein, ein Ereignis zu erstellen und gleichzeitig einige Gruppen zu erstellen und dann den Gruppen Slots hinzuzufügen.

Ich habe ein Ereignisfeld im Slot-Modell, weil ich sicherstellen muss, dass die Leute sich nicht für 2 Slots gleichzeitig anmelden können, und ich muss auch die Anzahl der Slots berechnen (Feld im Event-Modell) . Ich brauche offensichtlich Ereignisfelder in beiden Modellen, um auf dasselbe Ereignis zu zeigen, also dachte ich, dass ich etwas wie einen Standardwert für mein Slot.event haben könnte.

Fühlen Sie sich frei, irgendwelche Workarounds einzureichen, kann ich leicht meine App neu gestalten. Vielen Dank im Voraus für Hilfe.

EDIT: Ich werde versuchen, meine App besser zu beschreiben: Es soll ein Kalender für eine Online-Spiel-Community sein (das Spiel ist arma3). Ich erwarte, dass an jeder Veranstaltung nicht mehr als 40 Leute teilnehmen, aber für unsere Gaming-Sessions brauchen wir eine Hierarchie. Insbesondere teilen wir uns in Gruppen, in jeder Gruppe gibt es unterschiedliche Rollen (Teamleiter, Maschinengewehrschütze, Schützen etc.). Ich möchte einen Kalender haben, in dem Sie bestimmte Ereignisdetails, einschließlich Gruppen und alle verschiedenen Slots, anzeigen und sich für einen bestimmten Slot anmelden können. Ich hoffe, dass es das verdeutlicht. Bitte verzeih alle Fehler, Englisch ist nicht meine Muttersprache.

Ich vergaß es früher zu erwähnen, aber ich bin ein absoluter Anfänger bei Django und betreibe Django 1.7 auf Python 3.4. Die Lösung mit Lambda verwenden, nicht zu funktionieren scheint, ist hier das Fehlerprotokoll (sorry für keine Senkungen):

(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 

Hier wird Code aktualisiert (wiederum könnte es Einbuchtung Fehler sein, kann ich nicht meinen Kopf um dieser Code-System hier):

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

Was ist 'event = models.ForeignKey (Event, default = lambda: self.group.event wenn self.group sonst keine)'? – danihp

+1

... oder überschreiben '__init__' – madzohan

+1

... Oder binded zu post_init Signal @madzohan – danihp

Antwort

3

Ich hatte ein ähnliches Problem, einen Fremdschlüssel zu einer Migration ohne Standardwert zu schaffen versuchen. Entfernen Sie den Lambda-Ausdruck und lassen Sie den Standardwert als Nullable (None) und versuchen Sie es erneut mit dem folgenden Codebeispiel. Es hat perfekt für mich funktioniert.

z:

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') 

weggelassen ich die nicht interessant Felder auf Modelle aus Gründen der Einfachheit. Ich hoffe, es könnte dir helfen.

+0

Nun, ich habe dieses Konzept in meiner App aufgegeben und ging anders, aber danke für Ihre Antwort trotzdem. Ich habe es als akzeptiert markiert, falls jemand anderes auf dieses Problem stößt. – badn3wz

+0

Gern geschehen. Ich würde mich freuen, wenn Sie die Lösung teilen könnten, die Sie durch Refactoring Ihrer App erhalten haben. Natürlich, wenn Sie es mit uns teilen können. – emanuelcds

+0

Ich habe keine Lösung, ich habe gerade Group-Klasse und verknüpfte Slots zur Event-Klasse entfernt. Dann habe ich group_name charfield zur Slot-Klasse hinzugefügt, sodass jetzt jeder Slot einen Gruppennamen angeben kann. – badn3wz

0

So etwas wie, was sollte daniph vorgeschlagen arbeiten:

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

Nun, wenn ich Sie verstehen, Ereignisse werden für bestimmte Gruppen gemacht und diese Ereignisse haben Slots, Benutzer können sich für die Veranstaltung registrieren.

würde ich es so handhaben:

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) 

Auf diese Weise mehr Sinn, und es macht keine wiederholt Fremdschlüssel. Ihr Slot weiß, was es ist, und das Event kennt seine Besitzergruppe.

können Sie umkehren Abfrage sie mögen:

Slots für meine Veranstaltung:

my_event.slot_set.all() 

Events für meine Gruppe:

my_group.event_set.all() 

Als unabhängige Beratung, nicht Benutzer das rohe Benutzermodell. Der richtige Weg, um es zu verwenden, ist in der documentation.

Wenn Sie in Zukunft ein anderes Benutzermodell verwenden müssen, wird Ihre App nicht brechen, wenn Sie dies auf diese Weise tun.

Edit:

ich das falsch verstanden, ein paar Dinge. Es scheint Ereignisse haben mehrere Gruppen und Gruppen haben mehrere Slots. Jetzt können "mehrere haben" mit einem Fremdschlüssel dargestellt werden.

In diesem Fall sollte Gruppe einen Fremdschlüssel für Ereignisse haben, und Slots sollten einen Fremdschlüssel für Gruppen haben. Sie können die überprüfen, ist das Ereignis für einen bestimmten Slot mit:

my_slot.group.event 
+0

Sie haben mich nicht verstanden :) Die Gruppen sind für bestimmte Ereignisse erstellt und Slots sind für bestimmte Gruppen erstellt. Zuerst hatte ich keinen Bezug von Slots zu Gruppen, aber wie ich geschrieben habe, wird es hilfreich sein, einfach Zugang zu allen Slots von bestimmten Events zu haben. – badn3wz

+0

So haben Ereignisse mehrere Gruppen und Gruppen haben mehrere Steckplätze? – cdvv7788

+0

Genau, ich werde die Frage in einer Minute aktualisieren, weil Lambda-Lösung für mich nicht funktioniert hat. – badn3wz