I am trying to make a user registration form in django.
I browsed through many links but I am still confused. I am making some sill mistake please point it out.
here is my code:
models.py
from django.db import models
from django.db.models.signals import post_save
from django.contrib.auth.models import User
class UserProfile(models.Model):
mobile = models.CharField(max_length = 20, null=False)
address = models.CharField(max_length = 200)
user = models.OneToOneField(User, unique=True)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class CustomerRegistrationForm(UserCreationForm):
mobile = forms.CharField(max_length = 20)
address = forms.CharField(max_length = 200)
class Meta:
model = User
fields = ('username','email','mobile','address','password1','password2')
view.py
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from django.template import RequestContext
from django.core.context_processors import csrf
from neededform.forms import CustomerRegistrationForm
def register(request):
print "I am in register function"
if request.method == 'POST':
if request.method == 'POST':
form = CustomerRegistrationForm(request.POST)
if form.is_valid():
f = form.save()
return HttpResponseRedirect('/registered/')
else:
args = {}
args.update(csrf(request))
args['form'] = CustomerRegistrationForm()
return render_to_response('User_Registration.html', args ,context_instance = RequestContext(request))
what I am thinking is that when I do a form.save() in views.py, django should create the user in auth_user table and must insert the values (i.e mobile and address ) in the UserProfile table also.
but what happening is that it is inserting data in auth_user table correctly but in the UserProfile table only id and user_id coloumns are filled, mobile and address both remains empty.
What am I doing wrong ? What else must be done ?
Thank you.
Take a look at the following:
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
You create a UserProfile object which only has its user attribute set!
I don't think that using signal is the best approach to your problem since it's not easy to pass the mobile and address from your form to the Profile creation point. Instead you can override the save() method of your CustomerRegistrationForm where you'd first save the user and then create the profile. Something like this:
class CustomerRegistrationForm(UserCreationForm):
# rest code ommited
def save(self, commit=True):
user = super(CustomerRegistrationForm, self).save()
p = UserProfile.objects.get_or_create(user=user )
p[0].mobile = self.cleaned_data['mobile']
p[0].address = self.cleaned_data['address']
p[0].save()
return user
Related
I am trying to make a simple to-do list in Django that each user could have their own task list so when they logged in they add a task and its save for themselves and the list only display their own tasks, but when I try to add a task from the template's form it won't save but when I add task manually from admin panel it work.
my models.py
from django.db import models
from django.contrib.auth.models import User
class Tasks(models.Model):
user = models.ForeignKey(User, null=True,on_delete=models.CASCADE)
title = models.CharField(max_length=200)
check = models.BooleanField(default = False)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
forms.py
from django import forms
from django.forms import ModelForm
from .models import *
class TaskForm(forms.ModelForm):
class Meta:
model = Tasks
fields = '__all__'
views.py:
from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required
from .forms import *
from .models import Tasks
#login_required(login_url = 'login')
def tasks(request):
tasks = Tasks.objects.filter(user = request.user)
context = { 'tasks': tasks }
return render(request,'ToDo/list.html',context)
#login_required(login_url = 'login')
def add_task(request):
form = TaskForm()
if request.method == 'POST':
form = TaskForm(request.POST)
if form.is_valid():
form.save(commit=False)
form.user = request.user
form.save()
return redirect('/')
context = {'form' : form}
return render(request,'ToDo/add.html',context)
where is the problem?
You assign the user to the .user attribute of the form, not of the .instance wrapped in the form. You thus should alter the instance with:
#login_required(login_url = 'login')
def add_task(request):
if request.method == 'POST':
form = TaskForm(request.POST, request.FILES)
if form.is_valid():
form.instance.user = request.user
form.save()
return redirect('/')
else:
form = TaskForm()
return render(request, 'ToDo/add.html', {'form' : form})
You should furthermore only redirect in case of a successful POST request: in case the POST request is not successful, the form can render the error messages, and thus will inform the user what the problem is.
Furthermore you make the user field non-editable:
from django.conf import settings
class Tasks(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
editable=False,
on_delete=models.CASCADE
)
title = models.CharField(max_length=200)
check = models.BooleanField(default = False)
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.
The dropdown list appears correctly in the html, However I am unable to figure out why I run into the same error time after time when I try to submit / .
"Select a valid choice. That choice is not one of the available choices."
the problem context
I have two models defined in Django. One CourseModel database to hold all the offered courses and one registration database to link a course to a user.
models.py
from django.db import models
# Create your models here.
class CourseModel(models.Model):
course = models.CharField(max_length=100)
date = models.DateField(max_length=100)
time = models.TimeField()
location = models.CharField(max_length=100)
datetime = models.DateTimeField()
class RegistrationModel(models.Model):
name = models.CharField(max_length=100)
adress = models.CharField(max_length=100)
city = models.CharField(max_length=100)
email = models.EmailField(max_length=100)
course = models.ForeignKey('self', on_delete=models.CASCADE)
def __str__(self):
return self.name
I use modelForm to create a registration form, where the user can subscribe for a course from a dropdown list.
forms.py
from django.forms import ModelForm, RegexField
from home.models import RegistrationModel, CourseModel
from django import forms
import datetime
class RegistrationForm(ModelForm):
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields['course'].queryset = CourseModel.objects.exclude(date__lt=datetime.datetime.today()).values_list('datetime', flat=True)
self.fields['course'].empty_label = None
class Meta:
model = RegistrationModel
fields = '__all__'
views.py
from django.shortcuts import render, redirect
from home.forms import RegistrationForm
from .models import CourseModel
import datetime
def home(request):
return render(request, 'home/home.html')
def registration(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
crs = request.POST.get('course')
print(crs)
if form.is_valid():
cleanform = form.save(commit=False)
cleanform.course = crs
cleanform.save()
return redirect('home')
else:
form = RegistrationForm()
return render(request, 'home/registration.html', {'form': form})
In the RegistrationForm's __init__() method, your self.fields['course'].queryset = ...values_list('datetime', flat=True) returns datetime instances. See values_list() docs.
I believe this may cause the issue. I guess the queryset should return CourseModel instances, based on the Django docs:
ForeignKey is represented by django.forms.ModelChoiceField, which is a ChoiceField whose choices are a model QuerySet.
Also, your RegistrationModel.course field has a foreign key to 'self' instead of the CourseModel. Not sure if that is what you want.
Other examples of setting the field queryset can be found here.
I have two models(User and Profile). In Profile model as you can see I have idx field which I use for sorting. In my project I show list of profiles and admin can sorting them by drag and drop. For thats why I use idx. Also this field is invisible and admin dont change its value manually.
Question: How edit User data by profile id. As I said before I show list of profiles. Right now I have edit form where I show user data by profile id. Problem raise when I try to submit form after changes.
models.py:
# -*- coding: utf-8 -*-
from django.db import models
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save, post_delete
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
idx = models.IntegerField(verbose_name='Field for sorting, default=0, blank=True,)
class Meta:
ordering = ['idx', 'pk']
db_table = 'user_profile'
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
#receiver(post_delete, sender=Profile)
def delete_user(sender, instance=None, **kwargs):
try:
instance.user
except User.DoesNotExist:
pass
else:
instance.user.delete()
forms.py:
from django import forms
from django.contrib.auth.models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = '__all__'
views.py:
class UserEditView(UpdateView):
template_name = 'users/edit_user.html'
form_class = UserForm
model = User
def get(self, request, *args, **kwargs):
data = dict()
profile = Profile.objects.get(pk=self.kwargs['pk'])
user_edit_form = UserForm(instance=profile.user)
context = {
'profile': profile,
'user_edit_form': user_edit_form
}
data['html_user_edit_form'] = render_to_string(
'users/edit_user.html', context, request=request
)
return JsonResponse(data)
def form_valid(self, form):
form.save()
data = dict()
data['form_is_valid'] = True
context = {'users': User.objects.all()}
data['html_users'] = render_to_string('users/users.html', context)
return JsonResponse(data)
ERROR:
LevelName: WARNING | Module: base | Process: 662 | Thread: 123145371320320 | Message: Not Found: /user/31/edit/
LevelName: WARNING | Module: basehttp | Process: 662 | Thread: 123145371320320 | Message: "POST /user/31/edit/ HTTP/1.1" 404 1800
Finally I found my mistake.
From url I take id of profile but then in template I need to send id of user.
I just add context = {'user': profile.user,} and then use in template user.id instead of profile.id.
I am trying to extend the user profile using some of the other questions/answers found here and tutorials on the web. I'm trying to have the UserProfile model included in the admin so I can change the details of the profile (temporarily for now) but it's not showing up even after I include UserProfile in admin.py, which leads me to believe I'm doing something incorrectly here.
model.py
class UserProfile(models.Model):
user = models.ForeignKey(User, unique=True)
quote = models.CharField('Favorite quote', max_length = 200)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
urlconf
(r'^accounts/register/$', 'register'),
view in view.py that registers a user
def register(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
new_user = form.save()
return HttpResponseRedirect('reserve/templates/index.html')
else:
form = UserCreationForm()
c = {'form': form}
return render_to_response("registration/register.html", c, context_instance=RequestContext(request))
admin.py
from reserve.models import UserProfile
from django.contrib import admin
admin.site.register(UserProfile)
The common way is to inline the UserProfile in User editing page, in the admin.py of one your app which is after 'django.contrib.auth' in INSTALLED_APPS:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from reserve.models import UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
class UserWithProfileAdmin(UserAdmin):
inlines = [UserProfileInline]
admin.site.unregister(User)
admin.site.register(User, UserWithProfileAdmin)
Furthermore, you could use the ForeignKey itself as the primary_key:
class UserProfile(models.Model):
user = models.ForeignKey(User, primary_key=True)
quote = models.CharField('Favorite quote', max_length = 200)
In that way, you could save the cost of surrogate id, and keep the id of the userprofile same w/ the user's. This enables UserProfile.objects.get(pk=user_id) (and user.get_profile() is still available of course)
I want to save the email and name fields in django default table called UserSignup
my models.py is:
from django.db import models
class UserSignup(models.Model):
mailid = models.CharField(max_length=100)
name = models.CharField(max_length=100)
my views.py is:
from django import views
from django.shortcuts import render_to_response
from django.template import RequestContext
from Deals.signup.forms import signup
from django.contrib.auth.models import User
from django.http import HttpResponse
def usersignup(request,form_class=signup):
form = form_class()
print form
if form.is_valid():
mail= UserSignup(mailid=request.POST['mailid'])
mail.save()
name= UserSignup(name=request.POST['name'])
name.save()
else:
form = form_class()
return render_to_response('signup/registration_form.html',{'form':form})
and forms.py is
from django import forms
from django.contrib.auth.models import User
from Deals.signup.models import *
from django.utils.translation import ugettext_lazy as _
class signup(forms.Form):
email = forms.EmailField(widget=forms.TextInput(),
label=_("Email address:"))
username = forms.RegexField(regex=r'^\w+$',
max_length=30,
widget=forms.TextInput(),
label=_("Name:"))
def save(self,request,update):
name = self.cleaned_data['name']
name.save()
email = self.cleaned_data['email']
email.save()
Please help me in saving my forms input in database
Check the Django documentation properly http://docs.djangoproject.com/en/dev/topics/forms/
Just change your code in views.py.
def usersignup(request,form_class=signup):
if request.method == 'POST': #If its a form submission, the method is POST
form = form_class(request.POST)
if form.is_valid():
newuser = form.save()
else: #Else display the form
form = form_class()
return render_to_response('signup/registration_form.html',{'form':form})
The 'save' function in your forms file is incorrect and is not needed.
On a side note, your "UserSignup" is not a default User Table. That would be the user model provided by Django. And that already has the fields that you are creating in UserSignup. Why don't you use that feature of Django?
It might be better to save the model elements in the form in one time.
def save(self):
new_user = User.objects.create_user(name = self.cleaned_data['name'],
email = self.cleaned_data['email'])
return new_user