models.py
TITLE = (
(\'Classroom\', \'Classroom\'),
(\'Playground\', \'Playground\'),
(\'Staff Room\',\'Staff Room\'),
)
class Location(models.M
Try this function as signal handler:
def location_title(sender, instance, created, **kwargs):
# Don't fire up on updates.
if not created:
return
# Only handle new superusers.
if not instance.is_superuser or not instance.is_active:
return
# Create a `Location` entry for new superuser.
l = Location(user_id=instance.pk)
l.save()
post_save.connect(location_title, sender=User)
Adding choices to model field:
Django CharField has a named argument choices
that allows you to give the end user a list of possible values, and a proper validation of them in forms. The format of the iterable is as follows <internal_value>, <display_value>
. Once a field has been passed a choices
argument, you can access display value connected to it's internal value with instance.get_<field_name>_display()
method.
The choices iterable could look like this:
class Location(models.Model):
class Title:
CLASSROOM = 'classroom'
PLAYGROUND = 'playground'
STAFF_ROOM = 'staff_room'
TITLE_CHOICES = (
(Title.CLASSROOM, 'Classroom'),
(Title.PLAYGROUND, 'Playground'),
(Title.STAFF_ROOM, 'Staff Room'),
)
user = models.ForeignKey(User,null=True)
title = models.CharField('Incident Type', max_length=200,choices=TITLE_CHOICES,default=Title.CLASSROOM)
parent_location_id = models.CharField('Parent Location', max_length=100, null=True, blank=True)
is_active = models.BooleanField('Is Active', default=True)
The final solution is the following:
class Location(models.Model):
class Title:
CLASSROOM = 'classroom'
PLAYGROUND = 'playground'
STAFF_ROOM = 'staff_room'
BASE_LOCATION = Title.CLASSROOM
TITLE_CHOICES = (
(Title.CLASSROOM, 'Classroom'),
(Title.PLAYGROUND, 'Playground'),
(Title.STAFF_ROOM, 'Staff Room'),
)
user = models.ForeignKey(User,null=True)
title = models.CharField('Incident Type', max_length=200,choices=TITLE_CHOICES,default=Title.CLASSROOM)
parent_location_id = models.CharField('Parent Location', max_length=100, null=True, blank=True)
is_active = models.BooleanField('Is Active', default=True)
def location_title(sender, instance, created, **kwargs):
# Don't fire up on updates.
if not created:
return
# Only handle new superusers.
if not instance.is_superuser or not instance.is_active:
return
# Create a `Location` entry for new superuser.
base = Location(user_id=instance.pk, title=Location.BASE_LOCATION)
base.save()
for value, _ in Location.TITLE_CHOICES:
if value == Location.BASE_LOCATION:
continue
l = Location(user_id=instance.pk, title=value, parent_location_id=base.pk)
l.save()
post_save.connect(location_title, sender=User)
When you create the user or superuser the model instance is created but it does not have corresponding location
row. Hence, accessing instance.location.is_active
gives you the error.
You can update the signal handler to create the location
instance first and then set appropriate attributes. As below:
def location_title(sender, instance, created, **kwargs):
#also check for created flag
if created and instance.is_superuser:
location = Location(user=instance)
location.is_active=True
location.save()
post_save.connect(location_title, sender=User)
If you want to choices for title
field you can define that in field. Your definition of the title
field is not correct, change it to
title = models.CharField('Incident Type', max_length=200, choices=TITLE,
default='Classroom')
You are incorrectly using detfault=TITLE
instead of choices=TITLE
.