我在决定如何为特定数据结构构建模型时遇到麻烦。
我拥有的模型是帖子,组,用户。
我希望可以从组页面或用户页面以及可能的更多页面(如事件页面)发布Post模式。
帖子将包含文本,图像(fk),用户,观看次数,评分(例如,来自-指向用户或群组页面中发布位置的引用)的字段,尽管我不确定如何建立此连接
我曾考虑过使用通用外键将字段分配给不同的模型,但阅读articles时建议避免使用它。我尝试了建议的模型,但是我不确定它们是否适合我的需求。
此刻,我选择了替代4-多表继承
class Group(models.Model):
name = models.CharField(max_length=64)
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='_groups')
members = models.ManyToManyField(
settings.AUTH_USER_MODEL)
def __str__(self):
return f'{self.name} -- {self.created_by}'
def save(self, *args, **kwargs):
# https://stackoverflow.com/a/35647389/1294405
created = self._state.adding
super(Group, self).save(*args, **kwargs)
if created:
if not self.members.filter(pk=self.created_by.pk).exists():
self.members.add(self.created_by)
class Post(models.Model):
content = models.TextField(blank=True, default='')
created_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="%(app_label)s_%(class)s_posts",
related_query_name="%(app_label)s_%(class)ss")
# class Meta:
# abstract = True
def __str__(self):
return f'{self.content} -- {self.created_by}'
class PostImage(models.Model):
image = models.ImageField(upload_to=unique_upload)
post = models.ForeignKey(
Post, related_name='images', on_delete=models.CASCADE)
def __str__(self):
return '{}'.format(self.image.name)
class UserPost(models.Model):
post = models.OneToOneField(
Post, null=True, blank=True, related_name='_uPost', on_delete=models.CASCADE)
class GroupPost(models.Model):
post = models.OneToOneField(
Post, null=True, blank=True, related_name='_gPost', on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
要做一些特定的过滤器,例如:
过滤特定的论坛帖子
Post.objects.filter(_gPost__group=group)
过滤特定的用户帖子
Post.objects.filter(created_by=user) # exclude groups with _gPost__isnull=False
为用户/组创建帖子
p = Post.objects.create(...)
up = UserPost.objects.create(post=p)
gp = GroupPost.objects.create(post=p)
真的,我想知道这是否是明智的选择。当前的过滤器和创建方式感觉很奇怪。因此,让我对这种方法犹豫不决的只是它的外观。
因此,Generic ForeignKey是此处或当前多表方法使用的地方。我尝试使用abstract = True
进行继承,但由于我需要外键来建立帖子模型,因此无法工作。即使没有摘要,我也获得了外键引用,但是过滤器变得令人沮丧。
编辑:
到目前为止,只有奇怪的问题(但不是真正的问题)在过滤时,我必须明确地排除某些字段以获取所需的内容,仅使用.filter(created_by=...)
即可获取所有其他中间表。
不包括所有其他平板电脑的过滤器帖子将需要Post.objects.filter(_uPost__isnull=True, _gPost__isnull=True, _**__isnull=True)
,这可能最终很乏味。
答案 0 :(得分:0)
我认为您的方法是明智的,这也许就是我的结构方式。
另一种方法是将Group和Event外键移到Post模型中,如果Post没有发布到组或事件中,则将它们设置为NULL / None。这样可以提高性能,并使过滤器更合理一些,但是如果您认为Posts可以在将来添加到许多其他模型中,那么我会避免这种方法(因为您必须不断添加越来越多的外键)。 / p>
答案 1 :(得分:0)
此刻,我将坚持目前的模式。
有兴趣的人可以阅读一些额外的内容。