Django How to generate value of attribute while initializing - django

I have a enum table ServiceType in my database which includes "Credit", "Investment" and "Insurance" and another table Service which have two columns - type_id and type. Is there a way to call method which will be generating value of type from value of type_id while initialization?
Should I use __init__ or maybe save?
type in Service is a ForeignKey to ServiceType
Thanks, sorry for my bad English.
So, I've tried something like this:
class Service(models.Model):
type_id = models.CharField(..)
type = models.ForeignKey('ServiceType',
to_field = 'type',
default = foo(type_id))
class ServiceType(models.Model):
type = models.CharField(..)

I've found the answer if anyone will be looking for it in future.
Things like that are managed by using signals. For above example I've used pre_save signal in function decorated as reciver.
In my understanding, reciver catches data before or after saving in database - way of doing it is based on type of signal. Those functions could basicly do anything, for example - change type of Service based on given type_id.

Related

Django Table Join

I am going over the django join on to get some query set.
I have declared two model like this
class PortService(models.Model):
port=models.IntegerField()
service=models.TextField()
class Meta:
unique_together=(('port','service'),)
class ServiceDefects(models.Model):
port=models.ForeignKey('PortService')
defect_id=models.TextField()
defect_description=models.TextField()
class Meta:
unique_together=(('port','defect_id'),)
I want to get all the entry of ServiceDefects class which has a port number of 80 and service named 'Apache'. For this I wrote the query like this:
ServiceDefects.objects.filter(portservice__port=80).filter(portservice__service='Apache')
Any Help?? Thanks in advance.
The foreign key field is called port, not portservice, so you should do:
ServiceDefects.objects.filter(port__port=80).filter(port__service='Apache')
You might prefer to put both arguments in a single filter():
ServiceDefects.objects.filter(port__port=80, port__service='Apache')
You should write both conditions in a single filter:
ServiceDefects.objects.filter(port__port=80, port__service='Apache')

how to get child instance of a foreignkeyfield in a query

i have three classes. Place is foreignkey of Activity(where the activity takeplace), Park and Restarant are inherited from Place.
class Activity(Model):
place=ForeignKeyField('Place')
....
class Place(Model):
address=CharField(max_length=200)
....
class Park(Place):
ticket_price=Decimal()
....
class Restarant(Place):
manager_name=CharField(max_length=100)
how can i get the real type of 'Place' in a query on Activity,so i can get the additional attributes of child type.
activity_list= Activity.objects.all()
all the activity_list[n].place are 'Place' ,neither Park or Restarant, so i can't get 'ticket_price' or 'manager_name' directly.
i have checked the model-utils, and can't find a easy way to do this.
any help will be appreciated.
inspect.getmro(cls)
Return a tuple of class cls’s base classes, including cls, in method resolution order. No class appears more than once in this tuple. Note that the method resolution order depends on cls’s type. Unless a very peculiar user-defined metatype is in use, cls will be the first element of the tuple.
try:
import inspect
for activity in activity_list:
print inspect.getmro(activity.place)
or try :
for activity in activity_list:
print activity.place._type()
try:
activity_list= Activity.objects.all()
for act in activity_list:
for b in act.place.__class__.__bases__:
print b.__name__
I use Django Inheritance Managers for this, from django-model-utils. It allows you to do exactly what you want...you said you checked model-utils to do this, but it didn't work. It should work -- what did you try with django-model-utils? You need to add this line to the parent model of Place:
objects = InheritanceManager()
I haven't tried this with your exact model design, but have you tried something like:
places = Activity.objects.all().values_list('place_id', flat=True)
places_of_right_type = Place.objects.filter(pk__in=places).select_subclasses()
?
------ UPDATE --------
Not sure this will work, but throwing it out there as an idea...would only work for a get(), not all():
places = Activity.objects.get(pk=#).place.objects.select_subclasses()
The docs say that you can call select_subclasses() on the InheritanceManager itself, which is stored in .objects.

Django: How to use django.forms.ModelChoiceField with a Raw SQL query?

I'm trying to render a form with a combo that shows related entities. Therefore I'm using a ModelChoiceField.
This approach works well, until I needed to limit which entities to show. If I use a simple query expression it also works well, but things break if I use a raw SQL query.
So my code that works, sets the queryset to a filter expression.
class ReservationForm(forms.Form):
location_time_slot = ModelChoiceField(queryset=LocationTimeSlot.objects.all(), empty_label="Select your prefered time")
def __init__(self,*args,**kwargs):
city_id = kwargs.pop("city_id") # client is the parameter passed from views.py
super(ReservationForm, self).__init__(*args,**kwargs)
# TODO: move this to a manager
self.fields['location_time_slot'].queryset = LocationTimeSlot.objects.filter(city__id = city_id )
BUT, if I change that to a raw query I start having problems. Code that does not work:
class ReservationForm(forms.Form):
location_time_slot = ModelChoiceField(queryset=LocationTimeSlot.objects.all(), empty_label="Select your prefered time")
def __init__(self,*args,**kwargs):
city_id = kwargs.pop("city_id") # client is the parameter passed from views.py
super(ReservationForm, self).__init__(*args,**kwargs)
# TODO: move this to a manager
query = """SELECT ts.id, ts.datetime_to, ts.datetime_from, ts.available_reserves, l.name, l.'order'
FROM reservations_locationtimeslot AS ts
INNER JOIN reservations_location AS l ON l.id = ts.location_id
WHERE l.city_id = %s
AND ts.available_reserves > 0
AND ts.datetime_from > datetime() """
time_slots = LocationTimeSlot.objects.raw(query, [city_id])
self.fields['location_time_slot'].queryset = time_slots
The first error I get when trying to render the widget is: 'RawQuerySet' object has no attribute 'all'
I could solve that one thanks to one of the commets in enter link description here, by doing:
time_slots.all = time_slots.__iter__ # Dummy fix to allow default form rendering with raw SQL
But now I'm getting something similar when posting the form:
'RawQuerySet' object has no attribute 'get'
Is there a proper way to prepare a RawQuerySet to be used by ModelChoiceField?
Thanks!
Are you sure you actually need a raw query there? Just looking at that query, I can't see any reason you can't just do it with filter(location__city=city_id, available_reserves__gte=0, datetime_from__gt=datetime.datetime.now()).
Raw query sets are missing a number of methods that are defined on conventional query sets, so just dropping them in place isn't likely to work without writing your own definitions for all those methods.
I temporarily fixed the problem adding the missing methods.
The way I'm currently using the ModelChoiceField I only needed to add the all() and get() methods, but in different scenarios you might need to add some other methods as well. Also this is not a perfect solution because:
1) Defining the get method this way migth produce incorrect results. I think the get() method is used to validate that the selected option is within the options returned by all(). The way I temporarily implemented it only validates that the id exists in the table.
2) I guess the get method is less performant specified this way.
If anyone can think of a better solution, please let me know.
So my temporary solution:
class LocationTimeSlotManager(models.Manager):
def availableSlots(self, city_id):
query = """SELECT ts.id, ts.datetime_to, ts.datetime_from, ts.available_reserves, l.name, l.'order'
FROM reservations_locationtimeslot AS ts
.....
.....
MORE SQL """
time_slots = LocationTimeSlot.objects.raw(query, [city_id])
# Dummy fix to allow default form rendering with raw SQL
time_slots.all = time_slots.__iter__
time_slots.get = LocationTimeSlot.objects.get
return time_slots

