Django中全局变量的替代方案?

2024-05-19 00:40:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要一种方法来修改另一个ModelAdmin成员变量。所以我想也许我可以用一个全局变量。但是,如果有多个用户同时使用该应用程序,那么全局变量将继续意外地更改,所有的地狱都将崩溃。在

Django中是否有任何方法允许我从另一个ModelAdmin修改一个ModelAdmin成员变量?在

还是我犯了设计错误?是我让事情变得更难了还是我错过了什么?使用线程和锁呢?消息传递???事件?!?!?!帮助


这是整个故事。我的应用程序允许用户通过选择兼容的CPU、主板、内存和硬盘驱动器(按顺序)来构建PC。通过选择cpu,它们仅限于带有cpu插槽的主板。通过选择带有DDR3 DIMM的主板,它们仅限于DDR3内存,依此类推。在

另外,感觉到每个系统可能有许多相同的部分(例如:内存模块,但它们必须相同),我必须创建ManyToManyField关系并用through参数指定中间表(带有一个额外的count字段)。这需要使用InlineAdmin模型来显示管理页面中的字段。在

令我高兴的是,raw_id_字段变量导致下拉窗口小部件被替换为一个按钮,该按钮弹出一个与change相同的表单_列表.html并允许用户过滤/排序/搜索他们想要的部件。然而,这对我的老板来说还不够好。现在,我需要根据先前的选择预先定义这些过滤器(即,在选择带有DDR3的主板之后,用DDR3过滤内存)。所以我实现了这一点:Default filter in Django admin但是我需要一种方法来根据他们所做的其他选择动态地设置CpuAdmin.default_filters。在

我的模型,为了简洁起见,只包含一个零件模型:

# models.py
class CPU(Part):
    partNum = models.CharField(max_length=60)
    price = models.DecimalField(precision=2)
    socket = models.CharField(max_length=60)
    numCores = models.CharField(max_length=60)

class PC(models.Model):
    name = models.CharField(max_length=60)
    customer = models.CharField(max_length=60)
    cpuChoices = models.ManyToManyField(CPU, through='PcCpuChoice')
    memoryChoices = models.ManyToManyField(Memory, through='PcMemoryChoice')
    hardDriveChoices = models.ManyToManyField(HardDrive, through='PcHardDriveChoice')
    motherBoardChoices = models.ManyToManyField(MotherBoard, through='PcMotherboardChoice')

class PcCpuChoice(models.Model):
    pc = models.ForeignKey(PC, unique=False)
    cpu = models.ForeignKey(CPU, unique=False)
    count = models.IntegerField()

# admin.py
class PartAdmin(admin.ModelAdmin):
    class Meta:
        abstract = True
    search_fields = ['partNum', 'description', 'model']
    default_filter = []

    def changelist_view(self, request, extra_context=None):
        if not request.GET.has_key(self.default_filter[0]):
            q = request.GET.copy()
            q[self.default_filter[0]] = self.default_filter[1]
            request.GET = q
            request.META['QUERY_STRING'] = request.GET.urlencode()
        return super(PartAdmin,self).changelist_view(request, extra_context=extra_context)

class CpuAdmin(PartAdmin):
    list_filter = ['brand', 'socket', 'numCores', 'graphics']
    list_display = ('partNum', 'description', 'brand', 'model', 'markupPrice', 'clockSpeed', 'watts', 'voltage')
    default_filter = ['numCores','8'] # need to change this from PcAdmin!!!

class PcCpuInline(admin.TabularInline):
    model = PcCpuChoice
    extra = 1
    max_num = 1
    raw_id_fields = ['cpu']

class PcAdmin(admin.ModelAdmin):
    inlines = [PcCpuInline, PcMotherboardInline, PcMemoryInline, PcHardDriveInline]

admin.site.register(PC, PcAdmin)

Tags: selfdefaultadminmodelsrequestcpufilterlength
2条回答

谢谢你@PeterRowell给我指出了正确的方向。我使用django sessions存储过滤器,javascript向服务器发送请求,在加载表单时更新过滤器,在离开表单时删除过滤器,一些视图函数处理这些请求,向模型中添加了一个函数(将请求作为参数),以根据已保存的部分更新过滤器,并重写PartAdmin的changelist_view函数以使用中的过滤器请求.会话修改查询字符串。在许多不同的文件中有很多代码,但下面是一些亮点,希望能帮助人们寻找这样的解决方案:

所有发布在问题中的模型几乎都保持不变。在

电脑视图:

def update_filters(request):
    try:
        # get POST data
        url = request.POST['form_url']
        id = url.split('/')[-2:-1][0]
        system_type = url.split('/')[-3:-2][0]

        if id is not "new":
            system_content_type = ContentType.objects.get(app_label="systems", model=system_type.rstrip('s'))
            system = system_content_type.get_object_for_this_type(id=id)
            system.set_filters(request)
        else:
            request.session['filters'] = ''
        return HttpResponse("Filters where updated.")
    except:
        return HttpResponse("Select a part and click 'Save and continue' to set the filters.")


def delete_filters(request):
    request.session['filters'] = ''
    return HttpResponse("Filters where deleted.")

这是在更改中放置的javascript_表单.html(通过PcAdmin add_view和change_view函数中的extra_context参数添加它)

^{pr2}$

最后,添加到PartAdmin的函数:

^{3}$

噢,PartAdmin的changelist_view函数确实有点改变:

def changelist_view(self, request, extra_context=None):
    if ('filters' in request.session):
        q = request.GET.copy()
        for filter in request.session['filters'].split('&'):
            key, value = urllib.splitvalue(filter)
            # check if the request does not already use the filter
            # and that the model has the attribute to filter for
            if (not request.REQUEST.has_key(key)) and (key in self.list_filter):
                q[key] = value
        request.GET = q
        request.META['QUERY_STRING'] = request.GET.urlencode()
    return super(PartAdmin,self).changelist_view(request, extra_context=extra_context)

这不是一个答案,而是朝着正确的方向前进。在

还有更多的可变上下文localglobal。在您的例子中,上下文是user或者可能是{}(如果用户同时有多个构建)。在

注意,changelist_view()方法接受一个request对象。从这里你可以得到usersession(上面有任意数量的内容),以及所有其他形式的良好状态信息。在

进一步观察:在一个多线程、多进程的web环境中,实际上没有您习惯于思考的“全局”概念。虽然在这样的环境中创建一个“全局”是可能的(例如使用memcached),但是你必须非常努力地工作。在

相关问题 更多 >

    热门问题