SQLAlchemy lost connection to Database when I am accessing model's property - python-2.7

python 2.7.10
SQLAlchemy 1.2.15
I have a model like this
class SomeClass(Base):
__tablename__ = 'some_table'
id = Column(Integer, primary_key=True)
name = Column(String(50))
if there will be a lot of time between getting an object and accessing its property I can get an exception
obj = SomeClass.objects.get(11)
sleep(10000) # Some time passed
print(obj.name)
Here I can get an Exception
psycopg2.InterfaceError: connection already closed
Is there any way to avoid this Exception?
UPD: I don't understand why it needs a connection to DB when it tries to get property from obj even if obj was received before???

Related

Using django-fsm to determine the state of an object

How do I get the current state of a database item using django-fsm.
I have tried get_state() but it returns a null value.
Here is my code:
from django.db import models
from django_fsm import FSMField, transition
STATES = ("Open", "In Progress", "Re Opened", "Done", "Closed")
STATES = list(zip(STATES, STATES))
class Ticket(models.Model):
title = models.CharField(max_length=40)
state = FSMField(default=STATES[0], choices=STATES)
Is there a way of getting the state field using django-fsm library.
Also, how do I get the available state transitions using the model methods.
You can get the value of the stat field by accessing it like a normal field:
ticket.state
If you want to get the display friendly version, FSMField works like any CharField(choices=[]) field using:
ticket.get_state_display()
You can get all of the available transitions by calling:
ticket.get_available_state_transitions()
You didn't define any transitions on your model so this call would not return anything at the moment.

Add new object to model with a foreign key

So this seems to be asked before but for the life of me, i cannot get any of the solutions to work.
I have two classes, Device and Log. There are many logs per device and i'd like to be able to add new items to the Log objects.
class Device(models.Models):
name = models.Charfield(max_length=100)
type = models.Charfield(max_length=100)
class Log(models.Modles):
device = models.ForeignKey(Device, related_name='msgs', on_delete=models.CASCADE)
log = models.Charfield(max_length=100)
date_time = models.DateTimeField(auto_now=True)
I've been trying things like this in my view:
device = Device.objects.filter(name=hostname)
device.msgs.add(log=new_log_msg)
but nothing i try is working. any ideas?
You need a Device instance, but filter always gives a queryset. You should use get.
device = Device.objects.get(name=hostname)
device.msgs.add(log=new_log_msg)
Get device object as
device = Device.objects.filter(name=hostname) # If hostname not found throw exception
For creating a new log
log = Log.objects.create(device=device, log='')
use get instead of filter in queryset and for creating and updating the alway intitiate the instance.
device = Device.objects.get(name=hostname)
device.msgs.add(log=new_log_msg)
For adding data in log
Log.objects.create(device=device, log='')
The device=device is foriegn key.

How to create an unique object for a Django model with a many to many field?

