Immagine that I created a weblog application. Then I decide to make it accomodate multiple weblogs, by adding a weblog model and weblog_id to all records in the application.
Is there an easy way to achieve this without having to change all the model code in the application? I mean so that I don't have to go to the "post new entry" view for example and add some code to make sure the post is added to the correct weblog, then change the "view entries" view to filter comments to only display the ones made in that weblog, ..etc.
What I was thinking is someway of partitioning certain models then deciding the partition to be used somewhere outside the scope of any certain view.
On Fri, 2006-06-30 at 09:49 -0700, Ahmad Alhashemi wrote: > Hello,
> Immagine that I created a weblog application. Then I decide to make it > accomodate multiple weblogs, by adding a weblog model and weblog_id to > all records in the application.
> Is there an easy way to achieve this without having to change all the > model code in the application? I mean so that I don't have to go to the > "post new entry" view for example and add some code to make sure the > post is added to the correct weblog, then change the "view entries" > view to filter comments to only display the ones made in that weblog, > ..etc.
> What I was thinking is someway of partitioning certain models then > deciding the partition to be used somewhere outside the scope of any > certain view.
> I hope that my point is clear.
This thread is more appropriate for the django-users list than django-developers. Please send any follow-ups there.
To attempt to answer your question, though: I can't think of any automatic way to do this. I am not entirely clear about how you have set up your models (maybe post an example?), but if you need to ensure that the weblog_id field is set correctly then you are going to have to write some code to do that. Django can't read your mind; It does not know that you want to filter all your views and additions of new instances (via views) based on username and weblog_id or something like that.
Filtering based on username (or some other way to tie the request to the weblog_id). And this is a feature of views, not of the model itself (since models aren't tied to web requests). So you are going to have to edit your view logic to convert from the current environment (logged-in username or whatever) to the right filter condition.
Thank you for your reply. Sorry that my first email wasn't clear.
I wasn't asking on how to add this feature to an actual application I currently have, I'm asking for pointers because I want to add a new feature to Django's core that will make it easier to add such a feature to any Django application.
It is difficult for me to give an example of this feature because I've never seen it implemented anywhere else, but I've been thinking about it for a very long time.
Let me get back to the weblog_id example. Assume that I'm giving weblogs as subdomains and putting some code that will deduce the weblog_id from the subdomain and have it available for all views.
Then in the entries list, instead of displaying all entries, I will have to filter by weblog_id. In the RSS feeds, I will have to filter by weblog_id too. In the display all comments view I will have to filter by weblog_id.
See the pattern here?
Almost everything in the application is filtered by weblog_id.
When it comes to creating new objects, another pattern emerges. Everytime you create a new object, you will have to set the weblog_id. Everytime it will be the same line of code setting the weblog_id of that object to the weblog_id deduced at the initial processing of the request.
This is not very DRY.
I have two ideas on how to fix this.
The first one is to provide a feature in models that will allow me to pre-define some filters. For example, I can put one line that will make the ORM always filter the results of a certain object by weblog_id without having to specify the filter everytime something is retrieved.
Then provide another feature to the ORM to define the default value of a certain parameter in this particular request. So that I can say somewhere outside of all specific views that I want the weblog_id of any newly created posts to be set to a certain value without having to specify it everywhere a new post object is created.
The second idea is to provide this functionality at a higher level, where you can configure Django somewhere to split certain models by certain other models. For example, tell it to split the private messages model by the users model.
This feature will shine in areas where there is a major splitting variable that is splitting all the tables of the database almost to the extent that you can use seperate databases (but you don't want to do that). In these cases, filtering of the results by that variable is the rule, not the exception.
On Saturday 01 July 2006 21:03, Ahmad Alhashemi wrote:
> The first one is to provide a feature in models that will allow me to > pre-define some filters. For example, I can put one line that will > make the ORM always filter the results of a certain object by > weblog_id without having to specify the filter everytime something is > retrieved.
You could use a custom manager to achieve this -- you would override the get_query_set() function. However, the problem is how to tell the custom manager what the weblog_id is. There are ways I can think of doing this (using middleware and threadlocals and stuff), but I wouldn't advise them -- as much as possible a function's output should depend on its explicit input, not hidden inputs.
Would it not be possible to just create a couple of utility functions that encapsulate the logic of working out the weblog_id and applying the filtering? The function would take a QuerySet and HttpRequest object and apply the correct filtering, and return the new QuerySet.
Personally this is much better and simpler than trying to features to the ORM to enable this kind of special casing.
Luke
-- "Doubt: In the battle between you and the world, bet on the world." (despair.com)
I agree that explicitness is better. But I think implicit filtering here is not that bad for two reasons. The first is, as I said, it is the rule not the exception. The second is that it makes it extremely easy to start your application as a single site application then turn it into a multi-site application.
In all the other solutions, a lot of view code has to be changed when you decide to turn a single site application into a multi-site one.
Besides, I think of this feature more as DRY than as implicit parameter setting. It is in a way similar to authentication code. You don't have to repeat authentication code in every view becasue authentication is the rule not the exception.
The same way, you don't have to add code to tell the view that the table contains records for many weblogs and we are only interested in one weblog at a time. You will almost never run a query without specifying the weblog_id because the weblogs are completely seperate, and as I said before, you can almost put each weblog's data in its own database, but you don't want to do that.
On 7/2/06, Ahmad Alhashemi <ahmad.alhash...@gmail.com> wrote:
> I agree that explicitness is better. But I think implicit filtering > here is not that bad for two reasons. The first is, as I said, it is > the rule not the exception. The second is that it makes it extremely > easy to start your application as a single site application then turn > it into a multi-site application.
Django *does* already provide a way to do this: the CurrentSiteManager in django.contrib.sites[1]. Adding it to an existing model requires no changes to your database, and will require minimal changes to code that interacts with that model (and no changes whatsoever if you make it the default manager, which may or may not suit your use case).
> The same way, you don't have to add code to tell the view that the > table contains records for many weblogs and we are only interested in > one weblog at a time. You will almost never run a query without > specifying the weblog_id because the weblogs are completely seperate, > and as I said before, you can almost put each weblog's data in its own > database, but you don't want to do that.
There's no clean way to make Django automatically do all the filtering for you because, as Malcolm pointed out, Django can't read your mind and guess that you're always going to want to filter on a certain condition. However, the database API can still make your life a lot easier ; drop an ID or a slug or something in the weblog URLs which can be used to uniquely identify a weblog, and then filter on the related QuerySet. For example, if you had an Entry model related via ForeignKey to a Weblog model, the following would fetch the latest five entries:
Basically, once you've looked up the Weblog object, the 'entry_set' QuerySet attached to that Weblog will give you all the filtering you need; because it's a QuerySet, you can call all(), filter(), count(), etc. or any other query method on it.
On Sun, 2006-07-02 at 00:54 -0700, Ahmad Alhashemi wrote: > Hi Luke,
> I agree that explicitness is better. But I think implicit filtering > here is not that bad for two reasons. The first is, as I said, it is > the rule not the exception. The second is that it makes it extremely > easy to start your application as a single site application then turn > it into a multi-site application.
> In all the other solutions, a lot of view code has to be changed when > you decide to turn a single site application into a multi-site one.
> Besides, I think of this feature more as DRY than as implicit parameter > setting. It is in a way similar to authentication code. You don't have > to repeat authentication code in every view becasue authentication is > the rule not the exception.
> The same way, you don't have to add code to tell the view that the > table contains records for many weblogs and we are only interested in > one weblog at a time. You will almost never run a query without > specifying the weblog_id because the weblogs are completely seperate, > and as I said before, you can almost put each weblog's data in its own > database, but you don't want to do that.
To avoid going round and round in circles here with a lack of specifics, maybe you could suggest how you see this kind of API working. What would be added where to configure this type of filtering? And how will a request know what the right value to filter on would be?
I am struggling to see how you can do this without tying views to models. I think you are going to have to pass in some kind of identifying information from your view to indicate the filtering parameter's value. And that level of parameterisation can already be done with customer manager methods.
You are always going to have to specify the weblog_id (or whatever condition you are filtering on) somewhere and you are going to have to put in some logic somewhere to convert a request into the right weblog_id. The latter can be done by request context processors, so there's no repetition there, either.
On 7/2/06, Malcolm Tredinnick <malc...@pointy-stick.com> wrote:
> You are always going to have to specify the weblog_id (or whatever > condition you are filtering on) somewhere and you are going to have to > put in some logic somewhere to convert a request into the right > weblog_id. The latter can be done by request context processors, so > there's no repetition there, either.
It could also be done with middleware; for example, if he's using generic views he could pass 'Entry.objects.all()' or whatever his model's QuerySet is, then have a process_view() in middleware that looks up the correct weblog and tacks a filter() onto the QuerySet before handing off to the view.
Depending on exactly how he's setting things up, that might be simpler than doing a custom manager method.
-- "May the forces of evil become confused on the way to your house." -- George Carlin
Sorry again everyone. I don't actually have a specific application. Allow me to check all the suggestions, take a better look at Django then I promise I'll come back and summarize my findings.
In the mean time, does the need to tie the views with the models also apply to the proposed Row Level Permissions?