I have simple class:
class ChannelMessages:
def __init__(self, channel, date, message):
self.channel = channel
self.date = date
self.message = message
... somecode here ...
for message in messages:
ChannelMessages(name, message.to_dict()['date'], message.to_dict()['message'])
... name, date, message - is a variables ...
I want now to select all ChannelMessages class objects and put it in a variable. Im dont need to saving it anywhere, i need to render this Classes once on my app.
Im trying to use something like Django ORM:
ChannelMessages.objects.all()
but i cant select them this way. So is there a way to select all created objects w\o vars? Or i always shold specify variables for every created class object?
There's no built-in way to refer to all created instances of a particular class. APIs which enable you to do this have to implement this behaviour. Luckily you can very simply reproduce this behaviour with a class variable:
class ChannelMessages:
all_messages = []
def __init__(self, channel, date, message):
self.channel = channel
self.date = date
self.message = message
all_messages.append(self)
The all_messages list now hold a reference to all instantiated objects of its class, which, like all class variables, you can access either through the class itself (ChannelMessage.all_messages) or through any particular instance of the class (self.all_messages).
A more elegant solution would be using metaclasses and implementing __iter__ for the class itself, so you could write for message in ChannelMessages, but from a practical standpoint this works just as fine.
Why not store the items in a list?
allMessages = []
for message in messages:
allMessages.append(ChannelMessages(name, message.to_dict()['date'], message.to_dict()['message'])
Which can also be done in a single line using a list comprehension:
allMessages = [ChannelMessages(name, message.to_dict()['date'], message.to_dict()['message']) for message in messages]
Related
I am trying to make a simple library OOP program in Python.Here is the structure:
class Books(object) with attributes
class Books(object):
book_id=""
book_title=""
Books=[book_id,book_title]
def __init__(self,book_id,book_title):
self.book_id = book_id
self.book_title = book_title
#Books=[book_id,book_title]
book2= Books('1504231','Murders')
print(book1.__str__())
class BookList(Books) with objects of created by class Books
class BookList(Books):
def __init__(self):
self.listbook = []
book_list= BookList()
book_list.add_book_object(book2)
book_list.show_books()
(Operations in this scope works for me good)
class Users(object) with attributes (Similar def and init as for Books)
user1= Users ('adfelko','Adam')
print(user1.__str__())
class UserList(Users) with objects of created by class Users (Similar def and init as for BookList)
user_list= UserList()
user_list.add_user_object(user1)
user_list.show_users()
(Operations in this scope works for me good)
Now, I am trying to create actual Lease class, which will hold dictionary of objects(each object=each lease, each leases = [users object, books object])
This is my try:
#Definition of class Leases
class Leases(Users,Books):
#Set constructor
def __init__(self,user,book):
self.leases = [user,book]
#Create a lease
def borrow_book_to_user(self,u_name,t_book):
user=u_name
book=t_book
lease = [user,book]
self.leases.append(lease)
#Show lease
def __str__(self):
print(self)
Maybe I have a bad concept of using it, not sure, but I should probably not go through lists- BookList and UserList ?
Or how I should I get it connected and be able to call functions of the previous classes?
The thing for now works:
lease= Leases(user1,book2)
lease.__str__()
But the output looks something like this:
[<__main__.Users object at 0x0000010E69BFE280>, <__main__.Books object at 0x0000010E69BFE1F0>]
I would like to get direct out put like:
[ ['adfelko','Adam'],['1504231','Murders'] ]
With possibility to get access and change the attributes of this Users or Books object from Leases class, is someone able to help here please ?
Thanks
Best Regards
UPDATE:
#guimoute Thank you for your comment! It did not help to resolve, but helped me to understand more in depth.
I had to rethink my usage of Leases class(other stuff stay same):
#Definition of class leases
class Leases():
#Set constructor
def __init__(self):
self.leases = []
#Create lease object
def add_lease_object(self,user,book):
lease = { user : book}
self.leases.append(lease)
#Create lease object
def del_lease_object(self,user,book):
lease = { user : book}
self.leases.remove(lease)
#Show lease
def __str__(self):
return(self.leases)
#Show leases
def show_leases(self):
for l in self.leases:
#print(vars(l))
#json.dump(l,str)
print(l.__str__())
And I am executing:
lease= Leases()
lease.add_lease_object(user1,book2)
#print(lease.__str__())
print("*************************")
lease.show_leases()
print("*************************")
lease.add_lease_object(user2,book3)
print("*************************")
lease.show_leases()
print("*************************")
lease.del_lease_object(user2,book3)
print("*************************")
lease.show_leases()
Which seems to be working right, but again it is not showing output of nested objects as a string values:
{<main.Users object at 0x000001F9BD98E250>: <main.Books object at 0x000001F9BD8F2EB0>}
{<main.Users object at 0x000001F9BD98E250>: <main.Books object at 0x000001F9BD8F2EB0>} {<main.Users object at 0x000001F9BD98ED90>: <main.Books object at 0x000001F9BD98E1F0>}
{<main.Users object at 0x000001F9BD98E250>: <main.Books object at 0x000001F9BD8F2EB0>}
As you can see above I have tried even:
#print(vars(l))
#json.dump(l,str)
But similar result when trying to access nested object of different class. Do you have any better idea please ? Thank you
The ouptut you see:
{<main.Users object at 0x000001F9BD98E250>: <main.Books object at 0x000001F9BD8F2EB0>} {<main.Users object at 0x000001F9BD98ED90>: <main.Books object at 0x000001F9BD98E1F0>}
Is the default text representation of your instances of Users and Books. If you want it to display differently, you just have to override the __str__ method in both of these classes:
class Books(object):
[...]
def __str__(self) -> str:
return "{}, {}".format(self.book_id, self.book_title)
Now, when you directly (like with str(book1)) or indirectly call for a textual reprensentation of your Book and similarly User objects, your __str__ methods will be used instead of the default one.
So I have a very simple "Customer" class which only stores the name and creates an id:
import secrets
class Customer:
def __init__(self, name):
self.name = name
def get_id(self):
id = secrets.token_hex(20)
return id
In another class my objective is to create a list where all the instances of Customer are stored and in all the functions in the class I need to handle either the name or the id of those customers.
The two methods I've found so far are import gc and do something like this
for i in gc.get_objects():
if isinstance(i, Customer):
customer_list.append(i)
which I really dont understand and don't know if it works.
The other way I've found is to use getmembers(), but again I still have no idea about the syntax in using this function and how the name and the id will be stored.
Thanks in advance for any help!
a) In the following example I demonstrate a way to store object instances in a class variable (list) and access them throught that list. b) I think that your method get_id returns different id every time is called, so considering that you want only one id per customer I suggest to create the id inside __init__ and store it in a property.
import secrets
class Customer:
objects = []
def __init__(self, name):
self.name = name
self.id = secrets.token_hex(20)
Customer.objects.append(self)
Customer('A test')
Customer('B test')
Customer('C test')
for c in Customer.objects:
print(c.name, c.id)
I want to run this function only when the user logs in.
def purchased_today(self):
check = Rating.objects.filter(user=self.user, book__collection=self.collection, score__lte=4).order_by('newest')[:50]
a = check.count()
today = datetime.now().strftime("%Y-%m-%d")
if self.last_checked.date().strftime("%Y-%m-%d") != today:
return a
I tried it:
#receiver(user_logged_in)
def purchased_today(sender, user, request, **kwargs):
check = Rating.objects.filter(user=self.user, book__collection=self.collection, score__lte=4).order_by('newest')[:50]
a = check.count()
today = datetime.now().strftime("%Y-%m-%d")
if self.last_checked.date().strftime("%Y-%m-%d") != today:
return a
But it returns:
name 'self' is not defined.
how can i replace the self?
You don't say what kind of class self is referring to. But in this case, I would write code outside of that class that triggers on user_log_in, and instantiates a user class when that happens. Once the class is instantiated, you can call
purchased_today(self)
as before.
If you want to separate out the functions that can be run anytime versus the ones that must only be run when user is logged in, then I would make 2 separate classes and trigger instantiation of the 2nd one when user_log_in triggers.
The control code for the callback should be outside of the class either way.
I have the following code:
class Messenger(object):
def __init__(self):
# Class Type of what messages will be created as.
message_class = Message
def publish(self, body):
# Instantiate object of type stored in `message_class`
message = message_class(body)
message.publish()
I want to assert that the Message.publish() method is called. How do I achieve this?
I've already tried the following ways:
Assign message_class to Mock or Mock(). If I debug what message_class(body) returns, it is a Mock, but I don't seem to be able to get the instance and assert it (because the Mock I assign in my test is not the instance used, it is the Type).
Patch Message class with decorator. Whenever I do this it seems like it does not catch it. When I debug what message_class(body) returns its of Message type, not Mock.
Try to mock the __init__ method of message_class in hopes that I can set the instance that is returned whenever the code tries to Instantiate the message. Does not work, throws errors because the __init__ method is not suppose to have a return value.
If you were storing the actual instance, I'd say you could do something like messenger.message.publish.assert_called_once, but since message_class is being stored, it makes it slightly trickier. Given that, you can pull the return_value from the mocked class and check the call that way. Here's how I did it:
Messenger. Note the slight modification to assign message_class to self. I'm assuming you meant to do that, otherwise it wouldn't work without some global funkiness:
'''messenger.py'''
class Message(object):
def __init__(self, body):
self.body = body
def publish(self):
print('message published: {}'.format(self.body))
class Messenger(object):
def __init__(self):
# Class Type of what messages will be created as.
self.message_class = Message
def publish(self, body):
# Instantiate object of type stored in `message_class`
message = self.message_class(body)
message.publish()
Test:
'''test_messenger.py'''
from unittest import mock, TestCase
from messenger import Messenger
class TestMessenger(TestCase):
#mock.patch('messenger.Message')
def test_publish(self, mock_message):
messenger = Messenger()
messenger.publish('test body')
# .return_value gives the mock instance, from there you can make your assertions
mock_message.return_value.publish.assert_called_once()
Hoi, this is my first post and I am pretty new to django.
[Edit: changed "from" to "mfrom"]
I have a generic class like
class Message(models.Model):
mfrom = models.TextField()
text = models.TextField()
def beautify(self, text):
'''replace emoticons with images'''
return text
def save(self, *args, **kwargs):
self.text = self.beautify(self.text)
super(Message, self).save(*args, **kwargs)
and I have a few sources where messages are coming from that need different handling, some (like XMPP) will come from non HTTP request sources, but external scripts.
So I thought I'd make subclasses of Message for the different types like
class MessageXMPP(Message):
def load_from_XMPP(self, xmppmsg):
self.mfrom = xmppmsg.mfrom
self.text = xmppmsg.text
class MessageJSON(Message):
def load_from_JSON(self, jsonmsg):
self.mfrom = jsonmsg.mfrom
self.text = jsonmsg.text
If I now call the save() method of the above two classes django tries to save it to the MessageXMPP resp. MessageJSON tables, while I want the data to be stored in the Message table (and not have MessageXMPP resp. MessageJSON tables created at all).
Is there a way to not create a Message object and copy the values over, but have the subclasses write to the Message table?
I don't really understand why you have separate model classes here. You should really just have one class with the different methods. Even better, since these are creation methods, you should define a custom Manager which returns the instantiated Message.
However, if you insist on having separate classes, you should make them proxy models so that they do not reference their own tables:
class MessageJSON(Message):
class Meta:
proxy = True