2014-11-07 5 views
0

У меня есть вид в Django, который вызывает внешнюю библиотеку/класс. Проблема заключается в том, что по какой-то причине Django сохраняет результаты кэширования, исходящие из предыдущих вызовов этого класса.Django странное поведение

Пожалуйста, рассмотрим следующий простой пример:

Джанго вид:

from some_path import Demo 
def test_view(request): 
    demo = Demo() 
    result = demo.do_something() 
    return render(request, 'test.html', 
          { 'result':result } 
       ) 

Демо-класс:

class Demo(): 
    result = [] 

    def do_something(self): 
     self.result.append(1) 
     self.result.append(2) 
     self.result.append(3) 
     return self.result 

Вы ожидаете результат будет [1, 2, 3], не так ли? НЕПРАВИЛЬНО!

При первой загрузке страницы вы получите правильный результат. Но по всем следующим запросам он будет продолжать увеличиваться: [1, 2, 3, 1, 2, 3] ... [1, 2, 3, 1, 2, 3, 1, 2, 3] ...

Итак, мой вопрос очевиден - что здесь происходит? Как я получаю [1, 2, 3] каждый раз, когда я вызываю класс внутри представления Django?

Джанго 1.7/MacOS X.

+0

Мой вопрос описан в полном объеме в следующем учебном пособии: https://docs.python.org/3/tutorial/classes. html # переменные класса и экземпляра – Termos

ответ

11

Определить result в __init__ в качестве атрибута экземпляра.

class Demo(): 

    def __init__(self): 
     self.result = [] 

    def do_something(self): 
     self.result.append(1) 
     self.result.append(2) 
     self.result.append(3) 
     return self.result 

Если вы печатаете result в вашем коде, то вы получите, что result является назначение только один раз,

class Demo(): 
    result = [] 
    print result 

    def ... 
     . 
     . 

d = Demo() 
print d.do_something() 
print d.do_something() 
e = Demo() 
print e.do_something() 
>>> 
[] 
[1, 2, 3] 
[1, 2, 3, 1, 2, 3] 
[1, 2, 3, 1, 2, 3, 1, 2, 3] 

result является изменяемый объект, всякий раз, когда вы сделали экземпляр класса это сослаться result к та же ссылка. В случае неизменного объекта: -

class Demo(): 
    result = 1 

    def do_something(self): 
     self.result += 1 

d = Demo() 
d.do_something() 


d.do_something() 
e = Demo() 
e.do_something() 
print d.result, e.result 

Выход: -

>>> 
3 2 
+0

Я приму этот ответ, потому что он решает проблему. Но почему это происходит? – Termos

+0

Даже я предлагаю этот способ: P –

+0

@Termos проверяет обновленный код, я думаю, что решил то, о чем вы просите. –

1

Почему бы вам не попробовать инициализации result=[] внутри вашего do_something метод что-то вроде этого?

def do_something(self): 
     result = [] 
     result.append(1) 
     result.append(2) 
     result.append(3) 
     return result 
0
""" 
Case 1: 
Here we have declared the result and some_string as static Class variable 
""" 
class Demo_1(): 
    result = [] 
    some_string = "" 

    def do_something(self): 
     Demo_1.some_string = Demo_1.some_string + "Python " 
     self.result.append(1) 
     self.result.append(2) 
     self.result.append(3) 
     return self.result 

demo = Demo_1() 
print Demo_1.result 
result = demo.do_something() 
print Demo_1.result 

demo = Demo_1() 
result = demo.do_something() 
print Demo_1.result 

demo = Demo_1() 
result = demo.do_something() 
print Demo_1.result 

print result 
print demo.some_string 

print "Demo_1 class attributes :-", dir(Demo_1) 

""" 
Case1 Output : 
    [] 
    [1, 2, 3] 
    [1, 2, 3, 1, 2, 3] 
    [1, 2, 3, 1, 2, 3, 1, 2, 3] 
    [1, 2, 3, 1, 2, 3, 1, 2, 3] 
    Python Python Python 
    Demo_1 class attributes :- ['__doc__', '__module__', 'do_something', 'result', 'some_string'] 

As you can see both result and some_string exists in Demo_1's attributes 
which you can access by both by Class name as well as it's instance 
""" 

print "-----------------------------------------------------------------" 

""" 
Case 2: 
Here we have declared the result variable as Class instance variable. 
So each time we create an instance of class it creates new memory for that instance. 
""" 
class Demo_2(): 

    def __init__(self): 
     self.result = [] 
     self.some_string = " " 

    def do_something(self): 
     self.result.append(1) 
     self.result.append(2) 
     self.result.append(3) 
     return self.result 

demo = Demo_2() 
result = demo.do_something() 
print demo.result 

demo = Demo_2() 
result = demo.do_something() 
print demo.result 

demo = Demo_2() 
result = demo.do_something() 
print demo.result 

print result 
print "Demo_1 class attributes :-", dir(Demo_2) 
print Demo_2.some_string 

""" 
Case2 Output : 
    [1, 2, 3] 
    [1, 2, 3] 
    [1, 2, 3] 
    [1, 2, 3] 
    Demo_1 class attributes :- ['__doc__', '__init__', '__module__', 'do_something'] 
    Traceback (most recent call last): 
     File "bl.py", line 83, in <module> 
     print Demo_2.some_string 
    AttributeError: class Demo_2 has no attribute 'some_string' 


As you can see Class Demo_2 has no attributes result or some_string as 
they are instance variable. 
""" 

Подробнее о статической переменной классаHere