I'm using the Django User model for my users. What I need is to add an action on the User admin that will enable me to send a text message to the users I'll have selected.
This is how it's supposed to work:
I log into Django admin
Select the Users model
Select a user from the list of users and then select the "Send Message" action I have created.
I should be redirected to another page that will have the selected user names, and fields from a "Text Message" model that I have created to handle text messages.
So far I've had to create another model:
class UserProfile(models.Model):
user = models.OneToOneField(User) #extended the User model
phone_number = models.CharField(u'Number', max_length=20)
and then the form for the Text Messages:
class TextMessageForm(ModelForm):
class Meta:
model = TextMessage
fields = ('sender', 'to', 'message')
but I'm having trouble adding an action to the User model(raises an "model already registered error" which I solved by unregistering but then the passwords in the User model are viscible. That's why I created the UserProfile model)
So, can I be able to add an action to the User model without having to mess with how it'll display stuff on the admin?
Can I have the action redirect to the text form(or another template for that matter)?
Or is this a bad way to think of it... I'm using this API to send my texts. Any direction you can offer?
You could extend the UserAdmin admin page:
# admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
# Define a new User admin
class UserAdmin(UserAdmin):
"""My User Admin"""
# eg.
form = MyFancyForm
# or use my fancy template for the form
add_form_template = 'myadmin/user/add_form.html'
# or maybe add it to the change list
change_list_template = 'myadmin/user/change_list.html'
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
https://docs.djangoproject.com/en/1.7/topics/auth/customizing/#extending-the-existing-user-model
If you just want to add a button to go to another page to send a message, I'd modify the list template to add that button.
Related
I've added a plan field to my custom Account class, but cannot get it to show on the individual account page in the django admin. It shows correctly in table of all accounts in the list view (as denoted by list_display), but does not show on each individual account page.
Here's my Account model:
class Account(AbstractUser):
PLANS = (
("free", "free"),
("pro", "pro")
)
plan = models.CharField(max_length=10, choices=PLANS, default="free")
def __str__(self) -> str:
return self.first_name
And my admin file:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber
class SubscriberInline(admin.TabularInline):
model = Subscriber
extra = 0
class AccountAdmin(UserAdmin):
inlines = [SubscriberInline, ]
list_display = ("first_name", "plan", "email")
# fields = ("first_name", "plan", "email")
admin.site.register(Account, AccountAdmin)
Why does this happen?
Is the problem related to the custom Account class which inherits from the AbstractUser model? I thought to add fields to the AccountAdmin class, but that just returns the below error:
ERRORS:
<class 'accounts.admin.AccountAdmin'>: (admin.E005) Both 'fieldsets' and 'fields' are specified.
The plan field also doesn't show in the admin panel when trying to create a new account (mind you, neither do most of the other fields as it only asks for the username, password1 and password2 fields, and the option to add new subscribers to the table, but other fields like first_name etc can be edited in the admin after creation).
Thanks
UPDATE:
Adding user #bdbd's suggested changes seems to not make a difference to the admin area - am I adding this incorrectly? Here's my admin.py after adding #bdbd's changes:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from accounts.models import Account
from subscribers.models import Subscriber
from django.contrib.auth.forms import UserChangeForm
from django import forms
PLANS = (
("free", "free"),
("pro", "pro")
)
class MyAccountChangeForm(UserChangeForm):
plan = forms.ChoiceField(choices=PLANS)
class SubscriberInline(admin.TabularInline):
model = Subscriber
extra = 0
class AccountAdmin(UserAdmin):
form = MyAccountChangeForm
inlines = [SubscriberInline, ]
list_display = ("first_name", "plan", "email")
# #todo: bug! plan field not showing in django admin on individual account pages
admin.site.register(Account, AccountAdmin)
UPDATE 2:
Screenshots of admin area:
You should not extend from UserAdmin. Instead, you should create your own model admin class which extends from admin.ModelAdmin.
Then you should register your model separately.
class AccountAdmin(admin.ModelAdmin):
...
admin.site.register(Account, AccountAdmin)
As necessary, you can customize AccountAdmin to get the effect you want. You can peek at the UserAdmin source code to see how it is customized, if you want your admin view to behave similarly.
You need to override the default form that is being used by UserAdmin and add your field like so:
from django.contrib.auth.forms import UserChangeForm
from django import forms
class MyAccountChangeForm(UserChangeForm):
plan = forms.ChoiceField(choices=PLANS)
Then assign the form to your admin:
class AccountAdmin(UserAdmin):
form = MyAccountChangeForm
I customized my add user form in my django admin, using admin.tabularinline. So whenever the admin adds a user, information about Usermodel and UserProfile model is saved at the same time. However, the label tag of the UserProfile form says 'Staff Profiles'(with 's'). And it doesn't look good because there is only one profile for one user. Any ideas how to change the "Staff Profiles" into "Staff Profile"?
See the picture for reference:
As specified in docs, changing your verbose_name_plural in UserProfileInline
In admin declaration, add
class UserProfileInline(admin.YourInlineChoice):
verbose_name_plural="Staff Profile"
[Your params]
I have managed to add an additional field to the Registration form, "where did you hear about us?".
But I am not sure which files to edit in order to store the data from this field along with the users info.
i.e. When logging into the Admin section and go to "users" and view a users info I would like to see this field there.
Simplest way would be to store additional data in a UserProfile model about the user, e.g.
from django.contrib.auth.models import User
class UserProfile(models.Model):
# This field is required.
user = models.OneToOneField(User)
# Other fields here
where_heard_about_us = models.TextField()
You can then register the object as an inline object in your Django Admin
I am trying to create custom fields for users to enter on signup with django-allauth. I have referred to several posts about this, but I am not able to get my custom form to save to my database. I do get a combined form on my signup.html page with username, password1 and 2, email and my extra fields of city and school, but I am not able to save the extra fields to the database. I have run syncdb and can see my User Profile table in the admin area.
This advice is the closest I have come to the answer but I do not understand how to implement it: "You can't use UserProfileForm to the allauth.SIGNUP_FORM_CLASS. You need to extend it from SignUpForm and write a save method which will accept the newly created user as the only parameter," from this post:
Custom registration form for use with django-allauth
I have also attempted to integrate advice on this form these posts:
Django Allauth not saving custom form
How to customize user profile when using django-allauth
This is my code:
Models.py
from django.db import models
from django.contrib.auth.models import User
class UserProfile(models.Model):
# A required line - links a UserProfile to User.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
school = models.CharField(max_length=128)
city = models.CharField(max_length=128)
def __unicode__(self):
return self.user.username
Forms.py
from django import forms
from django.contrib.auth.models import User
from myapp.models import UserProfile
from django.forms.widgets import HiddenInput
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('city', 'school')
def signup(self, request, user):
user=User.objects.get(email=request.email)
city=request.POST.get('city','')
school=request.POST.get('school','')
userprofile_obj = UserProfile(user=user,city=city,school=school)
userprofile_obj.save()
Settings.py
ACCOUNT_SIGNUP_FORM_CLASS = 'myapp.forms.UserProfileForm'
My template is the basic Signup.html from the django-allauth templates and I do not have a view made for this, although I attempted to make one from the tangowithdjango user authentication section register view, and this gave similar behavior (not saving to the database).
Thanks,
Kelly
Not sure if this is still an active question/issue for the original poster: if so, and for anyone else who comes across this, a few things to correct to at least move in the right direction:
I don't see an __init__() method that calls the superclass? E.g.:
def __init__(self, *args, **kwargs):
super(SignupForm, self).__init__(*args, **kwargs)
use the user parameter to the signup method. It should be populated; don't reload it.
Ensure the two objects are linking correctly (I didn't use Django to build my profile table so YMMV but I set user.profile = Profile(...); then execute user.profile.save() at the end of my signup() method.
get the values to place into the profile from the form cleaned_data (e.g. self.cleaned_data['city'] not the POST.
Then start debugging: is your signup() method firing? What does it get? What happens when you execute the profile.save() method?
Good evening,
I am presently creating a site with Django and I extended the user with a user profile. I have a small problem though. Here is my situation:
I extended the user profile in order to add custom fields.
I added the model to the User Admin Model, so when I am adding a user, I can fill in directly the fields to create the profile.
Now, if I don't add ANYTHING in these new custom user fields, in the user add page, Django Admin won't throw me an error saying these fields are null (and they aren't suppose to be)
I want it to throw me an error in this User Add Admin page, so that the admins will HAVE to fill in a profile when adding a new user.
ALL the users will be added in the Admin Panel.
Is this possible? Thanks a lot!
in admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.contrib.auth.models import User
from accounts.models import UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
class UserAdmin(DjangoUserAdmin):
inlines = [ UserProfileInline,]
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
In model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
employee_number = models.PositiveIntegerField(unique=True)
def __unicode__(self):
return 'Number'
By default, empty inline is permitted and thus no further check would be taken for an empty form. You need to override it manually:
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if self.instance.pk is None:
self.empty_permitted = False # Here
class Meta:
model = UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
form = UserProfileForm