creating custom item in ADMIN_MENU_ORDER - python

I'm having trouble understanding how to use the custom functionality of ADMIN_MENU_ORDER?
I want to do something like so -
ADMIN_MENU_ORDER = (
("Content", ("pages.Page", "blog.BlogPost",
"generic.ThreadedComment", ("Media Library", "fb_browse"),)),
("Site", ("sites.Site", "redirects.Redirect", "conf.Setting")),
("Users", ("auth.User", "auth.Group",)),
("MYAPP", ("View1", "app_view1")),
)
From what I gather I need to use redirects from URLs but where and how am I doing this? What I'm assuming is I'm doing this in MYAPP?
urls.py:
urlpatterns = patterns('',
url(r'^view1/$', 'View1', name='app_view1'),
)
And then generate that in my views.py?
class View1():
queryset = model.objects.all().values('fielda', 'fieldb', 'fieldc')
def get(self):
return queryset
My custom menu items still don't show up. I'm guessing I need to parse them into a template or return the results in a format that can be consumed by the mezzanine code? In which case what does that format need to be?

You've pasted an example right there in your question:
("Media Library", "fb_browse")
From the docs: http://mezzanine.jupo.org/docs/admin-customization.html#custom-items
It is possible to inject custom navigation items into the
ADMIN_MENU_ORDER setting by specifying an item using a two item
sequence, the first item containing the title and second containing
the named urlpattern that resolves to the url to be used.
There's no need for redirects. You just need to use the urlpattern names. Your urlpatterns weren't named, they'd look like:
urlpatterns = patterns('',
url(r'^view1/$', 'view1', name='my_view1'),
url(r'^view2/$', 'view2', name='my_view2'),
)
Then:
ADMIN_MENU_ORDER = (
...
("MYAPP", (("First", "my_view1"), ("Second", "my_view2"))),
)

Related

Is it required to add custom views in admin page in ModelAdmin class when we can do it normally by adding views in views.py and urls in urls.py?

According to django docs:
class MyModelAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super(MyModelAdmin, self).get_urls()
my_urls = [
url(r'^my_view/$', self.my_view),
]
return my_urls + urls
def my_view(self, request):
# ...
context = dict(
# Include common variables for rendering the admin template.
self.admin_site.each_context(request),
# Anything else you want in the context...
key=value,
)
return TemplateResponse(request, "sometemplate.html", context)
If I am not wrong, we can do the same thing by adding url in urls.py and the views in views.py as it is normally done then, what is the use of introducing this way? I am a newbie to django and I may be missing something here.
Can you please provide an example where we cannot do it in views.py and we must use the above method?
Any guidance/help would be appreciated.
I think I figured out, both of them can be used to do the same thing but the key difference is that the views which you write using above method will belong to admin app while the general views in views.py belongs to the particular app in you have written.
Hence, the url in ModelAdmin need to be called using name admin:url_name since the url goes as admin/my_views/ in given example.

How do you give a wagtail/django Page a custom url to serve at?

In wagtail/django how do you make a basic wagtail Page model, create the html template, and then tell that model to serve as a view for a specific url?
from django.db import models
from wagtail.wagtailcore.models import Page
class MyPage(Page):
title = models.CharField(blank=True, null=True, max_length=255)
#...
I want the url to register like
url(r'^monkey/(?P<slug>[A-Za-z0-9]+)$', ...)
But I don't have a common urls.py folder its stored outside of the project. I tried using the RoutablePageMixin, but I believe that serves for subpages. I also know where to store the html template within the structure so that is not a problem.
You might want something like:
from django.http import Http404
from django.views import View
from wagtail.core.views import serve
class WagtailPageServeView(View):
"""
A default way to serve up wagtail pages in urls
"""
wagtail_slug = None
def get(self, request, *args, **kwargs):
if self.wagtail_slug:
return serve(request, self.wagtail_slug)
else:
raise Http404(
f"WagtailPageServeView missing 'wagtail_slug'. Cannot serve "
f"request.path: {request.path}"
)
Then you can do something like this in urls.py:
urlpatterns += [
re_path(r'^$', WagtailPageServeView.as_view(wagtail_slug='/'), name='home'),
]
In Wagtail, you are creating a page type and then creating instances of the page type in the CMS.
Even if you are only going to use this page once, you still need to make a type. Following this logic, page urls are defined inside the CMS through the page's parent and slug. Most likely, you could achieve what you want through these means.
If you want to override your page template and create a custom url, you can override the get_url_parts method on your model.
Also, if you want to skip Wagtail for this page specifically, remember that Wagtail is just built over Django. You can always create a new module and define the url in that model. If you check your site urls.py, you will see the wagtail url patterns. You can change it to look something like this:
urlpatterns = [
# other urls...
url(r'wagtail/', include(wagtail_urls)),
url(r'^monkey/', ('monkey_app.urls', 'monkey_app')),
]

Django Regular expression many slugs

