Django会话在生产中丢失了复杂的对象,但在dev中却没有

时间:2016-10-27 19:21:05

标签: django

所以我在开发中的会话中成功存储了一个复杂的对象(非模型)。我已经尝试了每个会话引擎和缓存类型,他们都在开发(Pycharm)。但是,当我将代码移动到生产中时,虽然没有抛出任何错误,但会话会丢失该对象。

以下是我用来设置会话对象的方法:

def instantiate_command_object(request):
    try:
        ssc = request.session['specimen_search_criteria']
        logger.debug('found ssc session variable')
    except KeyError:
        logger.debug('failed to find ssc session variable')
        ssc = SpecimenSearchCommand()

    return ssc

然后在一个通过ajax调用异步运行的方法中,我开始对会话中的对象进行更改:

def ajax_add_collection_to_search(request):
    ssc = instantiate_command_object(request)

    collection_id = request.GET.get('collection')

    collection = Collection.objects.get(pk=collection_id)

    if collection and collection not in ssc.collections:
        ssc.collections.append(collection)
        # save change to session
        request.session['specimen_search_criteria'] = ssc

    # refresh search results
    ssc.search()

    return render(request, '_search.html')

所有这一切都有效。但是,如果我然后刷新浏览器,则会话丢失。以下是模板的摘录:

{% with criteria=request.session.specimen_search_criteria %}
    <div class="search-criteria" id="search-criteria">
        <div class="row">
                Sesssion:
                 {{ request.session }}<br/>
                Search:
                 {{ request.session.specimen_search_criteria }}<br/>
                Created:
                 {{ request.session.specimen_search_criteria.key }}<br/>
                Collections:
                 {{ request.session.specimen_search_criteria.collections }}<br/>

同样,在开发中我可以整天刷新并返回相同的对象。在生产中,它将创建一个新对象,或者偶尔会返回先前创建的副本。

一些相关项目:

生产服务器正在运行带有mod_wsgi的Apache httpd。 我已经尝试过memcached,databasecache等行为仍然是一样的。始终在开发中工作,从不在生产中。

我用

尝试过
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer'

没有。我可以在数据库中看到会话信息,当我取消它时它似乎只是指向内存中复杂对象的位置。

我猜这可能与在多用户环境中运行有关,但同样,我没有使用locmem而且我已经尝试了所有的缓存方法都没有效果。

要清楚,会话本身似乎很好,我可以在其中存储字符串或其他简单项目,它会坚持下去。会话中的复杂对象似乎迷失了。

编辑:我可能还会指出,如果我在返回搜索条件后立即刷新 ,它将实际返回成功。任何超过一秒钟的东西都会消失。

编辑(添加SpecimenSearchCommand的代码):

class SpecimenSearchCommand:
    def __init__(self):
        pass

    created = datetime.datetime.now()
    key = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6))
    jurisdictions = []
    taxa = []
    strata = []
    collections = []
    chrons = []
    has_images = False

    query = None  # The active SQL query, not the actual result records
    page_size = 50
    current_page = 1
    sort_order = 'number'
    results = []  # Page of results from paginator

    def is_empty(self):
        if len(self.jurisdictions) == 0 and len(self.taxa) == 0 and len(self.strata) == 0 and \
                        len(self.collections) == 0 and len(self.chrons) == 0 and self.has_images is False:
            return True
        else:
            return False

    def get_results(self):
        paginator = Paginator(self.query, self.page_size)
        try:
            self.results = paginator.page(self.current_page)
        except PageNotAnInteger:
            self.results = paginator.page(1)
        except TypeError:
            return []
        except EmptyPage:
            self.results = paginator.page(paginator.num_pages)
        return self.results

    def get_results_json(self):

        points = []

        for s in self.results:
            if s.locality.latitude and s.locality.longitude:
                points.append({"type": "Feature",
                               "geometry": {"type": "Point",
                                            "coordinates": [s.locality.longitude, s.locality.latitude]},
                               "properties": {"specimen_id": s.id,
                                              "sci_name": s.taxon.scientific_name(),
                                              "cat_num": s.specimen_number(),
                                              "jurisdiction": s.locality.jurisdiction.full_name()}
                               })

        return json.dumps({"type": "FeatureCollection", "features": points})

    def search(self):
        if self.is_empty():
            self.query = None
            return

        query = Specimen.objects.filter().distinct().order_by(self.sort_order)
        if len(self.taxa) > 0:
            query = query.filter(taxon__in=get_hierarchical_search_elements(self.taxa))
        if len(self.jurisdictions) > 0:
            query = query.filter(locality__jurisdiction__in=get_hierarchical_search_elements(self.jurisdictions))
        if len(self.strata) > 0:
            query = query.filter(stratum__in=get_hierarchical_search_elements(self.strata))
        if len(self.chrons) > 0:
            query = query.filter(chron__in=get_hierarchical_search_elements(self.chrons))
        if len(self.collections) > 0:
            query = query.filter(collection__in=get_hierarchical_search_elements(self.collections))
        if self.has_images:
            query = query.filter(images__isnull=False)

        self.query = query
        return


def get_hierarchical_search_elements(elements):
    search_elements = []
    for element in elements:
        search_elements = set().union(search_elements, element.get_descendants(True))
    return search_elements

1 个答案:

答案 0 :(得分:1)

好的,正如Daniel指出的那样,SSC类的属性是类级别而不是实例级别。正确的版本现在看起来像这样:

    self.created = datetime.datetime.now()
    self.key = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(6))
    self.jurisdictions = []
    self.taxa = []
    self.strata = []
    self.collections = []
    self.chrons = []
    self.has_images = False

    self.query = None  # The active SQL query, not the actual result records
    self.page_size = 50
    self.current_page = 1
    self.sort_order = 'number'
    self.results = []  # Page of results from paginator