首先,通过不声明baseprofile抽象,可以使事情变得更简单:
from django.db import models
from django.contrib.auth.models import User, UserManager
class Person(User):
public_name = models.CharField(max_length=24, default="Mr. T")
objects = UserManager()
def save(self):
self.set_password(self.password)
super(Person, self).save()
def _getDefaultProfile(self):
try:
return self.baseprofile_set.get(default=True)
except ObjectDoesNotExist:
return False
profile = property(_getDefaultProfile)
def _getProfiles(self):
return self.baseprofile_set.all()
profiles = property(_getProfiles)
class BaseProfile(models.Model):
person = models.ForeignKey(Person)
is_default = models.BooleanField(default=False)
class Teacher(BaseProfile):
user_type = models.CharField(max_length=7, default="teacher")
class Student(BaseProfile):
user_type = models.CharField(max_length=7, default="student")
class Parent(BaseProfile):
user_type = models.CharField(max_length=7, default="parent")
这样更好吗?你的属性不知道它们返回的是什么类型,所以抽象基类只会让你在那里有一个令人难以置信的烦人开销。
如果你现在想知道,既然我做了任何返回的baseprofile,你怎么能从特定的profile中得到数据?你可以这样做:
try:
#note the lowercase teacher referal
print myuser.profile.teacher.someteacherfield
except Teacher.DoesNotExist:
print "this is not a teacher object!"
另外,我也希望您不要仅仅为了这个目的而使用用户类型字段,因为django有更好的内置功能,如您所见。我还希望在派生的概要文件类中确实有一些其他独特的字段,因为否则,您应该将它们丢弃,并将其通过一个用户类型字段进入baseprofile(请看
choices
做这件事)。
至于默认值,imho这个方法和其他方法一样好。您总是可以尝试将自定义约束添加到DBMS本身,即应该有0或1个包含相同FK的记录,并且默认值为“真”(没有Django方法可以做到这一点)。我还想说的是,添加一个方法使其成为默认值,在该方法中,确保“默认值”对该人是唯一的(例如,通过第一次设置,在具有相同FK的所有配置文件上,“默认值”为“假”)。这会让你省去很多可能的悲伤。您还可以在baseprofile的save()方法中添加此检查。
另一种方法是向指向默认配置文件的人员模型添加外键。虽然这将确保默认值在Django级别上是唯一的,但它也可以提供数据的非规范化和损坏,甚至在更烦人的级别上,所以我不太喜欢它。但同样,如果您通过预定义的方法添加/删除/更新概要文件(现在会更复杂!)你应该安全。
最后,也许您有很好的理由从用户继承,但是扩展用户功能的默认方法不是这样的,它已经描述过了。
here
.