Some troubles while converting authors id to User model

My Post model have list of authors id
class Post(Document):
authors_id = ListField(IntField(required=True), required=True)
But sometime I need to use default Django User class. How most rapidly I can do it?
(I'm using sqlite for users and sessions and MongoDB (mongoengine ODM) for other. Don't ask why:))
I was tried to write it:
def get_authors(self):
authors = list()
for i in self.authors_id:
authors.append(get_user(IntField.to_python(self.authors_id[i])))
return authors
...and it raises 'list index out of range' exception. (authors id not empty, really). What I'm doing wrong?
Not sure about the to_python method but since you are looping through the authors_id, there is no need to do
authors.append(get_user(IntField.to_python(self.authors_id[i])))
You should be good with
authors.append(get_user(IntField.to_python(i)))
Instead of
IntField.to_python(self.authors_id[i]))
I think you just need to do:
IntField.to_python(i)
In Python the 'for i in some_list' construction gives you elements of the list, not integer indexes.
You said that you were getting this error:
and unbound method to_python() must be called with IntField instance as first argument (got int instance instead)
I got a similar error from MongoEngine. In my case the problem was that I defined the field like this:
foo_id = IntField
The correct way to define it is:
foo_id = IntField()
When I added the parenthesis, the problem went away.

How do I get the default value for a field in a Django model?

I have a Django model with some fields that have default values specified. I am looking to grab the default value for one of these fields for us later on in my code. Is there an easy way to grab a particular field's default value from a model?
TheModel._meta.get_field('the_field').get_default()
As of Django 1.9.x you may use:
field = TheModel._meta.get_field('field_name')
default_value = field.get_default()
You can get the field like this:
myfield = MyModel._meta.get_field_by_name('field_name')
and the default is just an attribute of the field:
myfield.default
if you don't want to write the field name explicitly, you can also do this:
MyModel._meta.get_field(MyModel.field.field_name).default
If you need the default values for more than one field (e.g. in some kind of reinitialization step) it may be worth to just instantiate a new temporary object of your model and use the field values from that object.
temp_obj = MyModel()
obj.field_1 = temp_obj.field_1 if cond_1 else 'foo'
...
obj.field_n = temp_obj.field_n if cond_n else 'bar'
Of course this is only worth it, if the temporary object can be constructed without further performance / dependency issues.