django模型继承和模板中的子类访问

时间:2013-03-20 07:21:45

标签: django django-models django-templates

我正在看一些有趣的,在我看来,Django中的问题:模型继承及其在模板中的行为。为了清楚起见,我是一个django noob,所以这可能根本不是问题,实际上:)

他就是我的模特:

models.py

class AbstractUserProfile(models.Model):
    user = models.OneToOneField(User,
                                null=False, blank=False,
                                related_name=u'user_link')


    class Meta:
        abstract = True 

class UserProfile(AbstractUserProfile):

    personal_page = models.URLField(null=True, blank=True,
                                    verbose_name=u'personal page url')

    site_url = models.CharField(max_length=100,
                                null=False, blank=False,
                                unique=True,
                                verbose_name=u'web-site url')

    photo = ImageField(upload_to=u'profiles',
                       null=True, blank=True,
                       verbose_name=u'Profile picture')

以及相同models.py文件中的另外两个类:

class ProfileTypeOne(UserProfile):
    status = models.TextField(blank=True)

    def get_status(self):
         return mark_safe(self.status)

class ProfileTypeTwo(UserProfile):
    interests = models.TextField(blank=True)

    def get_status(self):
         return mark_safe(self.interests)

在模板中我有一些代码,需要调用 ProfileType 特定的方法,比如

.... some html .... {{ user.user_link.get_status }} ... some more html ....

我知道模型继承中自动创建的OneToOneRelationship,并且我可以这样访问所需的方法:

{{ user.user_link.profiletypeone.get_status }}

唯一的问题是,我不知道模板渲染中某些点的配置文件类型。在没有提出ProfileTypeOne.DoesNotExist异常的情况下,解决此问题的最佳方法是什么:

  1. 将此逻辑转移到视图中并创建一些标志,然后在模板中检查并访问受尊重的子类?
  2. 处理模板中的DoesNotExist异常? (不知道怎么做)
  3. 在模板中使用这种冗余的低效构造(几乎是变体#2):
  4. {{ user.user_link.profiletypeone.get_status }}{{ user.user_link.profiletypetwo.get_status }}

    我想把这个逻辑放到模板中的原因是因为该模板将被多次扩展,并且这个基本逻辑应该在所有模板中,因此迫使我,在将逻辑转移到视图部分的情况下,调用一些代码多次,而不是一次。

    先谢谢!

1 个答案:

答案 0 :(得分:1)

我的偏好是在视图中而不是在模板中进行错误处理。有很多方法可以做到这一点,以下是一个简单的例子。

###helpers.py
import models

def get_profile1_or_profile2(user):
    profile = get_instance_or_none(models.ProfileTypeOne, user=user)
    if profile is None:
        profile = get_instance_or_none(models.ProfileTypeTwo, user=user)
    return profile

def get_instance_or_none(model, **kwargs):
    try:
        result = model.objects.get(**kwargs)
    except:
        result = None
    return result


###views.py
import helpers

def some_view(request):
    """
    This view renders some template.
    """

    profile = helpers.get_profile1_or_profile2(request.user)
    if profile:
        # Render the template and pass in the profile object
    else:
        # Redirect to 404 or whatever kind of error handling.

然后在您的模板中,您只需{{ profile.get_status }}

即可

另外正如你所说:

  

我想把这个逻辑放到模板中的原因是因为该模板将被多次扩展,并且这个基本逻辑应该在所有模板中,因此迫使我,在将逻辑转移到视图部分的情况下,调用一些代码多次,而不是一次。

如何将逻辑转移到视图,多次调用代码。我的意思是它取决于您提出的请求,无论您的代码位于模板还是视图中。这就是请求在两种情况下的工作方式。

如果是观点:

  

请求 - > Url向视图发送请求 - >代码在这里运行 - >呈现模板

如果是模板:

  

请求 - > Url向视图发送请求 - >视图呈现模板 - >代码在这里运行