Django: Using 2 different AdminSite instances with different models registered - django

Apart from the usual admin, I want to create a limited admin for non-staff users. This admin site will have different registered ModelAdmins.
I created a folder /useradmin/ in my project directory and similar to contrib/admin/_init_.py I added an autodiscover() which will register models defined in useradmin.py modules instead of admin.py:
# useradmin/__init__.py
def autodiscover():
# Same as admin.autodiscover() but registers useradmin.py modules
...
for app in settings.INSTALLED_APPS:
mod = import_module(app)
try:
before_import_registry = copy.copy(site._registry)
import_module('%s.useradmin' % app)
except:
site._registry = before_import_registry
if module_has_submodule(mod, 'useradmin'):
raise
I also cretated sites.py under useradmin/ to override AdminSite similar to contrib/admin/sites:
# useradmin/sites.py
class UserAdminSite(AdminSite):
def has_permission(self, request):
# Don't care if the user is staff
return request.user.is_active
def login(self, request):
# Do the login stuff but don't care if the user is staff
if request.user.is_authenticated():
...
else:
...
site = UserAdminSite(name='useradmin')
In the project's URLs:
# urls.py
from django.contrib import admin
import useradmin
admin.autodiscover()
useradmin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^useradmin/', include(useradmin.site.urls)),
)
And I try to register different models in admin.py and useradmin.py modules under app directories:
# products/useradmin.py
import useradmin
class ProductAdmin(useradmin.ModelAdmin):
pass
useradmin.site.register(Product, ProductAdmin)
But when registering models in useradmin.py like useradmin.site.register(Product, ProductAdmin), I get 'module' object has no attribute 'ModelAdmin' exception. Though when I try this via shell;
import useradmin
from useradmin import ModelAdmin
does not raise any exception.
Any ideas what might be wrong?
Edit:
I tried going the #Luke way and arranged the code as follows as minimal as possible:
(file paths are relative to the project root)
# admin.py
from django.contrib.admin import autodiscover
from django.contrib.admin.sites import AdminSite
user_site = AdminSite(name='useradmin')
# urls.py (does not even have url patterns; just calls autodiscover())
import admin
admin.autodiscover()
# products/admin.py
import admin
from products.models import Product
admin.user_site.register(Product)
As a result I get an AttributeError: 'module' object has no attribute 'user_site' when admin.user_site.register(Product) in products/admin.py is called.
Any ideas?
Solution:
I don't know if there are better ways but, renaming the admin.py in the project root to useradmin.py and updating the imports accordingly resolved the last case, which was a naming and import conflict.

Does useradmin have a ModelAdmin class defined, or do you import it from contrib.admin? I don't see anywhere in the code you supplied where that class gets set up.
That being said, there's a much easier way to do this: just initialize two AdminSites, and then wire them up to the URLs that you want (You can even put them in the same urlconf).

Related

I try to be able to load an image in the django admin, but I can't see it when I click

I don't know how to solve it. It's really frustrating. If you managed to help, I would be very grateful.
settings:
STATIC_URL = '/static/'
MEDIA_URL='Proyectoweb/media/'
MEDIA_ROOT=BASE_DIR / 'Proyecto/media'
url:
from django.urls import path
from ProyectoApp import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
models:
from django.db import models
# Create your models here.
class Servicio(models.Model):
titulo=models.CharField(max_length=50)
contenido=models.CharField(max_length=50)
imagen=models.ImageField(upload_to='servicios')
created=models.DateTimeField(auto_now_add=True)
updated=models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name='servicio'
verbose_name_plural='servicios'
def __str__(self):
return self.titulo
admin:
from django.contrib import admin
from .models import Servicio
# Register your models here.
class ServicioAdmin(admin.ModelAdmin):
readonly_fields=('created', 'updated')
admin.site.register(Servicio, ServicioAdmin)
For some reason, this page asks me for more details, when I think I have already given enough.
I try to be able to load an image in the django admin, but I can't see it when I click....

Mezzanine ignores the view, displays the template but does not pass the context

I created a view for my model, with the corresponding urls and template files. Then, in the admin panel, I have created a Rich text page, specifying the same URL (ingredients) defined in urlpatterns. Mezzanine ignores the view, displays the template but does not pass the context.
How can I solve it?
These are the codes:
models.py
from django.db import models
from mezzanine.pages.models import Page
from django.utils.translation import ugettext_lazy as _
class Ingredient(Page):
name = models.CharField(max_length=60)
information = models.TextField(null=True, blank=True, verbose_name=_("Description"))
views.py
from django.template.response import TemplateResponse
from .models import Ingredient
def ingredients(request):
ingredients = Ingredient.objects.all().order_by('name')
templates = ["pages/ingredients.html"]
return TemplateResponse(request, templates, {'ingredients':ingredients})
urls.py
from django.conf.urls import url
from .views import ingredients
urlpatterns = [
url("^$", ingredients, name="ingredients"),
]
TemplateResponse does not expect the request in its arguments. See the docs.
return TemplateResponse(templates, {'ingredients':ingredients})
However I expect you meant to use the standard render function there:
return render(request, "pages/ingredients.html", {'ingredients':ingredients})
Ok, the solution has been define my app urls before any other definition in my project urls.py file.
project_name/project_name/urls.py
# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.
urlpatterns = [
url(r'^ingredients/', include("apps.ingredients.urls")),
]
urlpatterns += i18n_patterns(
# Change the admin prefix here to use an alternate URL for the
# admin interface, which would be marginally more secure.
url("^admin/", include(admin.site.urls)),
)

