Class Level Property for Django model in Python - python

I have a Django model storing some infrequently changed but often used data. I'm looking for a pattern so that I can refer to them as kind of static class variables, eg, like SomeModel.Bar or SomeModel.Baz.
At the moment I'm using a staticmethod like so:
class SomeModel(models.Model):
name = models.CharField(max_length=100)
#staticmethod
def Baz():
#retrieve from cache or lookup Baz item
return baz
Meaning I refer to the items as SomeModel.Baz() but this just doesn't quite feel right. I just get the impression that I'm doing something wrong. I don't want to make it a property, as I don't want an instance to refer to the item.
Can anyone point me at a pattern or example to show me is I can implement a class level property in this way? Or tell me why I should be doing something totally different? Thanks :).

If you want some logic for model which doesn't belong to particular row, write custom model manager.

Related

Should I be using controllers.py or #staticmethod in Django?

The person on our team who initially taught us django (and has subsequently left) utilized a controllers.py file for helper functions. A lot of these functions are directly related to classes. I prefer to use #staticmethod to house these helpers with the classes they're related to. For example, rather than doing this:
# controllers.py
def process_entry():
# do some exciting stuff that might not have to do with an instance
Called like this:
from myapp.controllers import process_entry
process_entry()
I'd prefer this:
# models.py
class Entry(models.Model):
name = CharField...
# some other fields
#staticmethod
def process_entry():
# do some exciting stuff that might not have to do with an instance
Called like so:
from myapp.models import Entry
Entry.process_entry()
Is there a preferred, standard way to deal with situations like this or is it just personal preference? Does anyone else utilize a controllers.py file? What goes in there?
Thanks.
EDIT:
Possibly a better example, commissions.
# models.py
class Commission(models.Model):
check = ForeignKey
payment = ForeignKey
# other fields
class Check(models.Model):
# fields
class Payment(models.Model):
# fields
Any time a Check or Payment instance is modified an adjustment as to be made to any related Commission instances or any time someone wants to manually run commissions, they can do so. So where should run_commissions() go? I prefer this, but apparently this shouldn't be encapsulated in a data-related model?
# models.py
class Commission(models.Model):
check = ForeignKey
payment = ForeignKey
# other fields
#staticmethod
def run_commissions():
# do stuff
Static methods are used for grouping related functions in one class (mostly for factory methods), beside that, there is no difference between static method and function.
BUT. In your example you are assigning behavior to DATABASE model. DATABASE models are not LOGIC models, and you should separate them from your app logic. Anyway, controllers is also a bad name in that matter.
I'm not sure what process_entry does, but if it's only changing one Entry entity, then it can be named: Entry.process(), but NOT Entry as DB model! just another Entry class. However if that function does more than just changing Entry, then it shouldn't be assigned to Entry entity, but made as a service function.

A lot functions in Django Model, way to separate it?

I got huge Django App with huge amount of sub-applications. Currently, i'm working on reworking of models in one subapp, so i got a... problem.
I have huge amount of separated ugly functions to work with model. Basicly, it is a someting like:
def get_some_things(...):
def postprocess(...):
pass
def preprocess(...):
pass
preprocess(...)
x = MyModel.objects.....get(1)
return postprocess(x, ...)
And i got A LOT of functiongs like this and it's really ugly! And it's ugly used in current code(like DatabaseAccessor.get_db().django_kitty().get_some_things(...)). So, my idea was to make developers able to use these functions like this:
MyModel.get_some_things(...)
Or even like this:
MyModel.objects.get_some_things(...)
But! I got soo many functions so i can't write it inside model.py. So, i got few ideas:
Create model_mymodel.py and define my model with all functions inside it and static functions. But... I'm not sure, do i need to put it in model class?
Create mymodel_manager.py and create model manager for mymodel, define functions here. But... some of my "functions" should return just dicts, lists or even numbers. I wonder, is it ideologically wrong to make model manager be able to return something except the QuerySet?
Override __getattr__ of the MyModel class and dynamicly load modules like functions_common.py, functions_things.py etc, store gathered functions into dictionary and call needed?
If your models require a lot of unique methods, having huge model definitions is the price you pay. If for some reason you do want to split the functionality to other files (or, for something actually useful, share common functionality) you could use a mixin approach:
#mymodel.py
class MyModelMixin:
def django_kitty(self, ...):
pass
def postprocess(self, ...):
pass
def preprocess(self, ...):
pass
#models.py
from mymodel import MyModelMixin
class MyModel(models.Model, MyModelMixin):
pass
Regarding your own suggestions:
1 - If you want separate files per model, you could use this approach:
myapp/
models/
__init__.py
from mymodel import MyModel
mymodel.py
Beware that you would need to explicitly set the app_label for each model:
#mymodel.py
class MyModel(models.Model):
...
class Meta:
app_label = 'myapp'
2 - The return value type of manager methods is irrelevant. The distinguishing point of managers and models is to separate table and row level functionality respectively.
3 - Sounds like unnecessary magic, overriding Model.__getattr__ is a painful task.
Sounds like option 2 is the way to go.
There is nothing wrong with a model manager method not returning a QuerySet.
The guiding principle I use for model functions versus model managers is this: I use method functions on models regularly as long as the objective is to act on a single model object. However if my use case required me to handle multiple objects of the model and meets my DRY incentive, I would use a model manager for that.

