I am using custom template tags to show site-specific content. Templates for these tags are stored in database and staff is able to edit them. I used that SO answer as reference. Each time after template changed and saved into database, I force reloading of django app (by reloading uwsgi service) or changes doesn't become visible. Looks like Django populates template library for custom tags only on first load of app.
I think reloading Django app isn't best practice to refresh DB templates, and I am searching way to do it programmatically (from model's save() or on save signal)
Template tags code:
from django.template import Template, Library
from project.custom_templates.models import DbTemplate
register = Library()
# template names
SHOW_PART_TABLE_ADMIN = 'custom/tags/show_part_table_admin.html'
SHOW_PART_TABLE_PUBLIC = 'custom/tags/show_part_table_public.html'
t_show_part_table_admin = Template(DbTemplate.objects.get(name=SHOW_PART_TABLE_ADMIN).content)
t_show_part_table_public = Template(DbTemplate.objects.get(name=SHOW_PART_TABLE_PUBLIC).content)
#register.inclusion_tag(t_show_part_table_admin)
def show_part_table_admin(parts, user, perms):
return {'parts': parts, 'user': user, 'perms': perms}
#register.inclusion_tag(t_show_part_table_public)
def show_part_table_public(parts, user, perms):
return {'parts': parts, 'user': user, 'perms': perms}
Related
I want to write custom template loader for my Django app which looks for a specific folder based on a key that is part of the request.
Let me get into more details to be clear. Assume that I will be getting a key on every request(which I populate using a middleware).
Example: request.key could be 'india' or 'usa' or 'uk'.
I want my template loader to look for the template "templates/<key>/<template.html>". So when I say {% include "home.html" %}, I want the template loader to load "templates/india/home.html" or "templates/usa/home.html" or "templates/uk/home.html" based on the request.
Is there a way to pass the request object to a custom template loader?
I've been searching for the same solution and, after a couple days of searching, decided to use threading.local(). Simply make the request object global for the duration of the HTTP request processing! Commence rotten tomato throwing from the gallery.
Let me explain:
As of Django 1.8 (according to the development version docs) the "dirs" argument for all template finding functions will be deprecated. (ref)
This means that there are no arguments passed into a custom template loader other than the template name being requested and the list of template directories. If you want to access paramters in the request URL (or even the session information) you'll have to "reach out" into some other storage mechanism.
import threading
_local = threading.local()
class CustomMiddleware:
def process_request(self, request):
_local.request = request
def load_template_source(template_name, template_dirs=None):
if _local.request:
# Get the request URL and work your magic here!
pass
In my case it wasn't the request object (directly) I was after but rather what site (I'm developing a SaaS solution) the template should be rendered for.
To find the template to render Django uses the get_template method which only gets the template_name and optional dirs argument. So you cannot really pass the request there.
However, if you customize your render_to_response function to pass along a dirs argument you should be able to do it.
For example (assuming you are using a RequestContext as most people would):
from django import shortcuts
from django.conf import settings
def render_to_response(template_name, dictionary=None, context_instance=None, content_type=None, dirs):
assert context_instance, 'This method requires a `RequestContext` instance to function'
if not dirs:
dirs = []
dirs.append(os.path.join(settings.BASE_TEMPLATE_DIR, context_instance['request'].key)
return shortcuts.render_to_response(template_name, dictionary, context_instance, content_type, dirs)
I learned that I can add a custom button in my Admin form by adding it to
fields = ["connect"]
readonly_fields = ('connect',)
def connect(self, obj):
return format_html("<button></button>")
connect.allow_tags=True
connect.short_description = ''
However, the html I want to add to the connect is getting out of control. I was wondering if there's a proper (Django-nic) way to move that to a template and load and return the content of the template in the connect function.
I can think of reading the content of the template file (open('file.html', 'r')) to read the content, however, I am looking for a suggestion that aligns Django standards (if any).
P.S. I also tried creating a view for getting the HTML content of the connect file, but that for some reason doesn't seem to work and feels unnatural to do.
from django.template.loader import render_to_string
...
def connect(self, obj):
html = render_to_string('file.html')
return html
With file.html in templates directory
i have an existing application data base from which my web site should only fetch the data according to user input. Added database details in the settings.py file and I tried python manage.py integratedb and get the all the 300+ tables came off to my models.py file. I was never able to do python manage.py runserver it threw a million errors. Now i found a work around but i need your opinion on this.
I added the default server into the settings.py and using it i was able to run the server. settings.py looks like this.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'mydatabase',
},
'user': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME' : 'test',
'USER' : 'testuser',
'PASSWORD': 'readonly',
'HOST' : '10.20.30.40',
'PORT' : '5446',
}
}
Now can i access the user db to fetch data from my form? for example
views.py looks like this
from django.shortcuts import render_to_response
from .models import TestCases
from django.shortcuts import HttpResponse
from django.http import JsonResponse
from django.forms.models import model_to_dict
from django.views.decorators.csrf import csrf_exempt
# Create your views here.
#csrf_exempt
def index(request):
posts = TestCases.objects.all()[:10]
return render_to_response('index.html',{'posts':posts})
where TestCases is a class name from the models.py file.
Now when i click the button to retrieve data i get "no such table: test_cases"
models.py looks like
class TestCases(models.Model):
id = models.BigIntegerField(primary_key=True)
clientid = models.ForeignKey(Clients, db_column='clientid')
projectid = models.ForeignKey(Projects, db_column='projectid')
class Meta:
managed = False
db_table = 'test_cases'
what am i doing wrong to get the data from the user input. please help.
Queryset .using() method
I guess Django is going for the default database.
Try this:
#csrf_exempt
def index(request):
posts = TestCases.objects.using('user').all()[:10]
return render_to_response('index.html',{'posts':posts})
When you set using to your queryset, you can specify which database django is going to query.
More information in Django docs
A better approach, so you don't have to manually set it to all your queries.
You can manually add it to all your queries, or you can create a custom manager to your objects and force it to use a specific database for objects.
Ex:
# this will override the default queryset for objects that use this Manager
class UserDatabaseManager(models.Manager):
def get_queryset(self):
return super().get_queryset().using('user')
class MyModel(models.Models):
objects = UserDatabaseManager()
Then, when you use MyModel, you can query as usually and Django will use the user db for default just for models that have objects = UserDatabaseManager().
Keep in mind that this is just a simple use of the Manager, you can have multiple managers and do a lot of cool stuff.
Take a look at the Django Managers docs
first of all you need to do:
python manage.py inspectdb > models.py
to store your models to models.py
By default, inspectdb creates unmanaged models. That is, managed = False in the model’s Meta class tells Django not to manage each table’s creation, modification, and deletion, if you do want to allow Django to manage the table’s lifecycle, you’ll need to change the managed option above to True (or simply remove it because True is its default value).
Next, run the migrate command to install any extra needed database
python manage.py migrate
integrating docs
I want to display mugshot and background from Userena in one of my APP namely UserBackground 's Template.But it seems to me that it is not a easy task to do for a person who is really new in Django like me.I have tried to do this several times but its not working.This is view which resides in my UserBackground , where i have tried to capture the Mugshot,but i failed.
from django.contrib.auth.models import User
from Photo.models import photo #Photo Model of the App
def userphoto(request,user_id):
user = Photo.objects.filter(user = user_id)
user_mugshot = get_object_or_404(User,username__iexact=user_id)
context = RequestContext(request)
ctx_dict = {'user': user,'user_mugshot' : user_mugshot}
return render_to_response('photo/user_portfolio.html',locals(),ctx_dict,context)
#return HttpResponse(ctx_photo)
and this is the urls.py
url(r'^(?P<user_id>\d+)/user_photo/$',views.userphoto,name = 'userporrfolio')
i write those codes in my View according to this link.
How to use the Django Usurena "mugshot" template variable
i am not sure is it right way to capture Mugshot from userena app in another app.
I need to allow the admin user to make an email template in html, and the user should be able to add dynamic variables where needed. The template will be saved in the database. For example,
Dear {{user.first_name}},
Thanks for participating in our cooking class on {{cooking_class.date}}
Then, there will be a cron job which will send emails and fill the dynamic variables.
What are my options? Is there a django package for this? I am using Django 1.4.3
thanks
I implemented something similar, here's what I did:
Create an app, and registered a model to store the email
Set up a management command to process the email
Manage the cron job via django-chronograph
Rendering the email, I used render_to_string, for example
from django.template.loader import render_to_string
from myproject.myemailapp.models import EmailTpl
email_tpl = EmailTpl.objects.get(...#criteria here)
# fetch the rest of your dynamic variables
rendered_tpl = render_to_string(email_tpl.user_entered_tpl, {
"user": user,
"cooking_class": cooking_class,
# ... and so on
})
Alternatively, Django Packages has some packages you might want to look into. Would be great if you post back the route you decided.
The plugin django-dbtemplates allows you to store templates in your database, and you can expose the dbtemplate app on your Admin site to edit. You can set your middleware settings such that either the database template or the same template in other locations has priority for loading.
We are using this in a project to manage templates for different products, with the database-stored template for each product linked by ForeignKey.