首页 > 解决方案 > 使用通用 UpdateView 始终编辑单个配置对象

问题描述

我需要的

我想为我的应用程序进行全局配置,并且我想重用一个通用的UpdateView.

我试过的

为此,我创建了一个模型(示例字段):

class Configuration(models.Model):
    admin = models.ForeignKey('User', on_delete=models.CASCADE)
    hostname = models.CharField(max_length=23)

一个通用的更新视图:

class ConfigurationView(UpdateView):
    model = Configuration
    fields = ['admin','hostname']

urls.py条目

path(
    'configuration/', 
    views.ConfigurationView.as_view(
        queryset=Configuration.objects.all().first()
    ),
    name='configuration'
),

如您所见,我希望配置/路径链接到此配置,并且始终只编辑这个对象。

问题

我得到错误

AttributeError:“配置”对象没有属性“全部”

问题

  1. 如何将对象硬编码到urls.py中的路径中,以便始终将第一个配置对象用于UpdateView

  2. 有一个更好的方法吗?我只想拥有一个全局配置对象,并希望它可以使用我选择的模板进行编辑和显示。

标签: djangopython-3.xdjango-views

解决方案


您正在尝试向期望查询集的类提供单个对象。执行此操作的视图调用get_queryset

def get_queryset(self):
    """
    Return the `QuerySet` that will be used to look up the object.
    This method is called by the default implementation of get_object() and
    may not be called if get_object() is overridden.
    """
    if self.queryset is None:
        if self.model:
            return self.model._default_manager.all()
        else:
            raise ImproperlyConfigured(
                "%(cls)s is missing a QuerySet. Define "
                "%(cls)s.model, %(cls)s.queryset, or override "
                "%(cls)s.get_queryset()." % {
                    'cls': self.__class__.__name__
                }
            )
    return self.queryset.all()

您已经提供了一个查询集self.queryset.all(),以便您的示例在其上调用all()您的类的实例。

要使用你的querysetkwarg,as_view()你会做类似的事情MyView.as_view(queryset=MyModel.objects.filter(enabled=True))

所以你需要改变视图寻找对象的方式;

class ConfigurationView(UpdateView):

    def get_object(self):
        return Configuration.objects.first()

默认情况下UpdateView这样做是为了获取一个对象;https://ccbv.co.uk/projects/Django/2.0/django.views.generic.edit/UpdateView/

如果您将配置限制为 1 个对象,您还需要实现单例设计。本质上,这是一种确保只能存在一个对象的方法。在这里阅读更多;https://steelkiwi.com/blog/practical-application-singleton-design-pattern/

有一个非常有用的单例包,叫做django-solo


推荐阅读