Can an attribute attached to a Django model get information about a given record?

I have a class object attached as an attribute to a Django model. For the purposes of the question, let's assume it looks something like:
class Foo(object):
def bar(self):
print "Does things here"
class Task(models.Model):
name = models.CharField(max_length=30)
user = models.ForeignKey(User, related_name = 'tasks'
foo = Foo()
Is it possible for me to access values of a specific record from the foo attribute? So, for example, if I have something like:
task = Task(name="Get things done", user=JordanReiter)
newest_task = Task.objects.filter(user=JordanReiter).order_by('-pk')[0]
Then I could have some function spiffy on the Foo class so I could run something like:
newest_task.foo.spiffy()
And the spiffy function would know that in this case the value for name was "Get things done", etc.
Basically I'm wondering whether attributes can know information about the instance that calls them, or only the class that calls them. And, of course, if this is possible, how do I access the values for the instance?
In a perfect world, the foo attribute would have access to info about the Task class as well as the newest_task instance.
It sounds like you might want a descriptor. They're classes that implement special methods that are called when getting or setting, and are passed the parent instance.
You would make Foo a custom manager so that it knows about Task inherently.

Naming practice for objects of a class in Python

I have this weird problem as to how to name objects of a class.
For example, consider the class:
>>> class DoSomething:
pass
What should I call the object of this class? do_something or what? Since I came out of the learning stage, I used to use x, y or z or whatever came to my mind. But now since I am learning to write proper code and not the language, I always face this problem. Any suggestions?
Name it something representative of what it's actually being used for. For instance:
class Cereal:
def eat(self):
print 'yum'
breakfast = Cereal()
breakfast.eat()
or
class User:
def __init__(self, userid):
# ...
admin_user = User(ADMIN_ID)
You should name it after what it represents. For example if I have a class User in a web application and I want to refer to the currently logged-in user, I name the variable current_user.
And if you have more objects of one class, your approach fails immediately. Giving the variable an index like do_something1, do_something2 is not and will never be an option.
Use something meaningful, so that a reader of your code knows what this variable represents.
Btw. this applies to all programming languages, not just Python.
One good naming practise is to give plural names to collections such as sets and lists.

How to get a subclassed object of a django model

When I have a given django model class like this:
class BaseClass(models.Model):
some_field = models.CharField(max_length = 80)
...
and some subclasses of it, for example
class SomeClass(BaseClass):
other_field = models.CharField(max_length = 80)
Then I know I can get the derived object by calling
base = BaseClass.objects.get(pk=3)
my_obj= base.someclass
Now the problem arises that I have multiple subclasses, and all I have is an instance of the base class. How can I get to the subclassed object without knowing it's class in advance?
The idea is to load a corresponding view and let that do the stuff. My project features only have a limited set of default actions for these models, like view, edit, delete etc. What I don't want is to expose the type of the given object via URL, so the "normal way" is not available
There isn't a built-in way.
Perhaps the best thing to do is to define a derived_type field on your base class, which is set automatically on save of the derived class. You could then have a get_derived method on the base which checks the value of derived_type and returns the actual derived object.
How can I get to the subclassed object without knowing it's class in advance?
Why would this be useful? If you don't know what class you want, you also won't know which methods to call or which attributes can be inspected.
The idea is to load a corresponding view and let that do the stuff. My project features only have a limited set of default actions for these models, like view, edit, delete etc. What I don't want is to expose the type of the given object via URL, so the "normal way" is not available
If you know the set of model subclasses ahead of time, or are willing to register them with a central view list, you can do something like this:
VIEWS = [('subclass_a', a_views), ('subclass_b', b_views)]
def edit(request):
base = (get base somehow)
for attrname, views in VIEWS:
if getattr(base, attrname) is not None:
return views['edit']
Depending on how many different kinds of views you have, you might abstract the search out into a separate function, so the end view is something like:
def edit(request):
return generic_base_view(request, 'edit')
For people looking into this answer a bit later than the question was posted and the accepted answer was given, in the newer versions of django, this is possible more directly, see:
django documentation about multi table inheritance
look at the example of places and restaurants. The base object is a place, and the subclass is a restaurant. You can get the subclass by place.restaurant which gives an exception you can catch if the place is not a restaurant.
I add this because the answer accepted might be a bit outdated and led me to the wrong track.
If you use the InheritanceManager from django-model-utils then you can select the subclasses when you query without knowing what they are ahead of time.
https://django-model-utils.readthedocs.org/en/latest/managers.html#inheritancemanager

Categories