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

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?

Related

How to add check on admin side actions in django?

Here i'm using django latest verion which is 3.1.4 and I just want to add condition in django admin side. I just wanted to return some text in terminal if i update my model from admin panel.
In my case
user submit kyc form
admin person approved that form
user will get notification on approval. (Right now I just want to print some message when admin update his kyc by updating his kyc form by updated approved boolean field.
In short Just wanted to show message when admin updates any model in django admin side.
admin.py
class KycAdmin(admin.ModelAdmin):
list_display = ['__str__','owner']
class Meta:
model = KycModel
def post(self,request):
response = "i'm updated"
print(vu)
return vu
admin.site.register(KycModel,KycAdmin)
If more detail is require then you can just tell me in a comments.
Have you tried overriding the save method in models.
Whenever you save an object, it will hit the save method. You can print whatever you want to over there
class SomeModel(models.Model):
... some fields for eg. name
def save(self, *args, **kwargs):
print(self.name)
super().save(*args, **kwargs)
This is the simplest way to achieve it. You can also override save in admin.

Django CustomUser created in Admin, User notification by email

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.

Storing new field to Django Admin "user" section from registration form

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

Django NOT NULL constraint failed userprofile.user_id in case of uploading a file

I am trying to practice a simple project: A user registers (using Django registration-redux), uploads some file, and then s/he is provided with a list of her files, being downloadable. Here are my models.py, forms.py, and views respectively:
models.py
class UserProfile(models.Model):
user = models.ForeignKey(User, related_name='uploaded_by')
names = models.CharField(max_length=40)
lastname = models.CharField(max_length=50)
email = models.EmailField()
uploads = models.FileField(upload_to= 'blablabla')
def __str__(self):
return self.email
forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['names', 'uploads']
view.py
from .forms import UserProfileForm
from .models import UserProfile
#login_required()
def new(request):
form = UserProfileForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
context = {'title': 'welcome', 'form': form}
return render(requst, 'upform.html', context)
however when I login with a user and try to upload a file I get the error: IntegrityError at /new
NOT NULL constraint failed: _userprofile.user_id
After digging a lot I noticed someone suggested the reason of the error is because the user is not included anyhow in the process of posting the form, so I tried whatever came to my mind and the case in which I added the user field to the forms.py worked:
forms.py
class UserProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['names', 'uploads']
the problem however is that the form shown in the browser now includes a drop-down list containing all the registered users. I tried to associate the logged-in user with the form in the views by I kept seeing different errors.
My question is: How can I associate the uploads with the logged-in user in a transparent manner.
sorry if the question is too newbie-liked
Keep the user out of the form and add it on save:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
I must say your model looks a bit odd; you have multiple profiles for each user, each with a single upload. Seems more likely you want a single profile, with a OneToOne relationship to User, than a separate Uploads model with a ForeignKey to UserProfile.
I added the user field to the forms.py worked:
This probably also opens up a security hole, because you could then set the user from outside of your application, overriding the logged-in user.
After digging a lot I noticed someone suggested the reason for the error is because the user is not included anyhow in the process of posting the form.
You figured that quite right. If the user is not a field, the form never knows how to fill the user field of UserProfile. Since you cannot save a UserProfile without a filled in user foreign key, you get the error.
There are various ways around this:
One way to solve the problem is to use save(commit=False) on the form, patch the user into the unsaved instance and manually saving the object to the database:
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.save()
This slightly violates the encapsulation because you now handle the database save outside of the form.
You are also able to provide a initial "template" instance to the form:
form = UserProfileForm(
request.POST,
request.FILES,
instance=UserProfile(user=self.request.user)
)
You probably want to do so, anyway because the form also allows to edit an existing userprofile. Currently you are saving a new UserProfile each time and since user is not unique=True in your model class, you will get multiple profiles per user.
If you do not want this to be possible, check Daniel Roseman's answer, because then you probably want UserProfile.user to be a OneToOne field.
In this case, we can simplify to
profile, created = UserProfile.objects.get_or_create(user=request.user)
form = UserProfileForm(
request.POST,
request.FILES,
instance=profile
)
Note also that I removed the or None as it is not necessary. BaseForm (which ModelForm derives from) does this check for you (it actually does self.data = data or {}) which essentially undoes the prior none-ification)
You can do following the advice of Daniel.
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='uploaded_by')
names = models.CharField(max_length=40)
lastname = models.CharField(max_length=50)
email = models.EmailField()
class UserFiles(models.Model):
user = models.ForeignKey(UserProfile)
file = models.FileField(upload_to= 'blablabla')
Remember OneToOneField is similar a ForeignKey with the attribute unique=True.

Django - can I get the current user when I'm not in a view function

I have Company and CompanyUser models. CompanyUser has 1:1 relationship with the django's auth User model. Every user is part of some company, so I have a ForeignKey field (Company) in the CompanyUser model:
class CompanyUser(models.Model):
Company = models.ForeignKey(Company)
User = models.OneToOneField(User)
Now I want to create some html tables to view and filter the data about Sales, Products, etc. I'm using django-tables2 and that works great.
Now let's say I want to see the Sales of a particular Product. So I need a dropdown that contains all Products of the Company that the user belongs to.
I've have created the forms.py file in my app:
from django import forms
class SaleFilterForm(forms.Form):
product_id = forms.ChoiceField(queryset=Product.objects.all(Company=???))
...
...
So my question is. How to get the current user, when I'm inside forms.py file? I don't have the "request" object there..
Views.py
def yourview(request):
yourform = SaleFilterForm(request.POST, user=request.user)
Forms.py
class SaleFilterForm(forms.Form):
...
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user', None)
super(SaleFilterForm, self).__init__(*args, **kwargs)
Then you can use your user inside of your form as self.user
Hope it helps!
This is the best simple code in Django to pass user information form views.py to various files is by using a function
in the file, you want to access the current user info (ex:models.py) :
after all imports
`
user = None
def current_user(request):
global user
user = request.user
`
and use the object variable user in the file
in views.py:
from .models import current_user
in any function(eg-def login(request):)
current_user(request)
It is just based on simple sending variable via the function. Simple logic

Categories