Cutting applications vertically, like multiple weblogs software

22 visualizações
Pular para a primeira mensagem não lida

Ahmad Alhashemi

não lida,
30 de jun. de 2006, 12:49:4330/06/2006
para Django developers
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.

Malcolm Tredinnick

não lida,
30 de jun. de 2006, 20:23:2530/06/2006
para django-d...@googlegroups.com
Hi Ahmad,

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.

Best wishes,
Malcolm

Ahmad Alhashemi

não lida,
1 de jul. de 2006, 16:03:3601/07/2006
para Django developers
Hi Malcolm,

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.

Luke Plant

não lida,
1 de jul. de 2006, 16:44:0301/07/2006
para django-d...@googlegroups.com
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)

Luke Plant || L.Plant.98 (at) cantab.net || http://lukeplant.me.uk/

Ahmad Alhashemi

não lida,
2 de jul. de 2006, 03:54:1902/07/2006
para Django developers
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.

James Bennett

não lida,
2 de jul. de 2006, 04:54:0802/07/2006
para django-d...@googlegroups.com
On 7/2/06, Ahmad Alhashemi <ahmad.a...@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:

def latest_five_entries(request, slug):
weblog = Weblog.objects.get(slug__exact=slug)
latest_five = weblog.entry_set.all()[:5]
return render_to_response('latest_entries.html', { 'latest_five':
latest_five })

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.

[1] http://www.djangoproject.com/documentation/sites/#the-currentsitemanager

--
"May the forces of evil become confused on the way to your house."
-- George Carlin

Malcolm Tredinnick

não lida,
2 de jul. de 2006, 05:09:5702/07/2006
para django-d...@googlegroups.com

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.

Malcolm


James Bennett

não lida,
2 de jul. de 2006, 05:17:5302/07/2006
para django-d...@googlegroups.com
On 7/2/06, Malcolm Tredinnick <mal...@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.

Ahmad Alhashemi

não lida,
2 de jul. de 2006, 09:30:5702/07/2006
para Django developers
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?

Responder a todos
Responder ao autor
Encaminhar
0 nova mensagem