I'm successfully using a custom user model with django.
The last thing to get working is the "AdminChangePasswordForm" for superusers to change any users password.
currently the change password link from admin:myapp:user gives a 404
The answer.
Override get_urls
and override UserChangeForm to have the correct url.
So I had similar problem. When I tried to change user password from admin I got url to "/admin/accounts/siteuser/password/" (siteuser is the name of my custom user model) and 404 error with this message: "user object with primary key u'password' does not exist."
The investigation showed that the problem was due to bug in django-authtools (1.4.0) as I used NamedUserAdmin class to inherit from.
So the solution is either (if you need to inherit from any custom UserAdmin like NamedUserAdmin from django-authtools):
from django.contrib.auth.forms import UserChangeForm
from authtools.admin import NamedUserAdmin
class SiteUserAdmin(NamedUserAdmin):
...
form = UserChangeForm
...
or just inherit from default django UserAdmin:
from django.contrib.auth.admin import UserAdmin
class SiteUserAdmin(UserAdmin):
pass
It seems it's a "bug" in 1.7.x, and fixed in 1.8.x, which set the url name, so you do have to override get_urls():
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
from django.conf.urls import url
class UserAdmin(AuthUserAdmin):
def get_urls(self):
return [
url(r'^(.+)/password/$', self.admin_site.admin_view(self.user_change_password), name='auth_user_password_change'),
] + super(UserAdmin, self).get_urls()
URL:
password_change_url = urlresolvers.reverse('admin:auth_user_password_change', args=(1,))
Related
I'm using django and its built in admin site for the project I'm working on. (Python 3.4, django 1.7)
For the current project I'm working on I require usernames to be fixed after object creation. I have made a small test project, which literally contains one app, and that app only contains this admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
class MyAdmin(UserAdmin):
def get_readonly_fields(self,request, obj=None):
ro_fields = list(super().get_readonly_fields(request, obj))
if obj is not None:
ro_fields.append('username')
return ro_fields
admin.site.unregister(User)
admin.site.register(User, MyAdmin)
As expected, the Username can be set in the Add page and is Read Only in the change page. However, I cannot save when on the change page, I receive the message "please correct the errors below" but no field is highlighted. Can anyone suggest a way to work round this problem?
EDIT: as a diferent option I attempted to replace the username with a widget that didn't allow input - no luck there either
To add a single model from an app in to the /admin area I have done like so:
from django.contrib import admin
from wiki.models import Page, Category, CategoryItem
# register Pages for use in Django admin
class PageAdmin(admin.ModelAdmin):
pass
admin.site.register(Page, PageAdmin)
which works fine for a single model, but when I try to register the other two (Category and CategoryItem), it breaks down. What is the correct way of adding multiple models for a single Django app in the admin interface?
in django 1.5 we do following:
from django.contrib import admin
from wiki.models import Page, Category, CategoryItem
for cls in (Page, Category, CategoryItem):
admin.site.register(cls)
This is default way:
class PageAdmin(admin.ModelAdmin):
pass
class CategoryAdmin(admin.ModelAdmin):
pass
class CategoryItemAdmin(admin.ModelAdmin):
pass
admin.site.register(Page, PageAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(CategoryItem, CategoryItemAdmin)
If you've got some unhandled exception, add it to the question, so we can find out what's broken.
If you are not making changes in the models display in admin portal no need to create Admin Items, you can pretty much register it like :
from django.contrib import admin
from wiki.models import Page, Category, CategoryItem
admin.site.register(Page)
admin.site.register(Category)
admin.site.register(CategoryItem)
I'm trying to customize my Admin views with Flask and Flask-SuperAdmin, however, the index view and subviews are apparently not using the same is_accessible method:
EDIT: I managed to figure out what I was doing wrong. I needed to define is_accessible in every view class. This is well-accomplished with a mixin-class, as show in the fixed code:
app/frontend/admin.py (FIXED & WORKING CODE)
from flask.ext.security import current_user, login_required
from flask.ext.superadmin import expose, AdminIndexView
from flask.ext.superadmin.model.base import ModelAdmin
from ..core import db
# all admin views should subclass AuthMixin
class AuthMixin(object):
def is_accessible(self):
if current_user.is_authenticated() and current_user.has_role('Admin'):
return True
return False
# the view that gets used for the admin home page
class AdminIndex(AuthMixin, AdminIndexView):
# use a custom template for the admin home page
#expose('/')
def index(self):
return self.render('admin/index.jade')
# base view for all other admin pages
class AdminBase(AuthMixin, ModelAdmin): # AuthMixin must come before ModelAdmin!
"""A base class for customizing admin views using our DB connection."""
session = db.session
# customize the form displays for User and Role models
class UserAdmin(AdminBase):
list_display = ('email',)
search_fields = ('email',)
exclude = ['password',]
#fields_order = ['email', 'active', 'last_login_at',]
class RoleAdmin(AdminBase):
field_args = {'name': {'label': 'Role Name'},
'description': {'description': "Duties & Responsibilities"}}
list_display = ('name', 'description')
Then set up the Flask app with our admin views:
apps/factory.py
app = Flask(package_name, instance_relative_config=True)
# other app setup stuff like db, mail, ...
from .frontend.admin import AdminIndex, UserAdmin, RoleAdmin
admin = Admin(app, name='PyCBM Admin',
index_view=AdminIndex(url='/admin', name='Admin Home'))
admin.register(User, UserAdmin)
admin.register(Role, RoleAdmin)
So, like the title says, here's the problem:
/admin throws a 403 when an 'Admin' user isn't logged in, like it should, but
/admin/user lets anybody right on in.
I dug through the source code to try to find another "global all-of-admin-blueprint" security function - maybe I'm blind - but I couldn't find one.
If you go to flask_superadmin/base.py, at line 193 there is the following code snippet:
def _handle_view(self, name, *args, **kwargs):
if not self.is_accessible():
return abort(403)
So maybe this method has to be overriden by AdminIndex to avoid returning abort(403) but to redirect to /login
I have strange problem. In admin.py I can say:
admin.site.register(MyModel)
and this is obviously fine. Now I want this model to be loaded automatically as an result of user action:
def user_action_from_admin_panel(......):
.....
admin.site.register(MyModel)
MyModel class gets shows up in the admin as plain text without links.
Any ideas to solve this?
May be you need this
from django.core.urlresolvers import clear_url_caches
from django.utils.importlib import import_module
def user_action_from_admin_panel(......):
.....
admin.site.register(MyModel)
reload(import_module(settings.ROOT_URLCONF))
clear_url_caches()
models created dynamically will not show up in the admin unless their app_labels match up with packages listed in INSTALLED_APPS
This is again by design, and should not be considered a bug.
Make sure you are adding app_label while creating a model
model = create_model('DynamicModel', app_label='existing_app')
Also reload your url conf so that new model gets links
# after creating model
from django.utils.importlib import import_module
reload(import_module(settings.ROOT_URLCONF))
Source: https://code.djangoproject.com/wiki/DynamicModels#Admininterface
I have black links if I don't permissions to add/change.
Try re-define your admin class:
class MyModelAdmin(admin.ModelAdmin):
def has_add_permission(self, request):
return True
def has_change_permission(self, request):
return True
...
admin.site.register(MyModel, MyModelAdmin)
The reason possibly is because Django couldn't find any URL match with that model for admin section. Hence, that model line in admin area will be set at disabled and no additional add or edit links.
For some cases, your code for registering models are triggered after the building of admin URLs (django.contrib.admin.site.AdminSite.get_urls()).A workaround solution is to update the whole admin urlpatterns of the global URLs, or using a Django apps named django-quickadmin, it will automatically load all custom models into admin without making any additional code.
I have used custom field in django registration form , every thing is working fine but whenever it try to redirect , it shows following error.
I dont know what i missed here.
NoReverseMatch at /accounts/register/
Reverse for 'registration_complete' with arguments '()' and keyword arguments '{}' not found.
I tried following
URL
url(r'^accounts/register/$', register, {'backend': 'registration.backends.default.DefaultBackend','form_class': RegistrationFormEx}, name='registration_register'),
registrationForm.py
from django import forms
from registration.forms import RegistrationForm
from django.utils.translation import ugettext_lazy as _
from registration.models import RegistrationProfile
class RegistrationFormEx(RegistrationForm):
#ADD ALL CUSTOM FIELDS BELOW
name=forms.CharField()
models.py
import hashlib
import datetime
import hmac
from django.db import models
from django.contrib.auth.models import User
from ecpCommon.models import StateModel
from ecpCommon.enum import enumauto
from ecpPayments.models import PaymentCard
from registration.signals import user_registered
from apps.ecpUser.models import UserProfile
from apps.ecpMerchant.registrationForm import RegistrationFormEx
from apps.ecpCommon.thumbs import ImageWithThumbsField
class MerchantProfile(StateModel):
name = models.CharField('Merchant Name', max_length=64)
def user_created(sender, user, request, **kwargs):
form = RegistrationFormEx(data=request.POST)
new_user = User.objects.get(username=request.POST['username'])
digest=hmac.new(str(request.POST['username'])+str(request.POST['password1']), str(request.POST['password1']),hashlib.sha1).hexdigest()
new_profile = UserProfile(user=new_user,api_key=digest)
new_profile.save()
#now add other fields including password hash as well
uid = new_profile.id
merchant_profile = MerchantProfile(user_id=uid,
create_time=datetime.datetime.now(),
modified_time=datetime.datetime.now(),
payment_card_id=uid,
current_state=1,
name=request.POST['name'],
)
merchant_profile.save()
return new_user
user_registered.connect(user_created)
It's likely because of the registration success redirection in your views is redirecting to a URL: registration_complete, that does not exist.
To fix it, you should add a url record similar to the one you have for registration_register
url(r'^accounts/register/$', register, {'backend': 'registration.backends.default.DefaultBackend','form_class': RegistrationFormEx}, name='registration_register'),
that points to the correct url with name=registration_complete.