I am creating a donation app that allows donors to create listings. This data is stored in a Django Model and is going to be displayed on a page. I want to save the user's username to the Django model and display it on the page. My code is down below
Models.py
class Donation(models.Model):
title = models.CharField(max_length=30)
phonenumber = models.CharField(max_length=12)
category = models.CharField(max_length=20)
image = models.CharField(max_length=1000000)
deliveryorpickup = models.CharField(max_length=8)
description = models.TextField()
Views.py
from django.contrib.auth.models import User
from django.http.request import RAISE_ERROR
from django.http.response import HttpResponseRedirect
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.forms import forms, inlineformset_factory
from django.contrib.auth.forms import UserCreationForm, UsernameField
from .forms import CreateUserForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from home.models import Donation
# Create your views here.
def index(request,*args, **kwargs):
return render(request, "index.html", {} )
#login_required(login_url='/login/')
def dashboard(request,*args, **kwargs):
return render(request, "dashboard.html", {} )
def register(request, ):
if request.user.is_authenticated:
return redirect('/dashboard/')
else:
form = CreateUserForm()
if request.method == "POST":
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been successfully created, {username} ')
return redirect('loginpage')
context = {'form': form}
return render(request, "register.html", context )
def loginpage(request):
if request.user.is_authenticated:
return redirect('/dashboard/')
else:
if request.method == 'POST':
username = request.POST.get('username')
password =request.POST.get('password')
user = authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('/dashboard')
else:
messages.error(request, 'Username OR password is incorrect')
context = {}
return render(request, 'login.html', context)
def logoutuser(request):
logout(request)
return HttpResponseRedirect('/login/')
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
title = request.POST['donationtitle']
phonenumber = request.POST['phonenumber']
category = request.POST['category']
image = request.POST['imagelink']
deliveryorpickup = request.POST['deliveryorpickup']
description = request.POST['description']
ins = Donation(title = title, phonenumber = phonenumber, category = category, image = image, deliveryorpickup = deliveryorpickup, description = description )
ins.save()
return render(request,'donate.html')
Forms.py (This is where the user is created)
class CreateUserForm(UserCreationForm):
username = forms.CharField(required=True, max_length=30, )
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True, max_length=50)
last_name = forms.CharField(required=True, max_length=50)
class Meta:
model = User
fields = ['username', 'email', 'first_name', 'last_name', 'password1', 'password2',]
#function to display errors
def clean(self):
cleaned_data=super().clean()
password1 = self.cleaned_data.get('password1')
password2 = self.cleaned_data.get('password2')
if User.objects.filter(username=cleaned_data["username"]).exists():
raise ValidationError("This username is taken, please try another one")
elif password1 != password2:
raise forms.ValidationError("2 password fields do not match")
elif len(password1) < 8 or len(password2) < 8:
raise forms.ValidationError("Passwords must be at least 8 characters long")
To associate the user with the Donation model, you should first add a ForeignKey field to the model class:
from django.conf import settings
class Donation(models.Model):
... # your other donation fields
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
blank=True,
null=True,
)
Once you've made this change, and run the migrations, in your views.py you'll pass the currently signed in user to the Donation model creation:
#login_required(login_url='/login/')
def donate(request):
if request.method == "POST":
ins = Donation(
title=request.POST["title"],
... # all of the other fields
user=request.user, # 👈 This adds the user
)
ins.save()
return render(request,'donate.html')
Notes
Using settings.AUTH_USER_MODEL allows your class to use a custom user model, or django's default user model, based on your project's settings.
To understand what on_delete=models.CASCADE does, you should read django's documentation about it.
Also, instead of manually passing all of the request.POST[...] values to the Donation model, I recommend that you use a ModelForm. It will handle errors and validation for you, as well as generate the HTML displayed in the template. Using a model form here would make your view code change to this:
from django.forms import ModelForm
class DonationForm(ModelForm):
class Meta:
model = Donation
exclude = ["user"]
#login_required(login_url="/login/")
def donate(request):
if request.method == "POST":
form = DonationForm(request.POST)
if form.is_valid():
donation = form.save(commit=False)
donation.user = request.user
donation.save()
# Use a redirect to prevent duplicate submissions
# https://docs.djangoproject.com/en/3.2/topics/http/shortcuts/#redirect
return redirect(request, ...)
else:
form = DonationForm()
return render(request, "donate.html", {"form": form})
i am making an ecom app for Django but when i use a diffrent user i get this error. i think it has something to do with assigning a Customer to a User, as when i manually create a Customer with a User.
Exception Type: RelatedObjectDoesNotExist
Exception Value:
User has no customer.
Exception Location: L:\Django\Website\lib\site-packages\django\db\models\fields\related_descriptors.py in __get__, line 420
Python Executable: L:\Django\Website\Scripts\python.exe
Python Version: 3.8.3
here is my views.py
from django.shortcuts import render
from .models import *
from django.http import JsonResponse
import json
import datetime
from django.contrib.auth.models import User
def store(request):
if request.user.is_authenticated:
customer = request.user.customer
order, created = Order.objects.get_or_create(customer=customer, complete=False)
items = order.orderitem_set.all()
cartItems = order.get_cart_items
else:
items = []
order = {'get_cart_total':0,'get_cart_items':0, 'shipping':False}
cartItems = order['get_cart_items']
search = request.GET.get('search')
products = Product.objects.all()
if search != '' and search is not None:
products = products.filter(name__icontains=search)
context= {'products': products, 'cartItems':cartItems}
return render(request, 'store/store.html', context)
...unrelated...
here is my models.py
from django.db import models
from django.contrib.auth.models import User
class Customer(models.Model):
user = models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
name = models.CharField(max_length=200, null=True)
email = models.CharField(max_length=200)
def __str__(self):
return self.name
...unrelated...
========================
when i use the method in the code block it doesn't save the extra fields
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST, request.FILES)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to login')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
but when i try this it saves everything except the passwords
forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class meta:
model = User
fields = ['username', 'first_name', 'last_name', 'email', 'password1', 'password2']
def save(self, **kwargs):
user = super(UserCreationForm, self).save(commit=False)
user.email = self.cleaned_data["email"]
user.first_name = self.cleaned_data["first_name"]
user.last_name = self.cleaned_data["last_name"]
user.save()
return user
views.py is the same.
I'd suggest to use the Customer model as what you refer to as the user throughout the app. Therefore I would keep the save method for the user as default and add the extra fields to the Customer model.
This makes it also easier to later add extra data of the user when registering. The Customer would be created on registering the user. For example:
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
def save(self, **kwargs):
user = super().save()
customer = Customer.objects.create(user=user, first_name=self.cleaned_data.get('first_name'),
last_name=self.cleaned_data.get('last_name'), email=self.cleaned_data.get('email'))
return user
The Customer model will need a first_name and last_name field instead of name now.
Your current code (store view) will then work as well.
thanks for your time.
i've been trying to set a model to his creator user. although i'm getting this error and would like to know if am'i doing anything wrong before try a AbstractUser. i'did my user app just in the forms.py i don't know if thats the reason.
Error:
table services_parceiros has no column named user_id
accounts/forms.py:
from django import forms
from django.contrib.auth import get_user_model, authenticate
User = get_user_model()
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput())
def clean (self, *args, **kwargs):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError('usuario não encontrado')
if not user.check_password(password):
raise forms.ValidationError('senha incorreta')
if not user.is_active:
raise forms.ValidationError('usuario desativado')
return super(LoginForm, self).clean(*args, **kwargs)
class RegisterForm(forms.ModelForm):
first_name = forms.CharField(max_length=100)
last_name = forms.CharField(max_length=100)
email = forms.EmailField(label='Email address')
email2 = forms.EmailField(label='Confirm Email')
password = forms.CharField(widget=forms.PasswordInput)
class Meta:
model = User
fields = [
'first_name',
'last_name',
'username',
'email',
'email2',
'password'
]
def clean(self, *args, **kwargs):
email = self.cleaned_data.get('email')
email2 = self.cleaned_data.get('email2')
if email != email2:
raise forms.ValidationError("Emails must match")
email_qs = User.objects.filter(email=email)
if email_qs.exists():
raise forms.ValidationError(
"This email has already been registered")
return super(RegisterForm, self).clean(*args, **kwargs)
services/models.py:
from django.db import models
from phone_field import PhoneField
from datetime import datetime
from django.contrib.auth import get_user_model
from django.template.defaultfilters import slugify
from accounts.forms import User
get_user_model = User
class Parceiros (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
nome = models.CharField(max_length=200)
endereco = models.TextField(max_length=400, blank=True)
responsavel = models.CharField(max_length=100)
tel = PhoneField(max_length=12)
created_at = models.DateTimeField(auto_now=True)
updated_at = models.DateTimeField(auto_now_add=True, blank=True)
ativo = models.BooleanField(default=False)
def __str__(self):
return '%s %s' % (self.user, self.nome)
and services/views.py:
from django.shortcuts import render, redirect
from .models import Servicos, Parceiros, Imagens
from django.views.generic import UpdateView, DetailView, ListView
from .forms import ParceirosForm, ServicosForm, ImagensForm
from django.contrib.auth.decorators import login_required
from django.contrib.auth.context_processors import auth
def home_view(request):
serv = Servicos.objects.all()
context = {'serv': serv }
return render (request, 'home.html', context)
#login_required
def parceiros_create(request):
if request.method == 'POST':
form = ParceirosForm(request.POST)
if form.is_valid():
parceiro = form.save(commit=False)
parceiro.user = request.user # assuming user is a FK field on Parceiros#
parceiro.save()
return redirect('home2')
else:
form = ParceirosForm()
context = {
'form': form,
}
return render (request, 'parceiroform.html', context)
def get_queryset(self):
return super().get_queryset().filter(parceiro__user=self.request.user)
services/forms.py:
if i specify the user on fields of my ParceirosForm i'll get the field displayed and still gets the same error when submit.
from django import forms
from .models import Servicos, Imagens, Parceiros
from phone_field import PhoneField
class ParceirosForm(forms.ModelForm):
nome = forms.CharField(max_length=200)
endereco = forms.TextInput()
responsavel = forms.CharField(max_length=100)
tel = PhoneField(max_length=12)
class Meta:
prefix = 'parceiro'
model = Parceiros
fields = ['nome', 'endereco', 'responsavel', 'tel']
0001_initial.py:
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import phone_field.models
import services.models
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Parceiros',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('nome', models.CharField(max_length=200)),
('endereco', models.TextField(blank=True, max_length=400)),
('responsavel', models.CharField(max_length=100)),
('tel', phone_field.models.PhoneField(max_length=12)),
('created_at', models.DateTimeField(auto_now=True)),
('updated_at', models.DateTimeField(auto_now_add=True)),
('ativo', models.BooleanField(default=False)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
I have a custom User Model. I can successfully add user to it and want to add the relationship to a related model. It gives me no errors but does not link the user to the related field compusers in the company model. Basically I need it to after creating a user, also add the user to the related compusers field.
This is the code I am trying in the view:
self.object.compusers.add(self.object.id)
The Model
class Company(models.Model):
user = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='compusers')
name = models.CharField(max_length=265, blank=True)
tel = models.IntegerField(blank=True, null=True)
email = models.EmailField(max_length=265,blank=True)
address = models.TextField(blank=True)
postal = models.TextField(blank=True)
regno = models.CharField(max_length=265,blank=True)
vatno = models.CharField(max_length=265,blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('nodisoapp:home')
The View
class AddStaffView(CreateView):
form_class = forms.AddStaffMember
success_url = reverse_lazy('nodisoapp:home')
template_name = "scrty/addstaff.html"
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.password = get_random_string(length=8)
self.object.save()
self.object.compusers.add(self.object.id)
return super(AddStaffView, self).form_valid(form)
The form
Class AddStaffMember(forms.ModelForm):
usrtype = forms.ChoiceField(choices=[('Admin','Admin'),('Manager','Manager'),('Employee','Employee')],label="User Type: See below for descriptions" )
class Meta:
model = get_user_model()
fields = ("firstname","lastname","email","usrtype")
labels = {
"firstname": _("First Name"),
"lastname": _("Last Name"),
"email": _("E-mail"),
}
I recently went through this same process. It's not finalized, but it should help. With this project, I create a user, and that user (customer) has obvious attributes that are required (e.g. first name, last name, phone, email, company, and site). There was a lot of problems in just simply trying to extend the django User model and add relationships that work well, so I went with having my own user model. This model retains the use of Username. I can provide projects that uses email instead of username. This project also uses some styling widgets on the login form. I have other projects that style other parts of auth as well.
main/models.py
from django.contrib.auth.models import (
AbstractBaseUser,
PermissionsMixin,
BaseUserManager,
)
from django.core.mail import send_mail
from django.db import models
from django.utils.translation import ugettext_lazy as _
from customers import models as customers_models
class TravelModel(models.Model):
mileageRate = models.DecimalField(max_digits=4, decimal_places=3)
def __str__(self):
return '%s' % (self.mileageRate)
class Meta:
verbose_name = "Current Federal Milage Rate"
#verbose_name_plural = "Milage"
class UserManager(BaseUserManager):
def create_user(self, username, email, firstName, lastName, company, phone, password=None, **kwargs):
if not email:
raise ValueError('Users must have an email address')
user = self.model(
username = userName,
email=self.normalize_email(email),
firstName = firstName,
lastName = lastName,
company = company,
phone = phone
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, email, firstName, lastName, password=None, **kwargs):
user = self.model(
username = username,
email = self.normalize_email(email),
firstName = firstName,
lastName = lastName,
)
user.set_password(password)
user.is_superuser = True
user.is_admin = True
user.save(using=self._db)
return user
class MyUser(AbstractBaseUser, PermissionsMixin):
username = models.CharField(_('Username'), max_length=150, unique=True, null=False, blank=False)
email = models.EmailField(_('E-mail Address'), max_length=255, unique=True)
firstName = models.CharField(_('First Name'),max_length=50, blank=False, null=False)
lastName = models.CharField(_('Last Name'),max_length=50, blank=False, null=False)
company = models.ForeignKey(customers_models.CompanyModel, on_delete=models.PROTECT, null=False)
phone = models.ForeignKey(customers_models.PhoneModel, on_delete=models.PROTECT, null=False)
is_admin = models.BooleanField(
_('staff status'),
default=False,
help_text=_(
'Designates whether the user can log into this admin '
'site.'
)
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as '
'active. Unselect this instead of deleting accounts.'
)
)
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email','firstName', 'lastName']
class Meta(object):
ordering = ['firstName']
verbose_name = _('Contact')
verbose_name_plural = _('Contacts')
def __str__(self):
return '%s - %s %s - %s - %s' % (self.company, self.firstName, self.lastName, self.email, self.phone)
def get_full_name(self):
return self.email
def get_short_name(self):
def has_perm(self, perm, obj=None):
return True
def has_module_perms(self, app_label):
return True
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
#property
def is_staff(self):
return self.is_admin
main/views.py
from django.shortcuts import render, redirect
from django.http import HttpResponseRedirect
from django.contrib import messages
from django.contrib.auth import logout, login, authenticate, update_session_auth_hash
from django.contrib.auth.decorators import login_required, permission_required
from django.contrib.auth.forms import PasswordChangeForm
from django.core.mail import send_mail
from .models import MyUser
from .forms import RegistrationForm, LoginForm, ResetPasswordForm
def IndexView(request):
return render(request, 'main/index.html')
def ContactView(request):
return render(request, 'main/contact.html')
def LoginView(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
return redirect('home')
else:
form = LoginForm()
args={ 'form': form }
return render(request, 'main/login.html', args)
def LogoutView(request):
logout(request)
#login_required
def PasswordChangeView(request):
if request.method == 'POST':
form = PasswordChangeForm(request.user, request.POST)
if form.is_valid():
user = form.save()
update_session_auth_hash(request, form.user) # Important!
messages.success(request, 'Your password was successfully updated!')
return redirect('change_password_done')
else:
messages.error(request, 'Please correct the error below.')
else:
form = PasswordChangeForm(request.user)
return render(request, 'main/change_password_form.html', {
'form': form
})
#permission_required(['auth.add_customuser', 'auth.change_customuser'], raise_exception=True)
def RegisterView(request):
if request.method == 'POST':
form = RegistrationForm(request.POST)
if form.is_valid():
form.save()
return redirect('main')
else:
form = RegistrationForm()
args = {'form': form}
return render(request, 'main/register.html', args)
main/urls.py
from django.conf.urls import url, include
from django.urls import reverse_lazy
from .views import IndexView, RegisterView, ContactView, PasswordChangeView
from .forms import LoginForm
from django.contrib.auth.views import (
LogoutView,
login,
PasswordChangeView,
PasswordChangeDoneView,
PasswordResetView,
PasswordResetDoneView,
PasswordResetConfirmView,
PasswordResetCompleteView,
)
# main app URLS extend from the base url i.e. www.website.com/*
urlpatterns = [
url(r'^$', IndexView, name='main'),
url(r'^register/$', RegisterView, name='register'),
url(r'^contact/$', ContactView, name='contact'),
url(r'^logout/$', LogoutView.as_view(next_page=reverse_lazy('main')),
name='logout'
),
url(r'^service/', include('service.urls')),
url(r'^consultation/', include('consultation.urls')),
# successful logins are redirected to the settings.LOGIN_REDIRECT_URL
url(r'^login/$', login, name='login', kwargs={'template_name':'main/login.html', 'authentication_form':LoginForm},
),
url(r'^change_password/$',
PasswordChangeView.as_view(
template_name='main/change_password_form.html'
),
name='password_change'),
url(r'^change_password/done/$',
PasswordChangeDoneView.as_view(
template_name='main/change_password_done.html'
),
name='password_change_done'),
url(r'^password_reset/$',
PasswordResetView.as_view(template_name='main/reset_password_form.html'),
name='password_reset'),
url(r'^password_reset/done/$',
PasswordResetDoneView.as_view(template_name='main/reset_password_done.html'),
name='password_reset_done'),
url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
PasswordResetConfirmView.as_view(template_name='main/reset_password_confirm.html'),
name='password_reset_confirm'),
url(r'^reset/done/$',
PasswordResetCompleteView.as_view(template_name='main/reset_password_complete.html'),
name='password_reset_complete'),
]
main/forms.py
from django import forms
from django.contrib.auth.forms import (
AuthenticationForm,
UserCreationForm,
UserChangeForm,
PasswordResetForm,
)
from .models import MyUser
class ResetPasswordForm(PasswordResetForm):
pass
class LoginForm(AuthenticationForm):
username = forms.CharField(label='Username',
widget=forms.TextInput(attrs={'placeholder':'Username'}))
password = forms.CharField(label='Password',
widget=forms.PasswordInput(attrs={'placeholder':'Password'}))
class RegistrationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = MyUser
fields = (
'username',
'firstName',
'lastName',
'email',
'password1',
'password2'
)
def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
user.first_name = self.cleaned_data['firstName']
user.last_name = self.cleaned_data['lastName']
user.email = self.cleaned_data['email']
if commit:
user.save()
return user
customers/models.py
from django.db import models
from django.core.validators import RegexValidator
from main import models as main_models
from django.utils.translation import ugettext_lazy as _
class PhoneModel(models.Model):
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$',
message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed."
)
phone_number = models.CharField(_('Phone Number'),validators=[phone_regex],
max_length=15, blank=True
) # validators should be a list
def __str__(self):
return '%s' % (self.phone_number)
class Meta:
verbose_name = "Phone Number"
#verbose_name_plural = "Phone Numbers"
class CompanyModel(models.Model):
name = models.CharField(_('Company Name'),max_length=255)
since = models.DateField(auto_now_add=True)
def __str__(self):
return '%s - Customer since %s' % (self.name, self.since)
class Meta:
ordering = ['name']
verbose_name = "Company Name"
#verbose_name_plural = "Companies"
class DetailsModel(models.Model):
company = models.OneToOneField(CompanyModel, on_delete=models.CASCADE, primary_key=True)
distance = models.SmallIntegerField(blank=True)
rate = models.DecimalField(max_digits=5, decimal_places=2)
def __str__(self):
return '%s - Distance: %s - Rate: %s' % (self.company, self.distance, self.rate)
class Meta:
ordering = ['company']
verbose_name = "Customer Agreement Information"
#verbose_name_plural = "Details"
class SiteModel(models.Model):
company = models.ForeignKey(CompanyModel, on_delete=models.CASCADE)
#contact = models.ForeignKey(main_models.User.email, on_delete=models.CASCADE)
details = models.ForeignKey(DetailsModel, on_delete=models.CASCADE)
street1 = models.CharField(max_length=255)
street2 = models.CharField(max_length=255, blank=True)
city = models.CharField(max_length=50)
state = models.CharField(max_length=2)
zipcode = models.IntegerField()
country = models.CharField(max_length=50)
def __str__(self):
return '%s - %s, %s' % (self.company, self.city, self.state)
class Meta:
ordering = ['company']
verbose_name = "Customer Site Information"
#verbose_name_plural = "Sites"
class ContactModel(models.Model):
company = models.ForeignKey(CompanyModel, on_delete=models.PROTECT, null=True)
first_name = models.CharField(_('First Name'),max_length=255)
last_name = models.CharField(_('First Name'),max_length=255)
email = models.EmailField(_('E-mail Address'), max_length=255, unique=True)
phone = models.ForeignKey(PhoneModel, on_delete=models.PROTECT, null=True)
def __str__(self):
return '%s %s of %s' % (self.first_name, self.last_name, self.company)
I found the answer, the many to many field needs a company reference, therefore instead of adding a user instance you just add a company instance
The following form always returns UserProfile matching query does not exist. though I configured the signal.
And it works like expected from the inetrpreter.
In [1]: from core.models import User
In [2]: u = User.objects.get(id = 1)
In [3]: user_address = u.get_profile().home_address
In [4]: user_address = '20 St.'
Model
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
url = models.URLField()
home_address = models.TextField()
user = models.ForeignKey(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)
View
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User, Group
from django import forms
from django.shortcuts import render_to_response
from django.http import HttpResponse
from django.template.context import RequestContext
from django.views.decorators.csrf import csrf_protect
class RegisterForm(UserCreationForm):
"""
Hacking the UserCreationForm class by creating a child class,
and overriding the save mthod .save().
Now it should provide email, first_name and last_name fields.
"""
permission_choices = (
('1', 'test1'),
('2', 'test2'),
)
email = forms.EmailField(required=False)
first_name = forms.CharField(required=False)
last_name = forms.CharField(required=False)
url = forms.URLField()
permission = forms.ChoiceField(choices=permission_choices)
class Meta(UserCreationForm.Meta):
model = User
fields = ('first_name', 'last_name', 'url', 'username', 'email', 'password1', 'password2', 'permission')
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
user_profile = user.get_profile()
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.permission = self.cleaned_data['permission']
user_profile.url = self.cleaned_data['url']
if commit:
user.save()
user_profile.save()
return user
#csrf_protect
def register(request):
if request.method == 'POST':
form = RegisterForm(request.POST)
if form.is_valid():
new_user = form.save()
if new_user.permission == '1':
try:
new_user.groups.add(Group.objects.get(name='test1'))
except Group.DoesNotExist:
u = User.objects.get(pk=new_user.pk)
u.delete()
return HttpResponse('The Organisation you\'ve just choosed doesn\' exist')
return HttpResponse('OK')
else:
form = RegisterForm()
return render_to_response('registration/user.html', {'form': form}, context_instance=RequestContext(request))
Like what cberner said, I think it's because:
I believe you're getting that error because you call
super(RegisterForm, self).save(commit=False). If you use commit=False
Django wouldn't emit a post_save signal, since the model isn't
actually committed to the database.
Here's the solution:
def save(self, commit=True):
user = super(RegisterForm, self).save(commit=False)
user.email = self.cleaned_data['email']
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
user.permission = self.cleaned_data['permission']
user.save()
user_profile = UserProfile(user=user, url=self.cleaned_data['url'])
if commit:
user_profile.save()
return user
I believe you're getting that error because you call super(RegisterForm, self).save(commit=False). If you use commit=False Django wouldn't emit a post_save signal, since the model isn't actually committed to the database.