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.
Related
I have 2 models:
class ModelA:
fieldA = models.ManyToManyField(ModelB, through="CustomThroughTable")
def foobar(self):
return self.fieldA.through.objects.filter(fieldA=self)
class ModelB:
whatever = models.CharField()
I want to implement a function in ModelA that would print out all the values of fieldA in the through table. The current implementation of the function foobar does what I need right now, but I figure it's rather inefficient. Is there a better way to do this? Thanks.
I don't see anything inefficient about that query, you'll have to debug your problem more precisely.
That said, you can achieve the same thing more simply (and equally efficiently) by just using a related name on the through table.
class ModelA(models.Model):
fieldA = models.ManyToManyField(ModelB, through="CustomThroughTable")
class ModelB(models.Model):
whatever = models.CharField()
class CustomThroughTable(models.Model):
modela = models.ForeignKey(ModelA, related_name="foobar")
modelb = models.ForeignKey(ModelB)
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.
OK here goes, this is one of those questions that makes perfect sense in my head but is difficult to explain properly :) I have a django app where I want to store records for lots of different items of equipment. Each type of equipment will have a custom model to store its attributes, such as MyEquipment below. Each type of equipment will also have a 'category', which would be useful to store as an attribute.
class Category(models.Model):
code = models.CharField('Category', max_length=4, unique=True)
description = models.CharField('Description', max_length=30)
...
class MyEquipment(models.Model):
serial = models.IntegerField()
...
To save this attribute to my model I could use a foreign key to Category but I don't need to because every record in MyEquipment must be the same Category. So then I thought maybe I could hardcode the Category in the MyEquipment meta like this:
class MyEquipment(models.Model):
serial = models.IntegerField()
...
class Meta:
category = Category.objects.get(code='EC')
But then this would rely on the Category model being populated with data to build the MyEquipment model. To me this doesn't seem best practice, using data that may or may not exist to define the structure of another model. Is there a better way I should be using to set which Category the MyEquipment model is related to?
EDIT
Thanks for the discussion below, it's made me realise perhaps I wasn't clear on my original post. So what I want to do is have a way of linking MyEquipment to a Category. So I can do something like this:
>>> from myapp.models import MyEquipment
>>> MyEquipment.CATEGORY
<Category: EC>
I want to link the whole model to a Category, so I can process each model in different ways in my view depending on which category it is. Having thought about the problem a bit more, I can get this functionality by writing MyEquipment like this:
class MyEquipment(models.Model):
CATEGORY = Category.objects.get(code='EC')
serial = models.IntegerField()
...
This way works, but is it the best way? I guess the model would do this get operation everytime the class is instantiated? Is there a more efficient method?
You can't do this anyway; the Meta class doesn't support arbitrary attributes.
The best thing would be to define this as a property, which you can access via the instance itself. To make it more efficient, you could memoize it on the class.
#property
def category(self):
_category = getattr(self, '_category', None)
if not _category:
self.__class__._category = _category = Category.objects.get(code='EC')
return _category
but ... every record in MyEquipment must be the same Category
Then you don't need any relationship. As you said already, every record in MyEquipment are same Category, why do you want to store relation in db?
UPD: Solution with model inheritance
class Place(models.Model):
category = models.ForeignKey(Category)
class Meta:
abstract = True
def save(self, *args, **kwargs):
self.category = Category.objects.get(name=self.CATEGORY)
return super(Place, self).save(*args, **kwargs)
class Restaurant(Place):
...fields...
CATEGORY = 'RE'
class Building(Place):
...fields...
CATEGORY = 'BU'
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.
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.