I want to create an unique object ( It couldn't exist another instance with the same fields). This object has a many to many relationship which is responsible of making it unique.
The object is a thread of messages, and this thread is a conversation between two users (really it could be between more users because I'm using a many to many field, but I'm only interested between two users ) .
class Thread(models.Model):
users = models.ManyToManyField(User, null=True,blank=True, related_name='threads')
class Mensaje(models.Model):
thread = models.ForeignKey(Thread, related_name='mensajes')#messages
When an user send a message to another user, if the thread doesn't exist it will be created, and if it exists the messages will be related with this thread.
I'm trying something like that:
thread = Thread.objects.get_or_create( users= [user1, user2])
But I have the next exception:
Exception Value: int() argument must be a string or a number, not 'list'
Any suggestions?
Thanks.
You can not use get_or_create directly for m2m. You can do something like this:
user_list = [user1, user2]
thread_qs = Thread.objects.filter(users=user_list[0])
for user in user_list[1:]:
thread_qs= thread_qs.filter(users=user)
try:
thread = thread_qs.get() #get if only one object.
except MultipleObjectsReturned as e:
print 'Multiple Objects Returned'
except ObjectDoesNotExist: #create object if does not exist
thread = Thread.objects.create()
thread.users.add(user_list)
thread.save() #this might be redundant

Django Save Model Idiom

Let's say you've got a ActiveDirectoryUser model:
class ActiveDirectoryUser(models.Model):
object_guid = models.CharField(max_length=200, unique=True)
mail = models.EmailField(unique=True)
name = models.CharField(max_length=200)
This model is populated from an Active Directory query. Every day, I rerun a job in batch that queries Active Directory, gets the results back, and checks if the person is already in AD. If they are it checks if anything has changed, and if not they get added to the Database. I found myself writing:
try:
ad_user = ActiveDirectoryUser.objects.get(object_guid=object_guid)
ad_user.object_guid = object_guid
ad_user.mail = mail
ad_user.name = name
ad_user.save()
except ActiveDirectoryUser.DoesNotExist:
ActiveDirectoryUser(
object_guid=object_guid,
mail=mail,
name=name).save()
Basically, I try to get the object with the attributes and if that throws a DoesNotExist exception, I know it's not already there and so I create a new one. Is this the right/best/idiomatic way of either updating or saving a new object into the database? I know it works, but it looks wrong somehow. Inelegant.
No, django has a built-in way to do this.
entry, created = ActiveDirectory.objects.get_or_create(
object_guid = 'your_value',
name = = 'your_value',
mail = 'your_value'
)

get_or_create failure with Django and Postgres (duplicate key value violates unique constraint)

Thanks for taking time to read my question.
I have a django app with the following model:
class UserProfile(models.Model):
user = models.OneToOneField(User)
...
class Visit(models.Model):
profile = models.ForeignKey(UserProfile)
date = models.DateField(auto_now_add=True, db_index=True)
ip = models.IPAddressField()
class Meta:
unique_together = ('profile', 'date', 'ip')
In a view:
profile = get_object_or_404(Profile, pk = ...)
get, create = Visit.objects.get_or_create(profile=profile, date=now.date(), ip=request.META['REMOTE_ADDR'])
if create: DO SOMETHING
Everything works fine, except that the Postgres Logs are full with duplicate key errors:
2012-02-15 14:13:44 CET ERROR: duplicate key value violates unique constraint "table_visit_profile_id_key"
2012-02-15 14:13:44 CET STATEMENT: INSERT INTO "table_visit" ("profile_id", "date", "ip") VALUES (1111, E'2012-02-15', E'xx.xx.xxx.xxx') RETURNING "table_visit"."id"
Tried different solution e.g.
from django.db import transaction
from django.db import IntegrityError
#transaction.commit_on_success
def my_get_or_create(prof, ip):
try:
object = Visit.objects.create(profile=prof, date=datetime.now().date(), ip=ip)
except IntegrityError:
transaction.commit()
object = Visit.objects.get(profile=prof, date=datetime.now().date(), ip=ip)
return object
....
created = my_get_or_create(prof, request.META['REMOTE_ADDR'])
if created: DO SOMETHING
This only helps for MySQL? Does anyone know how to avaid the duplicate key value errors for postgres?
Another possible reason for these errors in get_or_create() is data type mismatch in one of the search fields - for example passing False instead of None into a nullable field. The .get() inside .get_or_create() will not find it and Django will continue with new row creation - which will fail due to PostgreSQL constraints.
I had issues with get_or_create when using postgres. In the end I abandoned the boilerplate code for traditional:
try:
jobInvite = Invite.objects.get(sender=employer.user, job=job)
except Invite.DoesNotExist:
jobInvite = Invite(sender=employer.user, job=job)
jobInvite.save()
# end try
Have you at some point had unique=True set on Visit's profile field?
It looks like there's been a unique constraint generated for postgres that's still in effect. "table_visit_profile_id_key" is what it's auto generated name would be, and naturally it would cause those errors if you're recording multiple visits for a user.
If this is the case, are you using South to manage your database changes? If you aren't, grab it!
PostgreSQL behaves somewhat differently in some subtle queries, which results in IntegrityError errors, especially after you switch to Django 1.6. Here's the solution - you need to add select_on_save option to each failing model:
class MyModel(models.Model):
...
class Meta:
select_on_save = True
It's documented here: Options.select_on_save