django admin FilterSpec per AdminSite - django-admin

Looking at the implementation in django.contrib.admin.filterspecs.py it seems to me that FilterSpecs are managed in a global registry they are tied up with the field type.
I am curious if it is possible to have:
- different custom filters for different AdminSite instances?
- different custom filters for a field belonging to different models?
- different custom filters for a combination of the two?
For example:
I have a class Article(models.Model) which has tags(some model Tag) associated with it. The tags have been created by users visiting the site.
In the Articles admin page, I wish to have selection on the basis of tags.
I have an AdminSite for super users in which all tags are visible.
I have another AdminSite for staff users in which I wish that only those tags are visible which have been created by current user.
The above example is contrived but I hope it gives the idea.

Related

How should MVC Controllers be organised?

Is there a general rule of thumb to how controllers should be organised?
Should Controllers only be created if they are linked to a domain model?
For instance if I have a 'Product' model, I would have a ProductController, which would have actions such as 'GetProductDetails' etc...
But what about things that don't have an actual model, such as searching for products, and returning multiple products on a page?
Since the Product model is the underlying model for all these interactions, should this functionality be included into the ProductController and have actions for searching and displaying multiple products, or should another be created for Search?
If you follow the pattern used by the scaffolding used in visual studio then yes you end up with one controller per entity so a product controller would have a actions that returned a list, a single product and an action for posting update to. In addition you might have additional search actions and any other product related actions. Which is just state and reinforce infer-on's answer.
However the reason why you would do this is that it means your code is easier to maintain - if you're looking for code to do with products you have one controller class to look in. You're also adhering to the principle of separation of concerns each controller is only concerned with one type of entity.
Further to this if your app grows much larger and you use an IoC / dependency injection pattern then you only need to inject one repository or business service per controller that is a search controller that offers methods to search for products and customers would need services or repositories for customer and products but a request might only be a customer search so the creation of the products repository was pointless hence you get inefficient and overly complex code. There are patterns to solve this issue but they involve even more code so to avoid this and to keep it simple stick to one root entity one controller.
You should manage every action which involve same resource with same controller, and you should implement that solution in accord with Richardson Maturity Model
A model (developed by Leonard Richardson) that breaks down the
principal elements of a REST approach into three steps. These
introduce resources, http verbs, and hypermedia controls.
so your API will be something like this:
/api/products GET Gets full list of all categories
/api/products/123 GET Gets the details for a single category
/api/products PUT Replaces the entire list of categories with
the one given
/api/products/123 PUT Update the specified category
/api/products POST Creates a new category
/api/products DELETE Deletes all categories
/api/products/123 DELETE Deletes the specified category

ASP.NET MVC - Model-binding for different views at runtime

