Since Joomla 2.5 I can call functions from the default model now with this code:
$result = $this->get('Data');
Where get and Data together are leading to the function name "getData".
But I cannot do this:
$myModel = $this->getModel('special_model');
$result = $myModel->getData();
and I can also not do:
$myModel = $this->getModel('special_model');
$result = $myModel->getData('myId');
So, I can't call a method directly and also not with a parameter? Is it correct? Why is it like this? In J!1.5 this was possible.
Best Regards
Björn
What you have actually will work in J2.5, but you have to add one more piece. That should work as is if you are in the 'special_model' view. Based on the naming though, you are trying to add a second model to the view. This model has to be added to the view from the controller:
$view = $this->getView('myview', 'html') ;
$view->setModel( $this->getModel( 'special_model' )) ;
Again, add that to the controller, and the code you have will work in the model.
Related
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
I want list all objects of my model, and write to file the id of selected model. Using SiteController I render my page but what model I shall use?
$models = myModel::model()->findAll();
$list = CHtml::listData($models, 'id', 'name');
echo CHtml::dropDownList( ???? , $select, $list);
If I get what you're trying to do, You're talking about two models. Like tbl_product => Product and tbl_category => Category.
For demonstration purpose: Say, you want to create a new product and every product must belong to a category, then you might make use of the active dropdown. Using code similar to yours, you can say:
$category = Category::model()->findAll();
$list = CHtml::listData($category, 'id', 'name');
An important thing to note is that CHtml::activeDropDownList() expects different kinds of arguments. The main difference between it and CHtml::dropDownList() is that activeDropDownList( is tied to a Model while dropDownList() isn't.
public static string activeDropDownList(CModel $model, string $attribute, array $data, array $htmlOptions=array ())
public static string dropDownList(string $name, string $select, array $data, array $htmlOptions=array ())
So, using the example, assuming our Product model has a field called category_id, then the dropdown list would be generated using either:
CHtml::activeDropDownList($model, 'category_id', $list);
or if you've created an Activeform object like this:
$form=$this->beginWidget('CActiveForm');
then you could create the dropDown list like this:
$form->dropDownList($model, 'category_id', $list);
Where $model would be the Product model.
I hope this has been helpful.
I was wondering what is the correct approach,
Do I create HiddenInput fields in my ModelForm and from the
View I pass in the primaryKey for the models I am about to edit into
the hiddenInput fields and then grab those hiddenInput fields from
the AJAX script to use it like this?
item.load(
"/bookmark/save/" + hidden_input_field_1,
null,
function () {
$("#save-form").submit(bookmark_save);
}
);
Or is there is some more clever way of doing it and I have no idea?
Thanks
It depends upon how you want to implement.
The basic idea is to edit 1. you need to get the existing instance, 2. Save provided information into this object.
For #1 you can do it multiple ways, like passing ID or any other primary key like attribute in url like http://myserver/edit_object/1 , Or pass ID as hidden input then you have to do it through templates.
For #2, I think you would already know this. Do something like
inst = MyModel.objects.get(id=input_id) # input_id taken as per #1
myform = MyForm(request.POST, instance=inst)
if myform.is_valid():
saved_inst = myform.save()
I just asked in the django IRC room and it says:
since js isn't processed by the django template engine, this is not
possible.
Hence the id or the object passed in from django view can't be accessed within AJAX script.
So i want to create:
select * from Post where Post.is_chosen = true order_by create_date
and i want this to occur in the urls.py (that is, not have to define anything, just stick it in the ListView parameters)
How do i do this?
I currently have:
url(r'^$',ListView.as_view(
queryset=Post.objects.get(is_chosen = True).order_by('-pub_date')[:20],
context_object_name='latest_post_list',
template_name='posts/index.html')),
but this has an error - i cannot call order_by on the return object of the "get" This makes sense, but how can i do what i want?
I am open to calling the command from a defined function if it is impossible to do in the url definition!
UPDATE: ARGH I am an idiot.
"get" only returns one item, so of course "order_by" won't work on it. I use filter instead now!
Like the docs say, use .filter() instead.
This seems like it should be dead simple, so I must be missing something. I just want to set the value of a field in my model instance by name. Say I have:
class Foo(Model):
bar = CharField()
f = Foo()
I want to set the value of bar by name, not by accessing the field. So something like:
f.fields['bar'] = 'BAR"
instead of
f.bar = 'BAR'
I've tried setattr but it doesn't persist the value in the database. I also tried going through _meta.fields but got various errors along the way.
If you modify the value via setattr, you need to remember to save the model after modifying it. I've been bitten in the past where I changed the values but forgot to save the model, and got the same result.
setattr(f, 'bar', 'BAR')
f.save()
We may have to see more code.
setattr(f, 'bar', 'BAR')
should work as this is how Django does it internally.
Make sure you are calling 'save', as well.