Where to store my index.html and index view for a non-static Django homepage

I'm creating a Django project and currently have 3 apps (products, questions and choices) - I've got them all functioning separately/together as I'd like and am using namespaces and include as part of my urls (my urls.py given below...)
### urls.py
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.views.generic import TemplateView
admin.autodiscover()
urlpatterns = patterns('',
url(r'^products/', include('products.urls', namespace='products')),
url(r'^questions/', include('questions.urls', namespace='questions')),
url(r'^choices/', include('choices.urls', namespace='choices')),
url(r'^admin/', include(admin.site.urls)),
)
Now I'm looking to add an index page (accessible at localhost:8000/) that will allow me to access all models created. I'm happy with my views.py...
## views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from django.views import generic
from products.models import Product
from questions.models import Question
from choices.models import Choice
class IndexView(generic.ListView):
template_name = 'index.html'
context_object_name = 'latest_product_list'
def get_queryset(self):
return Product.objects.all()
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['questions'] = Question.objects.all()
context['choices'] = Choice.objects.all()
return context
What I'd like to know is, what is the most sensible combination of urls.py entry, positioning of views.py and location of index.html to allow me to show a combination of my models on the landing page?
Thanks,
Matt
Create another app (I tend to name it home). That way, your home app can import models from products, questions and choices.
App layout
home/urls.py
home/views.py
home/templates/index.html
Include your home urls just like your other apps (but don't use a prefix)
url(r'^', include('home.urls', namespace='home')),

Models not showing in Admin Interface

I can not get my models to display within the Admin Interface even after registering them in django-admin.py using admin.site.register(topic).
I have registered a model class topic, but it just isn't showing up in the interface. Instead, I'm getting groups and users in the auth section and sites in the sites section.
Below is the code I currently have. Any help would be appreciated.
models.py
class topic(models.Model):
topic_name = models.CharField(max_length=30)
description=models.CharField(max_length=255,null=True, blank = True)
class Admin:
pass
def str__(self):
return '%s''--' %(self.topic_name)
admin.py
from django.contrib import admin
from edc.kds.models import *
if __name == "main":
management.execute_from_command_line()
admin.site.register(topic)
You're doing some strange stuff.
1: You have some ancient, years old class Admin syntax which isn't necessary.
2: You have a strange if __name block in there. Clearly that should raise a NameError, but assuming you actually wrote __name__ == 'main', there's your problem.
__name__ is set to 'main' only if the file is directly executed. If it's executed by django machinery, the if block will never fire, and thus admin.site.register will never be called.
Where'd you get this idea?
# urls.py
from django.conf.urls import patterns, url, include
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
)

Issues with 2 different admin sites in a Django

I want to have 2 separate admin sites inside a Django project.
First is default admin
And Second is "coursemanager"
Following code i have added with the help of AdminSite
File Path "cms/courses/admin.py"
from courses.models import *
from django.contrib import admin
from django.contrib.admin.sites import AdminSite
from django.contrib.auth.models import User, Group
from django.contrib.auth.admin import UserAdmin, GroupAdmin
class CourseManager(AdminSite):
name = 'CourseManager'
course_manager = CourseManager()
class CityAdmin(admin.ModelAdmin):
list_display = ['__unicode__', 'status',]
list_filter = ['status',]
search_fields = ['title',]
course_manager.register(City, CityAdmin)
"cms/cms/urls.py"
from courses.admin import course_manager
urlpatterns = patterns('',
url(r'^admin/', include(admin.site.urls)),
url(r'coursemanager/', include(course_manager.urls)),
)
But when i add this http://domain.local/coursemanager/ & http://domain.local/admin/ both panel is working but in http://domain.local/coursemanger/ list register city module but not showing the add or changes links. Event i tried to access links from url but not working. I am checking this as superuser and i have all modules access. But when i change code like bellow
"cms/cms/urls.py"
from courses.admin import course_manager
urlpatterns = patterns('',
url(r'coursemanager/', include(course_manager.urls)),
url(r'^admin/', include(admin.site.urls)),
)
Then http://domain.local/coursemanager/ working properly and http://domain.local/admin panel is only listing all register admin but not showing the add/change links.
The app_name of AdminSite() is initialized through AdminSite.__init__(). You cannot override it by providing class-level variable, thus you were experiencing instance namespace collision and then some reverse failure, here, which caused add/change links not showing. Try
class CourseManager(AdminSite):
'...'
course_manager = CourseManager(name='CourseManager')
# or
course_manager = AdminSite(name='CourseManager')