Read only usernames in django admin site - python

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

Related

Where to best execute database operations using Django framework?

Thanks in advance for any help. I am new to django specifically as well as web development in general. I have been trying to teach myself and develop a website using the Django framework and while everything is working so far, I am not sure if I am really doing things in the best possible way.
Typically, within my django app, I will have certain points where I want to modify the contents of my database model in some way. A typical use case is where I have button on my site that says "Add a post":
models.py:
from django.db import models
# data model import
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
post = models.CharField(max_length=1024)
urls.py:
from django.urls import include, path
from . import views
urlpatterns = [
path('', views.post, name='new_post'),
path('post_exec', views.post_exec, name='post_exec'),
]
views.py:
from django.contrib import messages
from django.shortcuts import render, redirect
# import data models
from django.contrib.auth.models import User
from .models import Post
def post(request):
# make sure the user has privileges
user = User.objects.get(id = request.user.id)
if not user.is_superuser:
return redirect('home')
return render(request, 'post.html')
def post_exec(request):
# make sure the user has priveledges
user = User.objects.get(id = request.user.id)
if not user.is_superuser:
return redirect('home')
# create the post
new_post = Post.objects.create()
new_post.user = user
new_post.post = request.POST['post']
new_post.save()
# this could redirect to a confirmation page or something too
return redirect('home')
You can see what I am doing here is that everytime I need a change to the database due to user input, I am executing the code to do the requested database change in a django view and then redirecting to another page following completion of the database change. While this works, it feels kind of clunky (you end up needing pages that you never actually use), it seems pretty sketchy in terms of security (although I am checking for credentials on each page), and I imagine there is a better way to do this.
Can any experience Django developers offer some advice for how I should be best structuring my project for these specific types of common database operations?
The Django's views is a good place to organize the project's CRUD system so users can manage their data. You can use the class-based views to group the GET, POST etc requests. Also there are better ways of using the authorization system with the login_required() decorator, the LoginRequiredMixin class and other solutions that you can rich here

Django Admin template override

I am following the tutorial on django website to create my first django app.
Now I am stuck trying to override Django Admin template.
My project directory is this:
First I tried creating a new admin template in the surveys app. It works.
Then, I tried with the override function. For this I created at surveys/admin.py the following code:
from django.contrib.admin import AdminSite
from django.utils.translation import ugettext_lazy
class SurveysAdminSite(AdminSite):
site_header = ugettext_lazy('Test administration')
surveys_admin_site = SurveysAdminSite()
And add to computationalMarketing/urls.py the following:
from .admin import surveys_admin_site
urlpatterns = [
path('admin/', surveys_admin_site.urls, name='admin'),
]
It doesn't work, so I search, and tried something different. Add this same previous code to surveys/urls.py. Neither works. Then I rollback the changes to save the code to computationalMarketing/urls.py, but this time I changed the code from surveys/admin.py to computationalMarketing/admin.py (in fact I created the file because it doesn't exists.
It works and now I see the site header that I want, but I get You don't have permission to edit anything. I have seen that is something related with superuser creation, but until now I was able to admin my surveys app without problem, so I believe in some solution related with override properly the admin.py at surveys app
Does anybody knows why this does not works as expected?
You are overriding the complete admin site. You may want to override only specific templates and keep using the default admin site.
A first approach to solve your problem is to add models to your admin site:
surveys/admin.py:
from django.contrib.admin import AdminSite
from django.utils.translation import ugettext_lazy
from surveys.models import OneModel, OtherModel
class SurveysAdminSite(AdminSite):
site_header = ugettext_lazy('Test administration')
surveys_admin_site = SurveysAdminSite()
surveys_admin_site.register(OneModel)
surveys_admin_site.register(OtherModel)
And maybe use ModelAdmin objects to add advanced behavior.
Hope this helps.

Created User from django custom admin page can't login