My latest project involves actions returning different views at runtime (simply put, the application has a number of different customers as users, and they want their own custom data entry form designs - these forms all share the same model object-graph, but their display of the model's data is radically different to each other)...
For example, a "Case" entity has multiple People associated with it. Some forms only display a single Person's fields, other forms support multiple Persons, and another doesn't contain Person information at all. Furthermore, the forms have differing levels of fields - many forms lack many fields that others have.
Because of this radically different behaviour, I believe I'll need a different model binder for each view design.
Can StackOverflow recommend a course of action to take in this case, or an alternative solution that keeps the code simple.
If all your view models derive from a common abstract base view model you could have your POST action take this common view model as parameter and then write a custom model binder which will instantiate and bind the correct instance assuming each view sends an additional parameter containing the concrete type.
Here's an example of how this could be done.

How to handle multiple user types in Rails?

I'm finding a good way to modeling User different types in the system. For registration, he/she can select to be a student, a mentor, or both. Being a student or a mentor has different set of properties. Student and mentor will have different profile template layout as well.
How would you design your controllers and models for this kind of problem?
I would create a User which can hold a Mentor class and/or a Student class. This way your different properties are seperated from each other while the same properties still remain in the User class.
In the Controller you can render a template (or partial), depending on the instance the User holds. One for students, one for mentors and one for both.
You could also use Inheritance (User as parent with Mentor, Student and Both as childs). The key word you want to look into here is Single Table Inheritance.
Imho the problem is the both option. That's why I would prefer the 1st solution.

How can I modify the queryset in the change list view depending on a parameter I set in the URL

My problem is the following and it is related to the change list view of the admin interface.
I have a workorder model with several fields to caracterize the work order.
They are : type, nature, scheduling_type (and others).
When I see the list view, I would like to be able to change the filter (thus be able to create complex ones depending on the values of the different fields of the workorder model - the ones above and dates for example).
I have found post showing how to modify the default queryset (using managers for example) but I can't find a post that will use a value that is given in the url (ex. admin/workorder/planned_corrective). When the parameter planned_corrective is found, it must be used to select the appropriate queryset or manager and render the corresponding list.
As a add on, I want from that list to be able to use the standard admin options (like list filters, search ...) on that query.
Hope it is clear and thanks in advance for your help.
It sounds like you're after a RESTful interface.
You could accomplish much of this just by being clever with your urls.py - ie, defining admin/workoder/planned_corrective and every other possible parameter that could be encoded in the URL.
A lot of this can also be accomplished just by adding a get-absolute-url method to your models.
Or, you could the effort into using something like the django-rest-interface in your app.

Symfony Admin Generator in multi user setup (restricting records in LIST view)

I am using SF 1.2.9 to build a website. I want to use the admin generator to provide admin functionality for the object models I have used (specifically LIST, edit and delete).
I have read the Symfony docs (Chapter 14), but unless, I am very much mistaken, all examples I have come accross so far, seems to be written for a single user environment only. Meaning that the list of records returned to the user is essentially, ALL the records in that table. In a multiuser environment, this is irresposible at best, and potentially, a security threat. It is a necessary requirement to restrict the list of records returned to a user to only those that they own (i.e. created).
Suppose I have a table with (YML) schema like this:
foobar_dongle:
id: ~
title: varchar(255)
info: longvarchar
owner_id: ~
created_at: ~
where owner id is a FK into a user table.
Assume I generate an admin module like this:
symfony propel:generate-admin backend FoobarDongle --module=dongle
Question:
How do I modify the list of records returned to a user in the LIST part of the code generated by the admin generator? As I mentioned above, currently, (i.e. out of the box), the admin generator presents the user (rather naively, I feel), with the ENTIRE set of records for the model being administered. I need to be able to restrict that list somehow, so that I can only return records owned by that user.
This is what I am trying to find out how to do.
I would be most grateful to anyone who can show me how I can restrict the list of records returned when using the admin generator for administration of an object model. Ideally, I would like to be able to specify a custom method that has all the custom 'filtering' logic - but so long as I can restrict the LIST of records a user can see (in admin), to only the records that he is the owner of, that is all I want to be able to do.
If you only want to restrict the returned objects in one or two modules, do this:
Go to the actions.class.php file of your module. There should be no methods by default and the class should inherit from autoModuleNameActions you. Insert the following method:
protected function buildQuery()
{
$query = parent::buildQuery();
// do what ever you like with the query like
$query->andWhere('user_id = ?', $this->getUser()->getId());
return $query;
}
But this becomes unhandy if you do it for more modules. In this case I would advice to create a new admin generator theme.
And if you want to make the query depending on some custom parameter in the admin generator config file, then you have to extend this file. But is not just done with adding a new parameter. You can read this article how to do this.
If you want to know more about the auto generated classes, have a look at this class: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.
Edit after comments:
I think you looked at the wrong class. Look here: cache/[app]/[env]/modules/auto[ModuleName]/actions/actions.class.php.
I set up a Propel project to check it and the method that is interesting for you is:
protected function buildCriteria()
{
if (is_null($this->filters))
{
$this->filters = $this->configuration->getFilterForm($this->getFilters());
}
$criteria = $this->filters->buildCriteria($this->getFilters());
$this->addSortCriteria($criteria);
$event = $this->dispatcher->filter(new sfEvent($this, 'admin.build_criteria'), $criteria);
$criteria = $event->getReturnValue();
return $criteria;
}
I also posted the whole content of this class to pastebin. It is a lot, the function is in line 245. Even if you don't find this class, you should be able to override this method like this:
protected function buildCriteria()
{
$criteria = parent::buildCriteria();
// do something with it
return $criteria;
}
I don't know about these criteria objects, so I can't help you with that but I hope the other things help you.
You should use sfGuardPlugin to provide your login/user functionality - it includes user groups and permissions that can be assigned to users and/or groups.
Using security.yml you can then configure which permissions/credentials are required to access individual actions. IE: you can allow everyone to access the list/update/delete actions, but only people with the create permission to access the create page.
The docs for sfGuardPlugin are worth reading:
http://www.symfony-project.org/plugins/sfGuardPlugin
Plus this section from the jobeet tutorial covers sfGuard and also use of security.yml and credentials:
http://www.symfony-project.org/jobeet/1_2/Propel/en/13
And to round off, this page from the book is relevant too:
http://www.symfony-project.org/reference/1_2/en/08-Security (although not sure it covers anything that isn't in the page i linked from jobeet)

Resources