Opened 10 years ago

Closed 10 years ago

Last modified 10 years ago

#382 closed defect (wontfix)

globals should show up in model methods and classes (like normal python classes)

Reported by: brenocon@… Owned by: adrian
Component: Core (Other) Version:
Severity: minor Keywords:
Cc: brenocon@… Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

I want to do this:

import re

class Note(meta.Model):
  #...
  def __repr__(self):
    if re.search(...)

Unfortunately, "re" isn't present in the namespace. The following exception occurs:

  File "c:\brendano\djblog\apps\blog\models\blog.py", line 25, in __repr__
    if re.search(r'^\s*$', self.title):

NameError: global name 're' is not defined

as a workaround I can just do "import re" inside the method. But the larger problem is, all module-level (global) variables don't appear inside any method namespaces.

myglobal = 5
class Note(meta.Model):
  #...
  def __repr__(self):
    print myglobal

also gives the same error. In fact, a manual "global myglobal" statement fails to make it work.

IMPORTANCE: so I guess the preferred django way of doing things is to make the model classes as sparse and declarative as possible. In that case the bug is a minor inconvenience.

SUSPECTED CAUSE: maybe a bug in the ModelBase metaclass?

SVN version: 541

Change History (7)

comment:1 Changed 10 years ago by garthk

  • Severity changed from normal to minor

That's by design -- whilst re is present in your model module, it's not automatically exposed to each virtual module generated from the model classes. To insert it into those, you need to define module_constants:

class Note(meta.Model):
  module_constants = {'re': re}
  #...
  def __repr__(self):
    if re.search(...)

comment:2 Changed 10 years ago by brenocon@…

I see. It's a bit confusing since that violates the way a python file usually works: you define module-level variables, then you can get at them inside other declarations in that file. I guess things are complex for django because of virtual modules... I can't think of how to make the system more like normal python in this regard.

comment:3 Changed 10 years ago by adrian

  • Resolution set to invalid
  • Status changed from new to closed

See "Using module globals in models" on the DataModelPitfalls page.

comment:4 Changed 10 years ago by brenocon@…

  • Cc brenocon@… added
  • Resolution invalid deleted
  • Status changed from closed to reopened
  • Summary changed from Module-level variables in model methods don't show up to globals should show up in model methods and classes (like normal python classes)

Now with #122 implemented, models are starting to look like and behave more like standard python classes -- this is great! Ideally, you should be able to program all sorts of methods on a model class and use imports and global variables like normal.

Are there any design reasons not to have models work like this?

Sorry for reopening this, but it seems to me at least that this is the direction models ought to go -- I'd defintiely like to see that before using django intensively for any big projects, myself.

comment:5 Changed 10 years ago by adrian

  • Resolution set to wontfix
  • Status changed from reopened to closed

I can't fathom why you would avoid using Django intensively because of a little thing like this...

Yes, there's a design reason for custom model methods functions not having access to globals from the model module. A model module can define *multiple* model classes, and there's too much "stuff" in a model module for it to make sense to give *all* custom methods access to *all* globals. It's just too...messy.

comment:6 Changed 10 years ago by brenocon@…

sorry, i should say -- it's one of those things i'd try to fix if I started using it :) If I write 10 methods on a class, and have to do those imports inside each class, I just know I'm dumb and will forget things or forget to update code when things rename, and things will breaking...

a python file can define multiple classes too, and those classes all have access to globals defined in that file.

comment:7 Changed 10 years ago by upadhyay@…

class Note(meta.Model):
  _m_c = {}
  from types import ModuleType
  for k,v in globals().items():
    if isinstance(v, ModuleType):
      _m_c[k] = v
  module_constants = _m_c

Might save you some trouble. Or you can subclass models Meta class from MyMeta which does that for you.

Note: See TracTickets for help on using tickets.
Back to Top