python - 获取相关对象

标签 python django django-models django-templates

我有一位普通用户,他有一些测量结果,每个测量结果都可以有一个或多个标记结果:

class User(AbstractBaseUser):
    born = models.DateField(null=True, blank=True)
    ...

class Measurement(models.Model):
    user = models.ForeignKey(User, related_name='measurements')
    ...

class MeasurementResult(models.Model):
    measurement = models.ForeignKey(Measurement, related_name='results')
    tag = models.CharField(max_length=255)
    value = models.FloatField()
    ...

我希望获得所有用户、所有测量结果以及所有结果的标签,以便我可以执行以下操作:

{% for user in users %}
<div class="row">
    <div class="col-md-4">{{user.name}}, {{user.age}}</div>
    <div class="col-md-4">{{user.tags}}</div>
    <div class="col-md-4"><a href="{% url 'user_detail' user.id %}"> View detail</a></div>
</div>
{% endfor %}

我遇到了一些问题,我不知道如何正确解决:

  • user.age:我没有用户的年龄,而是用户的出生日期。如何将从数据库中的born属性派生的年龄属性添加到查询集中的用户?
  • user.tags:这比较棘手,因为标签是从给定用户的所有测量结果的所有标签的并集(集合)中获取的。我想我需要为此使用注释,但不知道该怎么做。

目前,我已经在 User 模型中添加了一个方法:

class User(AbstractBaseUser):
    ...
    def age(self):
        '''Returns the age of this user'''
        if not self.born:
            return None
        today = date.today()
        return today.year - born.year - ((today.month, today.day) < (born.month, born.day))

这是向模型添加属性的正确方法吗?通过添加方法?或者是更好的Django 方式来做到这一点?

为了添加标签,我有一个简单的辅助函数,它为每个用户添加一个属性:

def get_users_with_tags(skip_user=None):
    '''Lists all users, adding to each user the measurements results' tags'''
    users = User.objects.all()
    if skip_user:
        users = users.exclude(pk=skip_user.id)
    for user in users:
        measurements = Measurement.objects.filter(user=user.id)
        tags = set()
        for measurement in measurements:
            results = MeasurementResult.objects.filter(measurement=measurement)
            for result in results:
                tags.add(result.tag)
        user.tags = ','.join(list(tags))
    return users

但我不喜欢我请求每个用户的测量结果以及每个测量的结果。有没有办法在一次数据库访问中获得所有这些?

此外,我不喜欢像这样添加 user.tags 特别属性。有更好的方法吗? UserManager 也许吧,但是如何访问 Model Manager 中的相关模型?

归根结底是,尽管 get_users_with_tags 返回的值完全可以被上面的 django 模板使用,但这些相同的结果不可用(不可序列化 ,因为它们实际上并不是 django Rest API 的 QuerySet?)。

我想改进该函数,以便它生成可供 django 模板和 django Rest API 框架使用的结果。

最佳答案

我认为对于这两种情况你都可以使用属性装饰器;

class User(AbstractBaseUser):
born = models.DateField(null=True, blank=True)
.....

@property
def age(self):
    '''Returns the age of this user'''
    if not self.born:
        return None
    today = date.today()
    return today.year - born.year - ((today.month, today.day) < (born.month, born.day))


@property
def tags(self):
    '''Returns the tags of this user'''
    return MeasurementResult.objects.filter(measurement_id__in=self.measurements.all().values_list('id', flat=True)).distinct().values_list('tag', flat=True)

在这里您将获得标签列表

关于python - 获取相关对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33118893/

相关文章:

python - 通过 JSON 发送文件而不是上传到服务器,Django

django - 如何仅在第一次编辑日期时间字段

python - Django在不同服务器上传FileField和ImageField

python - 如果列表中的9个字符串全部被替换: do something

python - 如何将简单的 python 函数添加到 Web 应用程序中

python - 预测情绪分析时出错 Tensorflow NLTK

django - 通过 URL 参数进行数据库路由

python - 替换为 Python 中多个子字符串中的提取物

python - 有没有办法在 2 个字段上创建一个唯一的 id?

django - 由于 models.DO_NOTHING,FOREIGN KEY 约束失败