Django - 外键默认

时间:2014-12-02 14:20:10

标签: django foreign-keys models

我在模型中为ForeignKey字段设置默认值时遇到问题。这是我的代码:

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

这是一个简单的日历应用程序,我的想法是我有一个人们可以在指定的群组中注册的活动。所以我希望能够创建事件并同时创建一些组,然后向组添加插槽。

我在Slot模型中有事件字段,因为我需要确保人们无法同时注册2个插槽,我还需要计算插槽数(事件模型中的字段)。我显然需要两个模型中的事件字段指向同一个事件,所以我认为我可以为Slot.event设置一个默认值。

随意提交任何变通方法,我可以轻松地重新设计我的应用程序。在此先感谢您的帮助。

编辑: 我会尝试更好地描述我的应用程序:它应该是一个在线游戏社区的日历(游戏是arma3)。我希望每个活动的参加人数不超过40人,但对于我们的游戏会议,我们需要等级。特别是我们将自己分成小组,每个小组都有不同的角色(团队领导,机枪手,步枪兵等)。我希望有一个日历,您可以在其中查看特定的活动详细信息,包括组和所有不同的插槽,并注册一个特定的插槽。我希望它澄清它。请原谅所有错误,英语不是我的第一语言。

我之前忘了提到它,但我是Django的绝对初学者,我在python 3.4上运行Django 1.7。使用lambda的解决方案似乎不起作用,这里是错误日志(抱歉没有缩进):

(own)qwe@qwe:~/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

这是更新的代码(同样可能存在缩进错误,我无法理解这个代码系统):

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 个答案:

答案 0 :(得分:3)

我遇到类似的问题,尝试在没有默认值的情况下向迁移添加外键。删除lambda表达式并将默认值设置为nullable(None),然后使用以下代码示例再次尝试。它对我来说很完美。

e.g:

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')  
为了简单起见,我在模型上省略了非感兴趣的字段。我希望它可以帮助你。

答案 1 :(得分:0)

像daniph建议的那样应该有用:

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

现在,如果我了解你,会为特定群组制作事件,这些事件会有用户可以用来注册活动的插槽。

我会这样处理:

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)

这种方式更有意义,并且没有重复的外键。您的广告位知道它的活动是什么,并且活动知道它的所有者组。

您可以反向查询它们:

我的活动的插槽:

my_event.slot_set.all()

我小组的活动:

my_group.event_set.all()

作为一个不相关的建议,不要使用原始用户模型。使用它的正确方法是documentation

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

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

如果您将来需要使用其他用户模型,如果您这样做,您的应用就不会中断。

编辑:

我误解了几件事。似乎事件有几个组,组有几个插槽。现在,&#34;有几个&#34;可以用外键表示。

在这种情况下,组应该具有事件的外键,并且插槽应该具有组的外键。 您可以通过以下方式检查某个广告位的事件:

my_slot.group.event