Here is views.py code.
In the def index section, I use UserInfo model.Here information store in one to one relation so I write (user__pk=user_id)
from django.shortcuts import render
from Login_app.forms import UserForm, UserInfoForm
from Login_app.models import UserInfo
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.decorators import login_required
from django.urls import reverse
def index(request):
dict={}
if request.user.is_authenticated:
current_user = request.user
user_id = current_user.id
user_basic_info = User.objects.get(pk=user_id)
user_more_info = UserInfo.objects.get(user__pk=user_id)
dict = {'user_basic_info':user_basic_info, 'user_more_info':user_more_info}
return render(request, 'Login_app/index.html', context=dict)
Here is models.py code.where I create UserInfo model.It store user,facebook_id,profile_pc.
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserInfo(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
facebook_id = models.URLField(blank=True)
profile_pic = models.ImageField(upload_to = 'profile_pics', blank=True)
def __str__(self):
return self.user.username
Make Sure that you have inserted data in UserInfo table. For getting date related to one to one field with User table, you don't have to extract user id explicitly. The following code should do it-
current_user = request.user
user_more_info= UserInfo.objects.filter(user=current_user).get()
Moreover, if you have a field called 'full_name' in User model, you can directly access it -
user_full_name=current_user.full_name
Related
So I want to save a Biographie for each new created User. The user can enter his Bio and it will the it to his Profile.
For this I created a model with OneToOneField
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, null=True, blank=True)
bio = models.CharField(max_length=30)
To create the form I did the following in forms.py:
class BioForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('bio',)
Then I created in the views.py the saving, so the bio will be saved to the specific user:
from .forms import LoginForm, RegisterForm
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.contrib.auth import get_user_model
def test_view(request):
form = BioForm(request.POST)
user = get_user_model
if form.is_valid():
profile = form.save(commit=False)
profile.user = request.user
profile.phone_number = request.phone_number
profile.save()
return render(request, 'test.html', {'form': form})
There is something big wrong in the views.py but I don't get it.
I can submit the form and the form will be saved (sometimes) but without the user who wrote it + I get this error:
ValueError at /test/
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x00000253B7140D00>>": "Profile.user" must be a "User" instance
Try to assign the user id instead
from .forms import LoginForm, RegisterForm
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout, get_user_model
from django.contrib.auth import get_user_model
def test_view(request):
form = BioForm(request.POST)
user = get_user_model
if form.is_valid():
profile = form.save(commit=False)
profile.user_id = request.user.id
profile.phone_number = request.phone_number
profile.save()
return render(request, 'test.html', {'form': form})
Your problem is that the user you try to save with, is not an authenticated user that exists in the database. Only authenticated (logged in) users exist in the database and can be used in a relational field
i am getting this "duplicate key value violates unique constraint "myblog_profile_email_3f46e9ef_uniq"
DETAIL: Key (email)=() already exists." error every time when i submit my signup form even with new email address.values save inside User table but it not redirect it on home page.
models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
# Create your models here.
class Profile(models.Model):
user=models.OneToOneField(User,on_delete=models.CASCADE)
first_name=models.CharField(max_length=50,blank=True)
last_name=models.CharField(max_length=50,blank=True)
email=models.EmailField(max_length=120)
bio=models.TextField(blank=True)
gender_choices=(('M','Male'),('F','Female'),('S','Special'))
gender=models.CharField(max_length=1,choices=gender_choices,default='M')
age=models.PositiveIntegerField(default=12)
def __str__(self):
msg = "Name : {0} {1}|| Email : {2} || gender : {3}".format(self.first_name,self.last_name,self.email,self.gender)
return msg
#receiver(post_save, sender=User)
def ensure_profile_exists(sender, **kwargs):
if kwargs.get('created', False):
Profile.objects.get_or_create(user=kwargs.get('instance'))
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
class SignUpForm(UserCreationForm):
# first_name=forms.CharField(max_length=40,help_text="first Name")
# last_name=forms.CharField(max_length=40,help_text="first Name")
email=forms.EmailField(max_length=120)
class Meta:
model=User
fields=('username','email','password1','password2')
views.py
from django.shortcuts import render
from .forms import SignUpForm
from django.shortcuts import redirect
from django.contrib.auth import login,authenticate
from .models import Profile
# Create your views here.
def index(request):
return render(request,'myblog/home.html')
def signUp(request):
form=SignUpForm(request.POST)
if form.is_valid():
user=form.save()
user.refresh_from_db()
# user.profile.first_name=form.cleaned_data.get('first_name')
# user.profile.lastname=form.cleaned_data.get('last_name')
user.profile.email=form.cleaned_data.get('email')
user.save()
username=form.cleaned_data.get('username')
password=form.cleaned_data.get('password1')
user=authenticate(username=username,password=password)
login(request,user)
return redirect('http://127.0.0.1:8000/')
else:
print('form not submitted successfully \n')
form=SignUpForm()
return render(request,'myblog/signup.html',{'form':form})
i am new please also help me to explain why thanks in advance
I am using Django Signals to Trigger Code once the user is created i am saving additional data on another model class, it's getting triggered but it's not redirecting to additional data object page.
Here is my models.py
from django.db import models
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class Customers(models.Model):
user = models.OneToOneField(User)
business_name = models.CharField(max_length=250)
address = models.CharField(max_length=500)
area = models.CharField(max_length=250)
city = models.CharField(max_length=250)
state = models.CharField(max_length=250)
pincode = models.IntegerField(default='0')
phone = models.IntegerField(default='0')
mobile = models.IntegerField(default='0')
def create_customer(sender, **kwargs):
if kwargs['created']:
customer_profile = Customers.objects.create(user=kwargs['instance'])
post_save.connect(create_customer, sender=User)
and here is my admin.py
from django.contrib import admin
from .models import Customers
from django.shortcuts import redirect
admin.site.register(Customers)
class Customers(admin.ModelAdmin):
def response_add(self, request, obj, post_url_continue=None):
return redirect('/admin/app/customers/add/')
def response_change(request, obj):
return redirect('/admin/app/customers/add/')
Tired looking for the answer but nothing works, please correct me here.
It doesn't look like you are registering your admin configuration. Refer to Django docs on the register decorator for more information. The syntax is to decorate your function with #admin.register(<model>) or if you want to manually register the model admin configuration then admin.site.register(<model>, <model admin>).
I would recommend changing class Customers(admin.ModelAdmin): to class CustomersAdmin(admin.ModelAdmin): or something similar to stop the namespace clash.
See example below:
from django.contrib import admin
from .models import Customers
from django.shortcuts import redirect
#admin.register(Customers)
class CustomersAdmin(admin.ModelAdmin):
def response_add(self, request, obj, post_url_continue=None):
return redirect('/admin/app/customers/add/')
def response_change(request, obj):
return redirect('/admin/app/customers/add/')
The use case is that a logged in use, can call up their profile into a form, edit it and it gets updated in the database.
With the code below the correct Profile data can be viewed. It can also be called up into an editable form. The form allows the data to be edited , but when it is submitted, the database is NOT updated and the original profile is displayed.
I’ve tried everything, including console print statements so I know that it is getting to the POST portion of the code, is a valid form and doing the initial save().
Any insights would be appreciated (I am using Django 1.11). I do not want to start a rabbit running but the only thing I have not tried is breakink the OneToOne relationship with User and using a foriegnkey because I want the profile entry creaed when the user registers.
Notes:
When I popped this in for testing purposes: save_data.user = request.user
I get the error: Exception Value:'User' object has no attribute 'cleaned_data'`from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
Models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User)
description = models.CharField(max_length=100, default='')
city = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
balance = models.FloatField(default=0)
bank = models.FloatField(default=0)
image = models.ImageField(upload_to='profile_image', blank=True)
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = UserProfile.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
Forms.py
from django import forms
from django.contrib.auth.models import User
from .models import UserProfile
class ProfileForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ('description', 'city', 'phone', 'balance', 'bank', 'website', 'image')
Views.py
from __future__ import unicode_literals
from django.core.urlresolvers import reverse
from django.contrib.auth import login, authenticate, update_session_auth_hash
from django.contrib.auth.forms import (
UserCreationForm,
UserChangeForm,
PasswordChangeForm
)
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from core.forms import ( EditAccountForm, SignUpForm,
ProfileForm
)
from core.models import UserProfile
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
# Create your views here.
def edit_profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST, instance=request.user)
if form.is_valid():
save_data = form.save()
save_data.user = request.user
print(save_data)
save_data.save()
return redirect(reverse('core:profile'))
else:
udata = UserProfile.objects.get(user=request.user)
form = ProfileForm(instance=udata)
args = {'form': form}
return render(request, 'core/test.html', args)
urls.py
from django.conf.urls import url
from django.contrib import admin
#from playme.core import views as core_views
from core import views as core_views
from django.contrib.auth import views as auth_views
# SET THE NAMESPACE!
app_name = 'core'
urlpatterns = [
url(r'^$', core_views.index, name='index'),
url(r'signup/$', core_views.signup, name='signup'),
url(r'^account/$', core_views.account, name='account'),
url(r'^profile/$', core_views.view_profile, name='profile'),
url(r'^login/$', auth_views.login, {'template_name': 'core/login.html'}, name='user_login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/play/'}, name='logout'),
url(r'^edit_account/$', core_views.edit_account, name='edit_account'),
url(r'^edit_profile/$', core_views.edit_profile, name='edit_profile'),
url(r'^change_password/$', core_views.change_password, name='change_password'),
]
The URL I am hitting is:
http://127.0.0.1:8000/play/profile/
Which then goes to :
http://127.0.0.1:8000/play/edit_profile/
The form loads up but when submitted goes back to:
http://127.0.0.1:8000/play/profile/
With no database update.
I'm surprised this doesn't give an error.
When you instantiate the form on a GET, you correctly pass the UserProfile object as the instance parameter - this is correct because the form has that as its model. But when you instantiate on POST, you incorrectly pass the User object - request.user. You should pass the profile, as you do in the other branch.
Note, in both cases you can get the profile more simply by just doing request.user.userprofile.
Well the form being invalid situation isn't being handled here at all. Your code should look like this
def edit_profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST, instance=request.user)
if form.is_valid():
save_data = form.save(commit=False)
save_data.user = request.user
save_data.save()
return redirect(reverse('core:profile'))
else:
udata = UserProfile.objects.get(user=request.user)
form = ProfileForm(instance=udata)
args = {'form': form}
return render(request, 'core/test.html', args)
Note the change in indentation.
I am creating a web application where users have to register themselves and create profiles. I am using the "AbstractBaseUser" class provided by Django, as I wanted to add some other fields. Now, when a user logs in, I want the login credentials to be the Mobile number and the password. I created a custom authentication function for this and registered it in my settings.py. The problem is this changed the login to my admin sit, which I want to remain the same.
I followed the tutorial for add custom fields to User from this link
My models.py:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import UserManager
class userInfo(AbstractBaseUser):
email = models.EmailField('Email address', unique=True,)
Mobile = models.CharField(max_length=15, unique=True,)
Address = models.CharField(max_length=500)
Landmark = models.CharField(max_length=50)
Status = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
USERNAME_FIELD = 'Mobile'
def __unicode__(self):
return self.get_username()
views.py for login page:
import datetime
from .forms import userInfoForm, LoginForm
from django.shortcuts import render, render_to_response
from .models import userInfo, orderHistory
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext, loader
from django.contrib.auth import login as django_login, authenticate, logout as django_logoutdef Login(request):
"""
Log in view
"""
if request.method == 'POST':
form = LoginForm(data=request.POST)
print ("Step 1")
if form.is_valid():
print ("Step 2")
user = authenticate(Mobile=request.POST['username'], password=request.POST['password'])
print ("Step 3")
if user is None:
print("No valid user")
if user is not None:
print ("Step 3.10")
if user.is_active:
print ("Step 4")
django_login(request, user)
print ("Step 5")
return redirect('/i/Home')
else:
form = LoginForm()
return render_to_response('loginpage.html', {
'form': form,
}, context_instance=RequestContext(request))`
forms.py:
from django import forms
from .models import userInfo, orderHistory
from django.forms import ModelForm
class LoginForm(forms.Form):
"""
Login form
"""
Mobile = forms.CharField(widget=forms.TextInput)
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
fields = ['Mobile', 'password'] `
The backend I created:
from django.conf import settings
from django.contrib.auth.models import check_passwor
from .models import userInfo
class EmailAuthBackend(object):
"""
A custom authentication backend. Allows users to log in using their email address.
"""
def authenticate(self, Mobile=None, password=None):
"""
Authentication method
"""
try:
user = userInfo.objects.get(Mobile=Mobile)
if user.check_password(password):
return user
except userInfo.DoesNotExist:
return None
def get_user(self, user_id):
try:
user = userInfo.objects.get(pk=user_id)
if user.is_active:
return user
return None
except userInfo.DoesNotExist:
return None
And finally the changes I made to settings.py:
AUTH_USER_MODEL = 'Registration.userInfo'
AUTHENTICATION_BACKENDS = ['Registration.authBackend.EmailAuthBackend', ]
The default backend for Django is ('django.contrib.auth.backends.ModelBackend',), which is what the Django admin is using. When you insert the line:
AUTHENTICATION_BACKENDS = ['Registration.authBackend.EmailAuthBackend', ]
you're overwriting the default backend, rather than adding a second backend option. Change that line to:
AUTHENTICATION_BACKENDS = (
'Registration.authBackend.EmailAuthBackend',
'django.contrib.auth.backends.ModelBackend',
)
and your application should pick up the second backend. You may need to trigger the second backend based on logic for whether the first succeeds, see responses to questions like Django Multiple Authentication Backend for one project, HOW? or the docs here.