Django CustomUser created in Admin, User notification by email - python

Hobby developer, new with Python and Django.
Working on project which will include creating new users with a CustomUser(AbstractUser) Model via the Admin backend. On [Save] I want to auto-send email to the new user email [To:] and share the Username and Password provided when the new user was created by admin.
I'm using Python3.7 Django 2.2 on MacOS. Development being done in virtual env [Conda]. Email server setup in the development env as Backend File type. I have done 'extensive' search on forums [incl this one] ... tried the example code I could find. I have been able to send [then receive in Backend File] email on Form save but do not know how one would include the form variables in the email.
VIEWS.py
from django.shortcuts import render
from django.core.mail import send_mail
def notification_mail_send(request):
form = CustomUserCreationForm(request.POST)
if form.is_valid():
# SET UP MAIL CONTENT AND SEND MAIL
pass
FORMS.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm):
model = CustomUser
fields = ('username', 'owner_fullname', 'email')
class CustomUserChangeForm(UserChangeForm):
class Meta(UserChangeForm):
model = CustomUser
fields = ('username', 'owner_fullname', 'email')

You should be able to access to form data with form.cleaned_data[field_name], where field_name would e.g. be "username".
If you are using a Django template to build your email content, pass the form object as context and use e.g. {{ form.cleaned_data.username }}

When using the django admin you don’t need to write your custom views and forms.
If you want to change the behavior of the admin you often need to overide the ModelAdmin class.
In your case I'd suggest to override save_model()

Thank to my fellow developers for assistance. I did deep dive into Rupin's suggestion and applied successfully using 'signals' : http://docs.djangoproject.com/en/2.2/topics/signals. Solved by merely adding 'if created': in the post_save_receiver(sender, instance, created, **kwargs): function in models.py.

Related

Python Django - Customizing add user save method

I am pretty new to django framework . I am working on add user form in admin login .I need to send user details to third party API , On success from API call ,have to save in application database . Could you please guide me how to customize user save method to achieve this.
I suggest you override clean() method in UserCreationForm. This way, you can send user details to third party API and validate it.
class CustomUserCreationForm(UserCreationForm):
class Meta:
model=User
def clean(self):
# Send API
class UserAdmin(UserAdmin):
add_form = CustomUserCreationForm
admin.site.register(User, UserAdmin)
clean() method
custom user creation form

Extending user models in Django saves password publicly

The password for newly created users is shown publicly on the admin console models. Why is that and how I do it correctly?
Furthermore, I am not actually able to login with any of the new users created in the Accounts_app. I am able to login only with the python manage.py createsuperuser
I created at the early point in the project.
Here is the models.py
from django.contrib.auth.models import AbstractUser
class ProjectUser(AbstractUser):
def __str__(self):
return self.username
Here is the settings.py
PASSWORD_HASHERS = [
'django.contrib.auth.hashers.Argon2PasswordHasher',
'django.contrib.auth.hashers.BCryptSHA256PasswordHasher',
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.PBKDF2PasswordHasher',
'django.contrib.auth.hashers.PBKDF2SHA1PasswordHasher',
]
AUTH_USER_MODEL = 'accounts_app.ProjectUser'
Here is my admin view
To create the user, I click "Add User" in the app admin view.
Here is the apps.py file
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts_app'
Here is the admin.py file
from django.contrib import admin
from accounts_app.models import ProjectUser
# Register your models here.
admin.site.register(ProjectUser)
Although you set ProjectUser to be the AUTH_USER_MODEL, you registered it in the admin as a standard model, not the user one. You need to use the user admin, as shown in the docs, since this takes care of hashing the password:
from django.contrib.auth.admin import UserAdmin
admin.site.register(ProjectUser, UserAdmin)
You'll need to delete and recreate the users you generated via the admin before changing this.
Firstable, what do you want to do, extend or custom the User Model?
If you want to extend... It's enough with a foreign key. For this, the Django project recommends using OneToOneField(User)
In this case, see the link below.
https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#extending-the-existing-user-model
In the other hand, if you want to custom the User model, you must have to do this before doing the migrations. The initial setup must have your customization. You can create an app only for the User Model customization.
In this case, see the links below.
https://docs.djangoproject.com/en/2.1/topics/auth/customizing/#substituting-a-custom-user-model
https://wsvincent.com/django-tips-custom-user-model/
I hope this helped you

How to add an extra field to a Django ModelForm?

So I'm working on an admin page. I'm registering the form with admin.site.register. And I want to add an extra field to the form, which will let me populate a TextField with a file contents.
Therefore I need to add an extra FileInput to upload the file and populate the TextField with its contents. I am trying this:
class PersonForm(forms.ModelForm):
extra_field = forms.FileInput()
class Meta:
model = Person
fields = '__all__'
but the field is not showing. Any ideas?
Also I have no clue where to access the file contents and populate the TextField with that before saving the model.
Thanks in advance.
My problem was in this line:
extra_field = forms.FileInput()
I solved the problem changing the line to:
extra_field = forms.FileField()
Thanks to all willing to help.
Try to do it in the constructor.
class PersonForm(forms.ModelForm):
class Meta:
model = Person
fields = '__all__'
def __init__(self, *args, **kwargs):
super(PersonForm, self ).__init__(*args, **kwargs)
self.fields['extra_field'] = forms.FileInput()
And since you are using the django admin, you need to change the form in the admin too.
What you've done is ok according to the documentation, read note here - https://docs.djangoproject.com/en/2.0/topics/forms/modelforms/#overriding-the-default-fields
To register it in the admin you should add something like this to your admin.py:
from django.contrib import admin
from .forms import PersonForm
#admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
form = PersonForm
Example from here - https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#admin-custom-validation
EDIT: it is necessary to actually register custom ModelAdmin, there are two equivalent ways: using decorator, as in the example above, or use admin.site.register(Person, PersonAdmin).
Documentation for ModelAdmin registration - https://docs.djangoproject.com/en/2.0/ref/contrib/admin/#the-register-decorator
Registration source code - https://github.com/django/django/blob/master/django/contrib/admin/sites.py#L85
Register the model in admin as
admin.site.register(UserProfile)
where UserProfile is a OnetoOnemodel that extends django's builtin User Model then after every changes in models run
python manage.py makemigrations
python manage.py migrate

not saving custom fields to django-allauth - no luck from previous posts

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?

Override a form in Django admin

In Django admin I want to override and implement my own form for a model (e.g. Invoice model).
I want the invoice form to have auto-fill fields for customer name, product name and I also want to do custom validation (such as credit limit for a customer). How can I override the default form provided by Django admin and implement my own?
I am new to Django, I appreciate any pointers.
You can override forms for django's built-in admin by setting form attribute of ModelAdmin to your own form class. See:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.form
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin
It's also possible to override form template - have a look at https://docs.djangoproject.com/en/dev/ref/contrib/admin/#custom-template-options
If you're looking specifically for autocomplete I can recommend https://github.com/crucialfelix/django-ajax-selects
How to override a form in the django admin according to the docs:
from django import forms
from django.contrib import admin
from myapp.models import Person
class PersonForm(forms.ModelForm):
class Meta:
model = Person
exclude = ['name']
class PersonAdmin(admin.ModelAdmin):
exclude = ['age']
form = PersonForm

Categories