I'm using Django to create a site that provides a separate web UI for sorts of producers and consumers. Both UIs (or "subsites") have different layouts, menus and graphics. However they access the same database and models, just from different aspects (producer vs. consumer...).It's all hosted under a single domain, the UI differentiation is done with URLs.
The problem comes when I want to integrate a CMS to this system, to take care of the menu structures and textual content. How should I go about handling the two different menus for the different UIs? I took a look at django-cms and django-page-cms, and they seem to maintain only a single menu hierarchy.
Any ideas?
One dirtyish solution would be to add e.g. a different prefix for each UI's menu items in the CMS, and hack the CMS code so that it only inserts the menu items for the correct UI (given as a parameter to the show_menu template tag).
A nicer way would be if it was possible to have multiple instances of the CMS app, so that each of them had their own database tables as well. But is this possible with django and e.g. django-cms or django-page-cms?
Some further restrictions:
the CMS must support localization
I'd prefer running a single Django instance, to keep the configuration and testing simple
I have not used django-cms so this is just off the top of my head.
There's a section of the docs called Extending the menu that looked promising. It may be unfortunate that so much of their configuration is in settings.py because it looks like you could manipulate their CMS_TEMPLATES to use different base templates (etc.) for different users. One way of getting around this (assuming that there is not a more direct route) is to add something to the UserProfile that identifies a user as consumer/producer. Then in your base.html you do:
{% if user.get_profile.consumer %}
...
{% else %}
...
{% endif %}
This effectively gives you two entirely different look/feel options based on user type. I'll also note that {% extends %} can take either a string constant or a string variable, so you could use a context_processor to set the name of template you are extending.
What you need is show_menu_below_id tag of django-cms. Create the pages consumers and producers with their respective id (advanced fieldset, on bottom of the page form) and then start building the page hierarchy for each one.
Then in the templates uses the tags:
<ul>
{% if user.get_profile.consumer %}
{% show_menu_below_id "consumer" %}
{% else %}
{% show_menu_below_id "provider" %}
{% endif %}
</ul>
Related
For my application I want to serve a different base.html (and other templates and static files) for visitors and for admins: visitors will see a customized themed frontend, admins will see the editor interface (not related to the django admin interface). Some templates / resources will be shared between the two frontends.
I know I can do this by having separate settings.py configurations and include different template paths in each of them through a django app, but that would also mean I have to run two instances of the app. I'd rather serve both frontends from a single instance (or pool of workers).
Is there a way to dynamically add extra folders to the Django search path? That should suit my needs: if the user comes through the visitor domain, search the added path first and then the defaults, else just use the default template search path.
This is exactly why I've created django_layers
It's inspired by the Plone skinning/layer system where you can switch skins and have the framework search different layers for templates, staticfiles, and so on. I was missing something similar in Django where, like you, the only option I could find was inheritance or distinct INSTALLED_APPS configurations.
It turns out it's also very suitable for other use-cases such as A/B testing.
The packages is relatively new, let me know if it works for you or if you have issues if you decide to use it.
You can leverage template inheritance for this purpose, especially the {% extends %} template tag, which can accept variables instead of literal strings.
Example:
In your child templates make them extend unknown base template like this:
{% extends BASE_SITE_TEMPLATE %}
{% block page_head %}
<!-- Custom per-page static files may be defined here -->
{% endblock %}
{% block page_content %}
...
{% endblock %}
And then write a template context processor that will pass the BASE_SITE_TEMPLATE variable based on your custom conditions to rendered templates:
def base_site_template(request):
# Here goes your conditions to select proper base template, for example
# by checking request.user permissions or some other logic.
...
return {'BASE_SITE_TEMPLATE': ...}
Of course You will need to define various base templates, like base_site_user.html, base_site_editor.html, base_site_admin.html.
This method doesn't require you to change any of your views, just child templates, so I think it's one of the simplest methods to do what You want.
As you can read on the django reference or hacking a bit, get_flatpages can be used as follow:
{% get_flatpages as flatpages %}
{% get_flatpages for someuser as flatpages %}
{% get_flatpages '/about/' as about_pages %}
{% get_flatpages prefix as about_pages %}
{% get_flatpages '/about/' for someuser as about_pages %}
So, if I want to get a specific page I need to do it via its url or a prefix, which is somewhat rough, because my template code become data dependant, I meant, if I change the url of certain flat page then it is necessary to change my template code too.
A more flexible idea would be including an identifier to each page, addable through e.g. the 'Advanced options' section, so that the page can be refered via its identifier, thus we could do something like this:
{% get_flatpages 'about' as about_pages %}
Which is more flexible and less data dependant, no matter what url the page has, note we could change the page's url without changing the template code.
Is there something like that in the framework?, of course I could customize this app or to use a third-party app, but this isn't the point ;-)
Have you any other idea to deal with?
No, I don't believe there's any support for what you're asking for in Django at present. The docs you linked to for flatpages say:
A flatpage is a simple object with a URL, title and content. Use it for one-off, special-case pages, such as “About” or “Privacy Policy” pages, that you want to store in a database but for which you don’t want to develop a custom Django application.
My reading of this is "this is the bare minimum we're providing, and if you want any more you'll have to code it yourself". I agree that your proposal of allowing pages to be referred to by a symbolic name (which perhaps defaults to their URL) is more flexible, but you're probably better off raising an issue for it or discussing on the mailing list than hoping a dev happens upon your question on StackOverflow.
In the short term, you could look at some of the pre-built CMS-like Django apps. Django-page-cms is relatively lightweight (it's a relatively small app itself but does have a bunch of dependencies) and you could accomplish what you're after: each page is referred to by its slug (aka url / name), but you can define aliases / redirects to given pages for arbitrary URLs.
I have a simple (I hope so) question about the structure of a typical Django website. I have to restructure my site using some "Django-powered" pages mixed to other typical static pages.
I'd like to have a few templates and a lot of pages using these templates.
My question is:
What is the best way to provide different content for each page?
What I'm thinking right now is having different pages in my URL conf using the same templates and modifying the content within the View. But it's so unnatural to "hard-code" my content within the View, I suppose.
Is there a way to define content areas in my template and, for example, edit them within the Admin panel?
There must be better ways, I think.
Thank you!
Edit
Maybe Flatpages could help in my task. But does exist a way to add "content areas" tied to specific parts of the templates? I can fine only the main content area.
How are your "content areas" different than django's template blocks? You can define something like this in your layout file:
base.html
{% block overridable %}Default content{% endblock overridable %}
And in your templates, you extend it like this:
view.html
{% extends "base.html" %}
{% block overridable %} Overrided by view {% endblock overridable %}
You can use generic views, and I would heartily encourage you to. They're great. Check out the django docs for generic views. But as for different pages requiring a different template, yeah, that's how websites work.
Django is not "file-light" - it works by combining lots of small files. You're quite right to be averse to hard-coding HTML in your view controller - that's generally bad practice. You're going to have a template for each view, but really, how many views do you have? Even in a large application, the number of views that can't be handled by either a built-in or custom-made generic view is going to be pretty low.
I'm very new to django, about a week into it.
I'm making a site where users enter stuff, then other users can vote on whether they like the stuff or not. I know it's not so novel, but it's a good project to learn a bunch of tools.
I have a many-to-many table for storing who likes or dislikes what. Before I render the page, I pull out all the likes and dislikes for the current user, along with the stuff I'm going to show on the page.
When I render the page, I go through the list of stuff I'm going to show and print them out one at a time. I want to show the user which stuff they liked, and which they didn't.
So in my django template, I have an object called entry. I also have two lists of objects called likes and dislikes. Is there any way to determine if entry is a member of either list, inside my django template.
I think what I'm looking for is a filter where I can say something like
{% if entry|in:likes %}
or
{% if likes|contains:entry %}
I know I could add a method to my model and check for each entry individually, but that seems like it would be database intensive.
Is there a better way to think about this problem?
If you're using latest django version, then it's just
{% if entry in likes %}
Refer django docs
Go here. Very similar to what they're using on trunk. "Save this as smart_if.py in the templatetags folder of one of your apps. Then a simple {% load smart_if %} replaces the boring built-in Django {% if %} template with the new smart one."
If you're not running trunk one of the following should work:
Filter:
Replacement "if" tag, largely the basis for the new functionality in the upcoming 1.2 release:
i have a navigation element that is determined by values in a database.
no matter what view it is, i need to get these navigation objects out of the database.
where in the code can i tell it to set a template variable containing all the navigation objeccts without setting it in every view?
It sounds like a good use for a context processor.
Right way to do this is to use templatetag. Then you don't have to include it in every view, just in your templates like {% load navigation %} {% navigation %}
How to write one:
django docs on template tags (read overview and inclusion tags)
anoher resource