#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 , 20 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
comment:2 by , 20 years ago
comment:3 by , 20 years ago
| Resolution: | wontfix |
|---|---|
| Status: | closed → reopened |
comment:4 by , 20 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