Defining more models in a decorator - python

I have a pattern that I'd like to make as reproducible as possible, it goes something like this:
class TranslatedThing(models.Model):
name = models.Charfield(max_length=100)
class Thing(models.Model):
translation = models.ForeignKey(TranslatedThing)
name = models.Charfield(max_length=100)
The idea being that in my raw data I have some Things, which map to a reduced set of translated Things. Across many different data sets I have many different types of Things.
I already use an Abstract class to reduce the complexity of this pattern:
class AbstractThing(models.Model):
name = models.CharField(max_length=100)
class Meta:
abstract = True
-------
class TranslatedThing(AbstractThing):
pass
class Thing(AbstractThing):
translated = models.ForeignKey(TranslatedThing)
But I'd like to automate the creation and linkage to TranslatedThing. Is this possible with a decorator? e.g.
#translate
class Thing(AbstractThing): pass
----
Thing.objects.filter(translation__name="foo") #works
I've read through but it looks like maybe not. Is there any other way to reduce the repetition of code while using this pattern?

Related

How to pass multiple query-set in another class function

Let suppose I have some model
class Testmodel1():
amount = models.IntegerField(null=True)
contact = models.CharField()
class Testmodel2():
price = models.ForeignKey(Testmodel1, null=True)
Now I am using django ORM and apply a query like:
objs = Testmodel2.objects.filter(price__amount=123)
and it is returning n number of obj in any case like (obj1, obj2,..) ,
also I have written a another function in another class which is handling these obj and performing some other task, like-
Class SentMail():
def sending_mail(self, price_obj):
"""performing some task """
SO, currently I am doing like
for obj in objs:
sentmail().sending_mail(obj)
Is there any other better way to do this to make it better, I tried to find a good way, but don't get.
any help would be appreciated.

Is it appropriate to use Django's abstract classes for simple code reuse?

I am learning Django and writing my first semi-complex model. Many of my tables are made with a similar view style in mind, so many objects have a name, a description and an image. Ex:
class Ingredient(models.Model):
# Standard to many classes
name = models.CharField(max_length=50)
description = models.TextField()
image_url = models.URLField(max_length=200)
# Unique to this class
foodgroup = ..... etc.
Since name, description and url will be common to many objects (that are otherwise totally different), I was considering defining a base class that each can inherit from:
class BaseObjectWithImage(models.Model):
# Standard to many classes
name = models.CharField(max_length=50)
description = models.TextField()
image_url = models.URLField(max_length=200)
class Meta:
abstract = True
class Ingredient(BaseObjectWithImage):
# Unique to this class
foodgroup = ..... etc.
My question - which may be closer to a simple OOP Best Practices question - is whether this is a silly use of Django's abstract class, or if is worthwhile for stripping out 3xN lines of code and allowing me to treat most model classes as a generic type.
Not a silly use of abstact classes. Both Django and python are relatively polygamous in that they allow you to use many different programming styles (whichever one suits you best). Just make sure that you are making a consistent and conscious decision as to whether the models create individual tables each with its own copy of the repeated columns or whether they each contain a ForeignKey to a common base table.

django simple history - using model methods?

