#91 closed enhancement (duplicate)
A (possible) cleaner ORM fields description
Reported by: | mmarshall | Owned by: | Adrian Holovaty |
---|---|---|---|
Component: | Core (Other) | Version: | |
Severity: | normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Here is a cleaner approach to the ORM fields. Using this patch, the example in the tutorial can be changed to this:
from django.core.meta import Model # Create your models here. class Poll(Model): def fields(Field): Field.Char('question', maxlength=200) Field.DateTime('pub_date', 'date published') class Choice(Model): def fields(Field): Field.ForeignKey(Poll) Field.Char('choice', 'choice', maxlength=200, core=True) Field.Integer('votes', 'votes', core=True)
I have done an implementation, which is fully backwards compatible, and quite simple.
Index: django/core/meta.py =================================================================== --- django/core/meta.py (revision 227) +++ django/core/meta.py (working copy) @@ -377,12 +377,53 @@ new_v.func_globals[k] = func new_functions[k] = func + +class FieldGenerator(object): + """FieldGenerator is used for... uh... Generating fields. It has attributes, + such as "Char" and "DateTime", that can be used to create class instances such as + "CharField" or "DateTimeField". These instances are then added to the list "fields", + which can be retrieved to be used as the "fields" attribute in a Model class.""" + def __init__(self): + self.fields = [] + self.last_class = None #This is the class obj that corrisponds to the last __getattr__ call. + + def __getattr__(self,name): + self.last_class = None + try: + obj = eval(name+"Field") + if issubclass(obj,Field): self.last_class = obj + except NameError: pass + if not self.last_class: # If name+"Field" didn't work, just try name. + try: + obj = eval(name) + if issubclass(obj,Field): self.last_class = obj + except NameError: pass + if not self.last_class: + raise AttributeError("Could not find either %s or %sField (or they are not decendants of Field.)" % (name,name)) + return self.GenerateField + + def GenerateField(self, *args, **kargs): + """ This creates an instance of the class corrisponding to the + last __getattr__ call, and adds it to self.fields.""" + if not self.last_class: + raise ValueError("GenerateField should only be called with self.last_class set.") + self.fields.append(self.last_class(*args, **kargs)) + self.last_class = None + + class ModelBase(type): "Metaclass for all models" def __new__(cls, name, bases, attrs): # If this isn't a subclass of Model, don't do anything special. if not bases: return type.__new__(cls, name, bases, attrs) + + # If 'fields' is callable, we want to call it, passing a FieldGenerator. + if callable(attrs['fields']): + fg = FieldGenerator() + attrs['fields'](fg) + attrs['fields'] = fg.fields # If this model is a subclass of another Model, create an Options # object by first copying the base class's _meta and then updating it
I don't know if this is the best way of doing it... but it's out there!
Change History (4)
comment:1 by , 19 years ago
Resolution: | → wontfix |
---|---|
Status: | new → closed |
comment:2 by , 19 years ago
comment:3 by , 19 years ago
Resolution: | wontfix |
---|---|
Status: | closed → reopened |
comment:4 by , 19 years ago
Resolution: | → duplicate |
---|---|
Status: | reopened → closed |
I'm closing this ticket, because discussion has moved to #122.
Note:
See TracTickets
for help on using tickets.
I'm not sure who closed this ticket, but it's still under consideration. See the discussion here: http://groups-beta.google.com/group/django-developers/browse_thread/thread/219747f0af086cb0/27de1ddf96468200