Django admin: removing app name from URL for single-app projects - python

I am writing a simple Django app - say, called base - which has a few models. I am using Django's built-in admin site to manipulate the app's data. The admin is accessible via the default ^admin/ URL pattern.
Aside from Django's default INSTALLED_APPS (minus django.contrib.sites), base is the only app installed in my project. Is there any way to remove base/ from the URL, such that I can access base's models by simply using a path such as /admin/model/ instead of /admin/base/model/?
I would ideally like django.contrib.auth's models to still be accessible via /admin/auth/.

If you don't want base in the URL, don't put it there. It's not there unless you have specifically asked it to be. Just create your URLs without that prefix.
Edit Apologies, I misread your question: I thought you were asking about your app's own views, not the sub-sections with admin.
This is tricky. One way of doing it would be to use the hooks for adding URLs to the base AdminSite as described in the docs. You will probably need to copy the code from the ModelAdmin.get_urls method and hard-code the model name, since there won't be a way of doing that automatically.

Customizing or overriding your default Django admin site is quite easy. Here's the Django documentation on this. The following is an example of overriding the default admin site.
Create an admin.py in your Django project directory (if it's not there yet). Subclass the AdminSite.
To remove the 'appname' from the admin URLs override the get_urls() function:
# myproject/admin.py
from django.contrib import admin
class MyAdminSite(admin.AdminSite):
def get_urls(self):
urlpatterns = super().get_urls()
for model, model_admin in self._registry.items():
urlpatterns += [
path('%s/' % (model._meta.model_name), include(model_admin.urls)),
]
return urlpatterns
Creae an apps.py in your project directory (if it's not there yet):
# myproject/admin.py
from django.contrib.admin.apps import AdminConfig
class MyAdminConfig(AdminConfig):
default_site = 'myproject.admin.MyAdminSite'
Register this in your settings.py:
INSTALLED_APPS = [
...
'myproject.apps.MyAdminConfig', # replaces 'django.contrib.admin'
...
]

Related

Facing troubles on bringing the Django admin user tools like welcome, view site, log out on the custom template

I have to override the blocks like branding,site_title, and index title to a custom template. But the user tools are not displaying.
How I get.
How I want.
You can update the Site Header from your main urls.py. Just add in:
from django.contrib import admin
....
admin.site.site_header = "the title you want"
If you want to customise the admin site alot, you will likely want to subclass/override the default admin site. The documentation has most the info you need.
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#customizing-the-adminsite-class
If you’d like to set up your own admin site with custom behavior, you’re free to subclass AdminSite and override or add anything you like. Then, create an instance of your AdminSite subclass (the same way you’d instantiate any other Python class) and register your models and ModelAdmin subclasses with it instead of with the default site. Finally, update myproject/urls.py to reference your AdminSite subclass.
app/admin.py
from django.contrib.admin import AdminSite
from .models import MyModel
class MyAdminSite(AdminSite):
site_header = 'Monty Python administration'
admin_site = MyAdminSite(name='myadmin')
admin_site.register(MyModel)
project/urls.py
from django.urls import path
from myapp.admin import admin_site
urlpatterns = [
path('myadmin/', admin_site.urls),
]

How to include urls with app_name without having to use reverse with app name in Django?

I have a custom directory for allauth templates. I need some custom urlpatterns as well as I don't want some default views. I wanted to start with glueing in the entire allauth and change things that I need later on.
My main app config/urls.py file
from django.urls import include, path
urlpatterns = [
path("account/", include("users.urls")),
]
Users app:
users/urls.py
app_name = "users"
urlpatterns = [
path("login/", allauth_views.login, name="account_login"),
path("logout/", allauth_views.logout, name="account_logout"),
path("signup/", allauth_views.signup, name="account_signup"),
]
With this basic setup, if I go to /account/login it routes correctly to the desired view, but it is defined in users app with the app_name = "users", therefore, I have to access it in other views with reverse(users:account_login). The problem is that allauth LoginView has this method
def get_context_data(self, **kwargs):
ret = super(LoginView, self).get_context_data(**kwargs)
signup_url = passthrough_next_redirect_url(self.request,
reverse("account_signup"),
self.redirect_field_name)
redirect_field_value = get_request_param(self.request,
self.redirect_field_name)
site = get_current_site(self.request)
ret.update({"signup_url": signup_url,
"site": site,
"redirect_field_name": self.redirect_field_name,
"redirect_field_value": redirect_field_value})
return ret
which does the lookup on reverse("account_signup") but Django gets lost and throws django.urls.exceptions.NoReverseMatch.
Two solutions:
If I set those allauth urlpatterns in my main urls file it works correctly but I want to keep this file small and define allauth urls in my users app.
If I don't define app_name in my users/urls.py it works properly but I want it for other routes. I consider adding app_name to be a good practice. I could have created another app for allauth without an app name but then I'd have users stuff in two apps.
None of these satisfy me.
What I want:
Can I somehow include them without a namespace? I tried path("account/", include("users.urls", namespace=None)) without any luck.
I wasn't thinking... I can keep my custom users urls in users/urls.py with an app name and create another urls file like users/allauth_urls.py in users app and things work correctly.
Then, with
path("account/", include("users.allauth_urls")),
Things work as exepcted.

Refer to my (reusable) app's url namespace in Django

I want to write a reusable Django application.
I tell my users to add the following to their urls.py
path('slack/', include(('slack_integration.urls', 'slack_integration'), namespace='slack_integration'),
And in my urls.py I want to have a view login_callback.
Now in my view, I need to get a value of slack_integration:login_callback.
I can trust the user that he/she will integrate it with slack_integration prefix and use it. But is this the best practise? Can I somehow get the name of the namespace for the app if user chooses a different name for it?
Thanks a lot!
Using namespace= within urls.py files is no longer supported, as it moves something specific to the Django app outside of the Python package that is the Django app.
The best practice now is to define the app_name within the urls.py file inside the Django app.
The old way: DON'T DO THIS (pre-Django 2.0)
the root urls.py
path('slack/', include(('slack_integration.urls', 'slack_integration'), namespace='slack_integration'),
The new way: DO THIS! (Django 2.0+)
the root urls.py
from django.urls import path, include
urlpatterns = [
path('slack/', include(('slack_integration.urls', 'slack_integration')),
]
slack_integration/urls.py
from django.urls import path
app_name = "slack_integrations"
urlpatterns = [
path('', HomeView.as_view(), name='home'),
]
As you can see, this keeps the namespace for the patterns within the app itself, along with the templates most likely to use it. The days of extra instructions on how to include an app are over! Good luck.

Django 1.6 - templates for password change/reset

I want to use django's password change/reset views so for example for the view
django.contrib.auth.views.password_change
I need create a template named
registration/password_change_form.html
the problem is that even though I have this template implemented in my project, django still shows the password-change page of the admin website, the only way I can make django use my template is by renaming it to something different - like registration/password_change_form_1.html and then pass the name
url(r'^password/change/$',
auth_views.password_change,
{'template_name': 'registration/password_change_form_1.html',
'password_change_form': MyPasswordChangeForm},
name='password_change'),
Am I missing something here? why won't django use my template when I use the default name?
I think because your app is under django.contribute.admin in the INSTALLED_APP.
Django automatically generates the admin template with the default name, so, if you use the admin, you must specify a different template name.
It simply fails to find your template, since it is overiden by the generated one.
Add in settings
INSTALLED_APPS = (
...
'registration',
)
After
TEMPLATE_DIRS = (
...
"/home/user/templates",
)
Add in directory templates "registration"
base.html that will contain the template and other templates
run in django==1.5

Django admin.site.register doesn't add my app admin

as a django newbie (I have some exprience with other python webframework like turbogears and bottle but exploring django) I'm trying to auto create the admin management for my app model
in tha main URLS.py I have:
edit:
from django.contrib import admin
admin.autodiscover()
and after that:
urlpatterns = patterns('',
url(r'^appname/',include('appname.urls')),
url(r'^admin/',include(admin.site.urls))
notice this is in the main urls.py and not in the app urls.py
following the tutorial (which did work for me in the tutorial..) I created an 'admin.py' file in the appname folder and there:
from appname.models import Appname
from django.contrib import admin
class appnameAdmin(admin.ModelAdmin):
fieldsets = [various field sets and fields etc ]
admin.site.register(Appname,AppnameAdmin)
and in setting.py I have uncommented
'django.contrib.admin'
I don't get any error in the commandline window and the basic admin screen does appear (auth and sites)
I checked the imports in admin.py in the manage.py shell and everything seemed to work allright, I also tried commenting AppnameAdmin class out and registring just:
admin.site.register(Appname)
but that didn't work eith
I'm guessing I'm missing something obvious - I'll be glad to help with that
using django 1.4 + python 2.72
Check all of these:
There are seven steps in activating the Django admin site:
Add 'django.contrib.admin' to your INSTALLED_APPS setting.
The admin has four dependencies - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages and
django.contrib.sessions. If these applications are not in your
INSTALLED_APPS list, add them.
Add django.contrib.messages.context_processors.messages to TEMPLATE_CONTEXT_PROCESSORS and MessageMiddleware to
MIDDLEWARE_CLASSES. (These are both active by default, so you only
need to do this if you’ve manually tweaked the settings.)
Determine which of your application’s models should be editable in the admin interface.
For each of those models, optionally create a ModelAdmin class that encapsulates the customized admin functionality and options for
that particular model.
Instantiate an AdminSite and tell it about each of your models and ModelAdmin classes.
Hook the AdminSite instance into your URLconf.
Do you have all the other admin dependencies in your installed apps?
Do you have admin.autodiscover() in your URLS.py?
Also, I think your code should look something more like this:
from projectname.appname.models import Appname
from django.contrib import admin
class AppnameAdmin(admin.ModelAdmin):
fieldsets = [various field sets and fields etc ]
admin.site.register(Appname,AppnameAdmin)
Have you restarted the server process?
Maybe this helps someone: in my case the problem was solved by stopping and starting the server process, because when you add a new admin.py file it does not reload automatically.
aaargghhh - I found the problem. I saved admin.py in the template/appname/ folder instead of the appname/ folder. so stupid of me. so sorry for the interruption.
Set this in your model admin:
def has_add_permission(self, request, obj=None):
return True
def has_change_permission(self, request, obj=None):
return True
def has_delete_permission(self, request, obj=None):
return True
Check all these:
Restart the server and check again
Add 'models.Model' as a parameter in your class in models.py file
class Classname(models.Model):
Add your app in the 'INSTALLED_APPS' in settings.py, In my case it's 'travello.apps.TravelloConfig'
INSTALLED_APPS = [
'travello.apps.TravelloConfig',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
Add 'admin.autodiscover()' in main urls.py
from django.contrib import admin
from django.urls import path, include
admin.autodiscover()
urlpatterns = [
path('', include('travello.urls')),
path('admin/', admin.site.urls),
]
it worked for me!
Nothing above worked for me.
Then I went to Settings, and under Project:MyApp Project Interpreter
I switched the Project Interpreter from Python 3.8(venv) to Python 3.8(MyApp)
And then all my models where registered (could list them in http://localhost:8000/admin/)
Strangely enough, still in admin.py, after "admin.site." the method registered will not be listed as available. But it works anyway.
Go to models.py file and add 'models.Model' as a parameter in your class .
Example:
class className(models.Model)
In your case use below as class name and it will 100% work for you.
class AppnameAdmin(models.Model):
from django.contrib import admin
from .models import modelname
admin.site.register(modelname)
import models in this way
Please consider that some models can be seen only from a superuser.
Try to create one and log-in the admin with that user.
python3 manage.py createsuperuser

Categories