I'm using django-simple-history:
http://django-simple-history.readthedocs.io/en/latest/
I have a model, which I would like to apply its methods on an historical instance. Example:
from simple_history.models import HistoricalRecords
class Person(models.Model):
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
history = HistoricalRecords()
def fullName(self):
return firstname + lastname
person = Person.objects.get(pk=1) # Person instance
for historyPerson in person.history:
historyPerson.fullName() # wont work.
Since the class HistoricalPerson does not inherit the methods of Person. But using Person methods actually make sense, since they share the same fields..
Any solution for this? I'd prefer something simple, not like duplicating every method in my models for the history instances..
I found another workaround (maybe it's just the addon had been updated and got this feature). It's based on the documentation: adding-additional-fields-to-historical-models
HistoricalRecords field accepts bases parameter which sets a class that history objects will inherit. But you can't just set bases=[Person] inside Person class description, because it's not yet initialized.
So I ended up with an abstract class, which is inherited by both Person class and HistoricalRecords field. So the example from the question would look like:
class AbstractPerson(models.Model):
class Meta:
abstract = True
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
def fullName(self):
return firstname + lastname
class Person(AbstractPerson):
history = HistoricalRecords(bases=[AbstractPerson])
And now history objects can use fullName method.
For anyone else having the same problem, I made it work by calling the method from the original class on the historical record object. So for the example in the question, a solution could be:
for historyPerson in person.history:
Person.fullName(historyPerson)
This works because methods are very much like functions in Python, except that when you call a method on an instance, the instance is implicitly passed as the first parameter for the method. So if you have a class like:
class Foo:
def method(self):
....
doing
f = Foo()
f.method()
is the same as:
f = Foo()
Foo.method(f)
I don't know exactly why simple-history does not copy the original model's methods though. One reason might be that since it allows you to exclude fields to be recorded, having the original methods might not make sense, since a method might not work if it uses fields that are not recorded in the historical record.

Django model class methods for predefined values

I'm working on some Django-code that has a model like this:
class Status(models.Model):
code = models.IntegerField()
text = models.CharField(maxlength=255)
There are about 10 pre-defined code/text-pairs that are stored in the database. Scattered around the codebase I see code like this:
status = Status.objects.get(code=0) # successful
status = Status.objects.get(code=1) # failed
I would rather have a method for each so that the code would look something like this instead:
status = Status.successful()
status = Status.failed()
etc...
Is this possible? I have looked in to the Manager-stuff but I haven't really found a way. Is it time to really RTFM?
In Java it would be a static method and in Ruby you would just define a method on self, but it's not that easy in Python, is it?
You should perhaps implement this by defining a custom manager for your class, and adding two manager methods on that manager (which I believe is the preferred way for adding table-level functionality for any model). However, another way of doing it is by throwing in two class methods on your class that query and return resulting objects, such as:
class Status(models.Model):
code = models.IntegerField()
text = models.CharField(maxlength=255)
#classmethod
def successful(cls):
return cls.objects.get(code=0)
#classmethod
def failed(cls):
return cls.objects.get(code=1)
Do note please that get() is likely to throw different exceptions, such as Status.DoesNotExist and MultipleObjectsReturned.
And for an example implementation of how to do the same thing using Django managers, you could do something like this:
class StatusManager(models.Manager):
def successful(self):
return self.get(code=1)
def failed(self):
return self.get(code=0)
class Status(models.Model):
code = models.IntegerField()
text = models.CharField(maxlength=255)
objects = StatusManager()
Where, you could do Status.objects.successful() and Status.objects.failed() to get what you desire.

Finding all classes that derive from a given base class in python

I'm looking for a way to get a list of all classes that derive from a particular base class in Python.
More specifically I am using Django and I have a abstract base Model and then several Models that derive from that base class...
class Asset(models.Model):
name = models.CharField(max_length=500)
last_update = models.DateTimeField(default=datetime.datetime.now())
category = models.CharField(max_length=200, default='None')
class Meta:
abstract = True
class AssetTypeA(Asset):
junk = models.CharField(max_length=200)
hasJunk = models.BooleanField()
def __unicode__(self):
return self.junk
class AssetTypeB(Asset):
stuff= models.CharField(max_length=200)
def __unicode__(self):
return self.stuff
I'd like to be able to detect if anyone adds a new AssetTypeX model and generate the appropriate pages but currently I am maintaining a list manually, is there a way to determine a list of class names for anything that derives from "Asset"?
Asset.__subclasses__() gives the immediate subclasses of Asset, but whether that's sufficient depends on whether that immediate part is a problem for you -- if you want all descendants to whatever number of levels, you'll need recursive expansion, e.g.:
def descendants(aclass):
directones = aclass.__subclasses__()
if not directones: return
for c in directones:
yield c
for x in descendants(c): yield x
Your examples suggest you only care about classes directly subclassing Asset, in which case you might not need this extra level of expansion.

Categories