'I have a package called foo.package. And I also have a content item called mydocument.py. As a standard structure, inside foo/package I have browser, content, profiles, etc. What I want to achieve is to create a customized add template for my content item which is mydocument.
I have read the article from this link http://docs.plone.org/external/plone.app.dexterity/docs/advanced/custom-add-and-edit-forms.html
What I have done is that I created a file inside browser directory and named it as mydocumentaddform.py. Also, inside my browser directory I have templates directory.
The code inside mydocumentaddform.py:
from five import grok
from plone.directives import dexterity, form
from Products.CMFCore.utils import getToolByName
grok.templatedir('templates')
class mydocumentaddform(dexterity.AddForm):
grok.name('foo.package.mydocument')
form.wrap(False)
Inside browser/templates directory I created the template mydocumentaddform.pt. However, my customized mydocumentaddform template was not rendered as I add the mydocument content, since inside the template I added js script to detect whether the customized add template override the default add template. As I view my instance, there is a UserWarning that there is an unassociated template configuration which points to my add template: ~... /foo/package/browser/templates/mydocumentaddform.pt
Is there anyone who have encountered the same problem? Or is there any other way to do this? Thanks.
*Yes I forgot to include the quotes here on grok.name.
Update:
I found a temporary solution, inside the class ViewPageTemplateFile. Here's the updated code:
from five import grok
from plone.directives import dexterity, form
from Products.CMFCore.utils import getToolByName
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
grok.templatedir('templates')
class mydocumentaddform(dexterity.AddForm):
grok.name('foo.package.mydocument')
template = ViewPageTemplateFile('templates/mydocumentaddform.pt')
form.wrap(False)
The customized add template was read, however, still my instance always says that the template that I used is still unassociated. As I also observed, when I replace the base class into dexterity.DisplayForm, the instance error is gone. With this temporary solution, I am not sure of any possible effect in the future due to this persistent error.
I see some issues in your code: you're missing the quotes on the name:
grok.name('foo.package.mydocument')
you need to define the context:
grok.context(IMyDocument)
did you declare an add-on layer? then you need:
grok.layer(IMyLayer)
you can find a working example in collective.nitf.
Related
I am trying to add a custom/overridden AdminSite because I need a different template for the Admin. I did everything as the Docs said:
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#overriding-the-default-admin-site
project/admin.py
from django.contrib.admin import AdminSite
class NewAdminSite(AdminSite):
index_template = 'admin/index.html'
site_header = 'Administration'
admin_site = NewAdminSite(name='newadmin')
project/apps.py
class NewAdminConfig(AdminConfig):
default_site = 'project.admin.NewAdminSite'
I don't have any other apps, project is my root directory
ofc I added admin_site.urls instead of admin.site.urls to urls.py, created a custom AdminConfig in apps.py, and added that new AdminConfig to installed Apps instead of django.contrib.admin.
The Problem is that I now receive this:
AdminSiteClass = import_string(apps.get_app_config('admin').default_site)
File "C:\Users\User.virtualenvs\ssccms-fGQRLLK4\lib\site-packages\django\utils\module_loading.py", line 24, in import_string
) from err
ImportError: Module "project.admin" does not define a "NewAdminSite" attribute/class
my folder structure:
manage.py
project
admin
settings
urls
apps
static
templates
migrations
workdir
sqlite
media
node_modules
locale
pipfile.lock
pipfile
wsgi
hope this is enough for folder structure, it is the django-shop cookiecutter project example structure
EDIT:
yes, it was definitely a circular import error. My workaround now is simply using the given admin.site by writing:
admin.site.index_template = 'admin/newadminindextemplate.html'
it works! Which is actually all that I wanted. But the Documentation says the following
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#root-and-login-templates
If you wish to change the index, login or logout templates, you are better off creating your own AdminSite instance.
I tried that:
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/#customizing-the-adminsite-class
instead of the overriding part I pasted in the first link in the question but now there is
django.urls.exceptions.NoReverseMatch: Reverse for 'cascade_texteditor_config' not found. 'cascade_texteditor_config' is not a valid view function or pattern name.
now my new question is:
is it necessary to create your own instance of the index template ? the Documentation says no explanation so are there any problems that I might run into at a later time by doing admin.site.index_template?
I've just hit a similar error. It's a bit confusing, in my case it was due to a circular import.
In my case the following helped:
convert imports from top of the file containing NewAdminSite class to local imports (inside of the function where they're needed
move the instantiation of admin_site variable to a separate file
Neither of those problems is actually visible in the code you've pasted, but may give you an idea what to look for.
I have a url like below:
url(r'^board/(?P<pk>\d+)$', board_crud, name='board_update'),
I want to get current view 'board' without parameters so that i can redirect to it.
I want to redirect to current view(without param) in same view(with param).
Thanks in Advance.
I believe you want to do something like this:
urls.py
url(r'^board/$', board_redirect, name='board_redirect'),
url(r'^board/(?P<pk>\d+)/$', board_crud, name='board_update'),
PS: Note the ending /, it's a good idea to always end the url
patterns with a forward slash, for consistency (except cases where you
are return a url like sitemap.xml for example).
Then, you would need to create a view like this:
views.py
from django.shortcuts import redirect
from .models import Foo
def board_redirect(request):
latest = Foo.objects.values('pk').order_by('-date').first()
return redirect('board_update', pk=latest['pk'])
The queryset would define the logic you want to implement. I don't have more info on your application. In this example you would always show the "latest" object based on a "date" field. Hope it makes sense.
I have an app called transactions. Within this app I have a model called BatchFile. In my views.py file, I subclass ListView (amongst others). The default behavior is that django thinks batchfile_list.html should be located at:
templates/transactions/batchfile_list.html
That's great, but the folder is getting crowded. I'm able to add "templates/transactions/batchfiles" to TEMPLATE_DIRS, but because the default behavior is to look for appname/modelname_type.html that requires that I put my templates in:
templates/transactions/batchfiles/transactions/batchfile_list.html
when I'd really like it to be in:
templates/transactions/batchfiles/batchfile_list.html
or my optimal result:
templates/transactions/batchfiles/list.html
Are there configuration options that would allow me to do this? I know the optimal result is probably not cleanly achieved, but I was hoping for at least the slightly less optimal result.
Thanks!
The easiest way is to specify template_name:
class MyListView(ListView):
template_name = "transactions/batchfiles/list.html"
An alternative is to override get_template_names:
class MyListView(ListView):
def get_template_names(self):
return ["transactions/batchfiles/list.html"]
Note that it needs to return a list of possible template locations.
In this case there would only be one which is the desired location.
I just ran into a problem..
I'm trying to build a website at the moment with different pages.
So I created a django app called pages, with the following fields:
title
text
URL
The idea is, that users can create new pages and delete existing ones and it actually affects the navigation in real time.
So in my urls.py I wanted to handle this somehow like this:
from django.conf.urls.defaults import *
urlpatterns = patterns('',
(r'^pages/(/w)', pages.views.display_content),
)
For example there could be a page with URL property "page1", then "page1" should be stored by (/w) and passed over to pages.views.display_content, which then would display the corresponding data. The "page1" page would be accessible through domain.com/pages/page1.
However, as I'm not really good with regex, I think I really need your help.
I would be really happy if someone could explain to me how I have to write my URL rule for this..
Good Night :)
In addition, you could name the parameter that will be captured and passed to your view function with this notation:
...
(r'^pages/(?P<page_name>\w+)', 'pages.views.display_content'),
...
So you can access it with that name in your view function.
Its header should look like this:
def display_content(request, page_name):
...
Given a class C in Python, how can I determine which file the class was defined in? I need something that can work from either the class C, or from an instance off C.
The reason I am doing this, is because I am generally a fan off putting files that belong together in the same folder. I want to create a class that uses a Django template to render itself as HTML. The base implementation should infer the filename for the template based on the filename that the class is defined in.
Say I put a class LocationArtifact in the file "base/artifacts.py", then I want the default behaviour to be that the template name is "base/LocationArtifact.html".
You can use the inspect module, like this:
import inspect
inspect.getfile(C.__class__)
try:
import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)
This is the wrong approach for Django and really forcing things.
The typical Django app pattern is:
/project
/appname
models.py
views.py
/templates
index.html
etc.