I have the regular expression in my url that accepts pass one slug to my view, exemple:
127.0.0.1/cart/product_slug1
But I need a regex that accept pass one or more slugs, example:
127.0.0.1/cart/product_slug1/product_slug2/product_slug3/.../product_slugN
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(
r'^cart/add/(?P<slug>[\w_-]+)/$', views.create_cartitem,
name='create_cartitem'
),
It's possible send many slugs?
[UPDATE]: It seems that you cannot do that. Instead, you can place a catch all pattern and capture the whole url. Then inside your views you can split it by / and get the parameters you want. Something like this:
urlpatterns = [
url(
r'^cart/add/(?P<slugs>[\w_/-]+)/$', views.create_cartitem, name='create_cartitem'
),
And then in your views, do this:
def my_view(request, slugs):
slugs = slugs.split('/')
# now slugs is a list of strings
Note, however, that this is error prone since both cart/add/h/e/l/l/o and cart/add/hell//o//to/you are valid.
-- OLD ANSWER --
Sure you can, but you cannot use both named captured parameters with unnamed ones.
So, change your urls.py to this:
urlpatterns = [
url(
r'^cart/add/([\w_-]+)/([\w_-]+/)*$', views.create_cartitem, name='create_cartitem'
),
And inside your views.py, instead of kwargs (like slug you already have) you must use args (positional arguments, now you're gonna have a list of slugs). Like this:
def my_view(request, *args):
for arg in args:
print(arg)
Now if you type 127.0.0.1:8000/cart/add/argv/argvv/argvvv/, inside your views you get them as a list ['argv', 'argvv', 'argvvv'].

urlpatterns don't get updated after DB insertion?

I'm having an html form which inserts data into one table called srv.
I've built the urls.py in such a way to capture every insertion:
for item in srv.objects.all():
linkSrv = item.loc.lower() + '/srv/' + item.subctg.lower() + '/' + item.title.lower()
urlpatterns += patterns('',
url(r'^' + linkSrv + '/$', 'beta.views.queryFromIndexDeep'),
)
After the one insertion is being made, e.g. loc='loc', subctg='subctg' and title='title'
if i point my browser to 127.0.0.1:8000/loc/srv/subctg/title/ i get the http404 error (no matching url)
If I 'force-save' the urls.py (vim urls.py then :x! ) - after loc,subct,title were inserted - then I can successfully access 127.0.0.1:8000/loc/srv/subctg/title/
Anyone can shed some light? It looks like the urlpatterns need to be 'updated' each time a row is insterted in srv table.
You should just use something like this:
urlpatterns += patterns('',
url(r'^(?P<loc>\w+)/(?P<subctg>\w+)/(?P<title>\w+)/$',
'beta.views.queryFromIndexDeep'),
)
Using regular expressions to match your view is way easier, and recommended. In your view, the above would match a function defined like beta.views.queryFromIndexDeep(request, loc, subctg, title), from where you can continue to work with these variables to extract the relevant data from your defined models.
add a slugfield (unique) to your srv model and add a method to the model
def get_absolute_url(self):
return /yourapp/%s/ % self.slug
Then in urls use a pattern to match this
url(r'^srv/(?P<slug>[-\w]+)/$', yourgenericview),
Look into the django slugify snippit for fun http://djangosnippets.org/snippets/690/

How to do reverse URL search in Django namespaced reusable application

Consider that I include namespaced reusable application:
urlpatterns = patterns('',
# ella urls
url('^ella/', include('ella.core.urls', namespace="ella")),
)
Now, the Ella applications has urls like that:
urlpatterns = patterns( '',
url( r'^(?P<category>[a-z0-9-/]+)/$', category_detail, name="category_detail" ),
# object detail
url( r'^(?P<category>[a-z0-9-/]+)/(?P<year>\d{4})/(?P<month>\d{1,2})/(?P<day>\d{1,2})/(?P<content_type>[a-z0-9-]+)/(?P<slug>[a-z0-9-]+)/$',
object_detail, name="object_detail" )
)
Now, calling {% url ella:category_detail category="cat" %} works fine. However, when object tries to generate link to it's details, it calls
from django.core.urlresolvers import reverse
url = reverse('object_detail', kwargs={'required' : 'params'})
This is not working, unless rewritten as
from django.core.urlresolvers import reverse
url = reverse('ella:object_detail', kwargs={'required' : 'params'})
So, if I understand it correctly, including reusable application into namespace breaks all inner reverse()s inside given application.
Is it true? What have I missed? Is there any way around?
Since you have name-spaced url configuration, you need to mention namespace:view-name pattern in order to reverse it properly (especially from view).
But, if you want to avoid this, you may also pass namespace/appname as current_app parameter.
There are multiple ways to specify current_app when you are in template. But if you are in view, you need to hard-code as you did, or pass to current_app parameter
url = reverse('object_detail',
kwargs={'foo':'bar'},
current_app=app_name_or_name_space)
refer: http://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
URL Namespaces can be specified in two ways.
Firstly, you can provide the application and instance namespace as arguments to include() when you construct your URL patterns. For example,:
(r'^help/', include('apps.help.urls', namespace='foo', app_name='bar')),
This is right from http://docs.djangoproject.com/en/dev/topics/http/urls/#defining-url-namespaces.
Try changing include('ella.core.urls', namespace="ella") to include('ella.core.urls', namespace="ella", app_name="ella"). I'm not 100% this will work, but its worth a shot.
At least in Django 1.8 you can write something like this:
url = reverse('%s:object_detail' % request.resolver_match.namespace, kwargs={'required' : 'params'})
request.resolver_match.namespace is a string containing the namespace of the currently running view.

Categories

Resources