I have a custom admin page:
class StripeAdminSite(admin.AdminSite):
...
pass
I have registered django.contrib.auth.models to this admin site:
stripe_admin_site = StripeAdminSite(name='Stripe')
stripe_admin_site.register(User)
Now User show up in the admin page, it also let me create users (as stuff), but after creation when I try to log in using them to dashboard it does not allow me to do that.
After switching back to default admin site, I got this written in my old users password fields:
Invalid password format or unknown hashing algorithm.
Now what can be done?
More/Extra information: How to bring default add user page at django custom admin page?
The problem is that you did not register the User model with Django's UserAdmin. This means that the password was not hashed properly when the user was created, so they can't log in.
To use Django's UserAdmin, change your code as follows.
stripe_admin_site = StripeAdminSite(name='Stripe')
from django.contrib.auth.admin import UserAdmin
stripe_admin_site.register(User, UserAdmin)
Once you have done this, you will not get this problem for new users that you add in future.
Use the change password link to reset the password for any existing users, and then they should be able to log in.

Django: do not allow users to see pages when they are not logged in

I created a very basic login application. The LOGIN_URL, LOGIN_REDIRECT_URL and the LOGOUT_URL work just fine.
The thing is that if i log in succesully and then i close the window (browser) and then i reopen the browser, i can perfectly search the url (the one i am supose to only see if i am logged in) and use the applcation without loggin in again. This is not where it ends: if i open 2 separate browsers: Chrome and Firefox at the same time and i only logged in in ONE, i can use the applicaction from the other browser without problems.
I dont want this to happend. I tried using login_required in the urls.conf for the index view (the page that you can only see if you are logged in) and in the class view, i tried using stronhold, and django-braces. Is ther any other way to do this?. If you want to see any of the code let me know. Im using the login and log out that django implements (auth).
Than you
I know this is an old post but maybe the answer will help others in the future.
if you workflow is class based views you have to use: LoginRequiredMixin
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import generic
class CreateGroup(LoginRequiredMixin, generic.CreateView):
fields = ('name', 'description')
model = Group
The LoginRequired mixin
When using class-based views, you can archive the same behavior as with login_required by using the LoginRequiredMixin. This mixin should be at the leftmost position in the inheritance list.
https://docs.djangoproject.com/en/2.0/topics/auth/default/
It would seem like you need to wrap the 'private' views with Django's login_required decorator:
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
...
This will redirect to LOGIN_URL if the user is not logged in or authenticated.
in the view to the which your login redirects you can add:
def after_login(request,..):
if not request.user.is_authenticated():
redirect('some-non-existence-page-or-404',...)
#Your code
return

Django 1.5 custom user model plus admin.autodiscover() breaks app

I have a custom user model (it's actually named User as I didn't see any need to name it otherwise) in my Django 1.5c1 project (currently running on the latest from the Django 1.5 branch on github). AUTH_USER_MODEL is defined in my settings properly, so the auth module works correctly and I can log in etc. fine.
However, with the custom user module enabled, the admin site doesn't work. When I add admin.autodiscover() to my urls.py, every page on the site (not just admin pages) throws a NotRegistered exception and says The model User is not registered. The traceback shows that admin.autodiscover() is trying to call admin.site.unregister(User), apparently before it has registered that model.
I tried renaming my user model to something other than User, but it didn't seem to work. I also tried creating my own admin.py for that app, and then I tried manually registering my custom User model with the custom UserAdmin model specified in admin.py before admin.autodiscover() ran, but that actually caused a separate exception saying that User was already registered.
What should I try next in order to get admin.autodiscover() working?
It looks like you need to jump through a few extra hoops if you want your custom User model to work with the admin. From the documentation:
...your User model must define some additional attributes and methods.
These methods allow the admin to control access of the User to admin
content:
class models.CustomUser
is_staff True if the user is allowed to have access to the admin site.
is_active True if the user account is currently active.
has_perm(perm, obj=None) True if the user has the named
permission.
has_module_perms(app_label) True if the user has perm
to access models in the given app.
I set up a brand new empty project with a custom user model and attempted to recreate the situation, which led to a diagnosis: we had added the django-usertools package to the project, which has not been updated for Django 1.5 and apparently conflicts with custom user models. Removing that package from the installed apps list in settings resolved the issue.

Categories