Custom Add and Edit Template Dextertiy - python

'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

Django ImportError: Module does not define attribute/class

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.

Get Current Url Without Parameters in Django

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.

Can I change the template search behavior of class based views?

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.

Django - using regex in urls.py to pass values

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):
...

How do I get the filepath for a class in Python?

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.

Categories

Resources