Django - внешний ключ по умолчанию
у меня проблема с установкой значения по умолчанию для моего поля 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
Это простое приложение календаря, и идея в том, что у меня есть событие, на которое люди могут подписаться в указанных группах. Поэтому я хотел бы иметь возможность создавать события и одновременно создавать некоторые группы, а затем добавлять слоты в группы.
у меня есть поле событий в модели слота, потому что мне нужно убедиться, что люди не смогут подписаться на 2 слота в то же время, и мне также нужно рассчитать количество слотов (поле в модели событий). Мне, очевидно, нужно, чтобы поля событий в обеих моделях указывали на одно и то же событие, поэтому я подумал, что у меня может быть что-то вроде значения по умолчанию для моего слота.событие.
не стесняйтесь представлять любые обходные пути, я могу легко перепроектировать свое приложение. Заранее спасибо за помощь.
изменить: Я постараюсь лучше описать свое приложение: это должен быть календарь для сообщества онлайн-игр (игра arma3). Я ожидаю каждый мероприятии примут участие не более 40 человек, но для нашей игры нам нужны иерархии. В частности, мы делим себя на группы, в каждой группе разные роли(командир, пулеметчик, стрелок и др.).). Я хочу иметь календарь, в котором вы можете просматривать конкретные детали событий, включая группы и все различные слоты, и подписаться на один конкретный слот. Надеюсь, это все прояснит. Пожалуйста, простите все ошибки, английский не мой первый язык.
I забыл упомянуть об этом ранее, но я абсолютный новичок в Django и запускаю Django 1.7 на python 3.4. Решение с использованием лямбда, похоже, не работает, вот журнал ошибок (извините за отсутствие отступов):
(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 ответов
У меня была аналогичная проблема, пытаюсь добавить внешний ключ к миграции без значения по умолчанию. Удалите лямбда-выражение и пусть значение по умолчанию равно nullable (None) и повторите попытку со следующим образцом кода. Для меня это сработало идеально.
Эл.г:
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')
Я опустил не интересные поля на моделях для простоты. Надеюсь, это поможет вам.
что-то вроде того, что 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()
в качестве несвязанного совета не используйте модель raw user. Правильный способ его использования-в документация.
from django.conf import settings
from django.db import models
class Article(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL)
Если вам нужно использовать другую модель пользователя в будущем, ваше приложение не сломается, если вы сделаете это таким образом.
Edit:
Я не понял пару вещей. Кажется, события несколько групп и групп несколько игровые автоматы. Теперь "иметь несколько" можно представить с помощью внешнего ключа.
в этом случае группа должна иметь внешний ключ к событиям, и слоты должны иметь внешний ключ к группам. Вы можете проверить, какое событие для определенного слота:
my_slot.group.event