0

我正在尝试建立一个典型的社交网站。主要有两种类型的对象。

  1. 照片
  2. 地位

用户可以喜欢照片和状态。(请注意,这两个是互斥的)意味着,我们有两个表 (1) 仅用于图像,其他仅用于状态。

现在,当用户喜欢一个对象(可能是照片或状态)时,我应该如何存储该信息。

我想为此设计一个有效的 SQL 模式。目前我正在使用 Genericforeignkey(GFK)

class LikedObject(models.Model):
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

但是昨天我想如果我可以在不有效使用GFK的情况下做到这一点?

class LikedObject(models.Model):

    OBJECT_TYPE = (
        ('status', 'Status'),
        ('image', 'Image/Photo'),
    )

    user = models.ForeignKey(User, related_name="liked_objects")
    obj_id = models.PositiveIntegerField()
    obj_type = models.CharField(max_length=63, choices=OBJECT_TYPE)

我能理解的唯一区别是,如果我想获取特定用户的所有 like_status,我必须进行两次查询

status_ids = LikedObject.objects.filter(user=user_obj, obj_type='status').values_list('object_id', flat=True)
status_objs = Status.objects.filter(id__in=status_ids)

我对么?那么就易于查询/插入或性能等而言,最好的方法是什么?

4

2 回答 2

0

您基本上是在实现自己的通用对象,只是您将 ContentType 限制为硬编码的 OBJECT_TYPE。

如果您只想像示例中那样访问数据库(获取用户 x 喜欢的所有状态对象),或者几个特定的​​查询,那么您自己的实现当然可以快一点。但显然,如果以后您必须添加更多对象或做其他事情,您可能会发现自己正在实现整个完整的通用解决方案。就像他们说的,为什么要重新发明轮子。

如果您想要更好的性能,并且真的只需要担心这两个模型,您可能只想拥有两个不同的 Like 表(StatusLike 和 ImageLike)并使用继承来共享功能。

class LikedObject(models.Model):
   common_field = ...

   class Meta:
      abstract = True

   def some_share_function():
      ...

class StatusLikeObject(LikedObject):
   user = models.ForeignKey(User, related_name="status_liked_objects")
   status = models.ForeignKey(Status, related_name="liked_objects")

class ImageLikeObject(LikedObject):
   user = models.ForeignKey(User, related_name="image_liked_objects")
   image = models.ForeignKey(Image, related_name="liked_objects")

基本上,要么你有很多模型要担心,然后你可能想要使用更多的 Django 通用对象实现,或者你只有两个模型,为什么还要费心半个通用的解决方案。只需使用两个表。

于 2016-01-17T18:12:19.673 回答
0

在这种情况下,我会检查您的数据对象是否StatusPhoto许多常见的数据字段,例如Status.userand Photo.user, Status.titleand Photo.title, Status.pub_dateand Photo.pub_date, Status.textandPhoto.caption等。

你能把它们组合成一个Item对象吗?那Item会有一个Item.type字段,“照片”或“状态”?那么您将只有一个表和一个用户可以“喜欢”的对象类型。简单得多,基本上没有成本。

编辑:

from django.db import models
from django.utils.timezone import now

class Item(models.Model):
    data_type = models.SmallIntegerField(
        choices=((1, 'Status'), (2, 'Photo')), default=1)
    user = models.ForeignKey(User)
    title = models.CharField(max_length=100)
    pub_date = models.DateTimeField(default=now)
    ...etc...

class Like(models.Model):
    user = models.ForeignKey(User, related_name="liked_objects")
    item = models.ForeignKey(Item)
于 2016-01-17T20:12:14.007 回答