0

我想为基于Photologue应用程序的用户制作画廊。为了将用户的个人资料连接到我想使用的 photologue 模型OneToOne。我还想......让我们说get_absolute_url模板使用的'覆盖' photologue's 。

# models
from photologue.models import Gallery
from profiles.models import UserProfile

class GalleryExtended(models.Model):
    gallery = models.OneToOneField(Gallery)
    user = models.ForeignKey(UserProfile, verbose_name=_('user'), on_delete=models.CASCADE)

    def get_absolute_url(self):
        return reverse('profiles_user:profiles_gallery-details', args=[self.user.user_url, self.gallery.slug])

# views
from photologue.views import Gallery
from profiles.models import UserProfile
from .models import GalleryExtended, PhotoExtended

def get_user_gallery_queryset(self):
    user = get_object_or_404(UserProfile, user_url=self.kwargs['user_url'])
    gallery = Gallery.objects.filter(galleryextended__user=user)
    return gallery

class ProfileGalleryDateView(object):
    date_field = 'date_added'
    allow_empty = True

    get_queryset = get_user_gallery_queryset

# site.com/username/gallery (shows photos + images with a filter by year)
class ProfileGalleryPhotoArchiveIndexView(ProfileGalleryDateView, ArchiveIndexView):
    template_name = 'galleries/gallery_n_photo_archive.html'

所以考虑到如果我这样做

gallery = Gallery.objects.filter(galleryextended__user=user)

模板开始使用 Photologue 的get_absolute_url(我不使用 corephotologue的 url url(r'^photologue/', include('photologue.urls', namespace='photologue')),,因为我将应用程序集成到我自己的 url 架构中)

是否有可能恢复到这样的事情

gallery = GalleryExtended.objects.filter(user=user).***(get fields from Gallery)***

并避免django.core.exceptions.FieldDoesNotExist: GalleryExtended has no field named 'date_added'以开始使用get_absolute_urlfrom GalleryExtended

我知道,通过继承扩展 s 模型可以轻松解决photologue,但我想知道是否可以使用 OneToOne?因为在我读过的一些资料中,建议使用 1to1 而不是继承。

4

1 回答 1

0

所以,我想我现在明白你想做什么了。而且它在各个方面都是错误的,骇人听闻的和糟糕的。
首先——模型继承没什么好怕的,事实上恰恰相反。如果您决定不遵循 OOP 最重要的原则之一,那么您现在所经历的喧嚣就是一个很好的例子。诸如“我从某处读过一些东西”之类的论点并不能真正改变我的看法,我真的建议您使用继承而不是 1to1 关系。更不用说每次需要在同一个地方使用对象时,使用 1to1 关系而不是继承也会创建一个额外的 DB 查询。

尽管不建议继续使用此设置,但我可以为您提供一些可能的版本,如何实现与您想要的类似的东西。它并不完美,因为它不应该以这种方式使用。

如果我们现在在同一页面上,则您的结构如下:

class Model1(models.Model):
    name = models.CharField(max_length=128)
    state = models.CharField(max_length=128)

    def some_method(self):
        return self.name


class Model2(models.Model):
    first = models.OneToOneField(Model1, related_name='second')
    name = models.CharField(max_length=128)

    def some_method(self):
        return self.name + '2345678'

您想查询所有Model2s 并在它们上调用Model1's some_method()(如果错误则更正)。
当您将self参数替换为符合标准的另一个模型时,可以通过一个 hacky 解决方案来实现这一点。
IE

all_method_values = []
for obj in Model2.objects.all():
    all_method_values.append(Model1.some_method(obj))

那么如何以更 Pythonic 的方式编写它并且仍然保持 1to1 关系呢?将有问题的方法更改为带有参数的静态方法,如果您需要将其作为任一模型的绑定方法调用,请让它们使用各自的参数调用相同的静态方法。但是代码说了超过 1000 个字:

# In the model
def get_absolute_url(self):
    return GalleryExtended.get_gallery_url(self.user.user_url, self.gallery.slug)

@staticmethod
def get_gallery_url(user_url, slug):
     return reverse('profiles_user:profiles_gallery-details', args=[self.user.user_url, self.gallery.slug])

现在,您可以在没有丑陋的黑客攻击的情况下调用,而不是上面显示的丑陋:

all_method_values = []
for obj in Model2.objects.all():
    all_method_values.append(Model1.get_gallery_url(obj.user.user_url, obj.gallery.slug))

作为记录,我仍然建议继承,但这也可以。做这个小步骤消除了混合两个单独模型的绑定方法的混淆,并清除了数据的来源。

于 2016-09-13T20:58:22.333 回答