我有一个Profile
模型,它是与OnetoOne
模型的User
关系。
我想告诉用户他们的个人资料不完整,并要求他们动态填写某些详细信息。
例如,我有一个Location
模型,它是OneToOne
的{{1}}。
Profile
用户注册后,我们尚未将class Profile(models.Model):
# some fields e.g. name
class Location(models.Model):
profile = models.OneToOneField(Profile, on_delete=models.CASCADE, null=True)
# longitude = ...
# latitude = ...
实例连接到location
。我想显示的是顶部的django消息/错误栏,如果profile
不具有profile
属性,则指示用户完成配置文件。
我不确定应该如何进行:
我认为一种方法是将location
布尔字段添加到completed_setup
类中。如果用户现在决定删除Profile
,我们还将更新此字段并将其设置为location
。
False
另一种方法是在模板中包含以下内容:
{% if profile.completed_setup %}{% else %}
<p>Finish Building Your Profile</p>
{% endif %}
我正在寻找最有效,最正确的方法,因为我拥有更多的关联模型(而不仅仅是位置)。
答案 0 :(得分:2)
我将使用添加到Profile模型的属性而不是新字段。由于completed_setup很可能是计算值,因此可以使用属性的getter来提供completed_setup的值。有两种选择。首先,您可以尝试获取OneToOne字段,如果该字段不存在,则返回False。您可以针对多个字段执行此操作
#models.py
class Profile(models.Model):
# some fields e.g. name
@property
def completed_setup(self):
try:
Location.objects.get(profile_id=self.id)
AnotherModel.objects.get(profile_id=self.id)
except (Location.DoesNotExist, AnotherModel.DoesNotExist):
return False
else:
return True
#template
{% if profile.completed_setup %}{% else %}
<p>Finish Building Your Profile</p>
{% endif %}
您还可以使用相关名称来检查其是否可能比上述名称更可靠。也可以对多个字段执行此操作。
#models.py
class Profile(models.Model):
# some fields e.g. name
@property
def completed_setup(self):
if self.location and self.another_onetoone:
return True
else:
return False
class Location(models.Model):
profile = models.OneToOneField(Profile, related_name='location', on_delete=models.CASCADE, null=True)
# longitude = ...
# latitude = ...
#template
{% if profile.completed_setup %}{% else %}
<p>Finish Building Your Profile</p>
{% endif %}
在您对其中一个问题的评论中,您希望能够对多个组运行查询。这是一种方法。如果您像我对objects.all()那样进行传递,则建议对queryset使用prefetch_related进行此操作。第一种解决方案对于大型数据库而言并不理想。第二个对一个对象有好处。以下是针对completed_setup进行过滤的最佳解决方案。
#models.py
class Profile(models.Model):
# some fields e.g. name
@property
def completed_setup(self):
if self.location and self.another_onetoone:
return True
else:
return False
@classmethod
def filter_completed_setup(cls, queryset=None, completed_setup=True):
match_ids = []
if not queryset:
queryset = cls.objects.all().prefetch_related('location', 'another_onetoone')
else:
queryset = queryset.prefetch_related('location', 'another_onetoone')
assert queryset.model is cls, "queryset must be of class Profile"
for p in queryset:
if completed_setup:
if p.location and p.another_onetoone:
match_ids.append(p.id)
else:
if not (p.location or p.another_onetoone):
match_ids.append(p.id)
return cls.objects.filter(id__in=match_ids)
Profile.filter_completed_setup(queryset or None, completed_setup=False)