Required "owner_id" field is empty in the Database - django

I am trying to save the owner_id that is the same as the Logged In user/Authenticated user. But after I save the AddressBook form,the database saves the owner id with 'Null' value. Can someone help me knowing where am I going wrong.
models.py
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="profile")
mobiles = models.ManyToManyField(Product, blank=True)
class AddressBook(models.Model):
name = models.CharField(max_length=50)
owner = models.ForeignKey(UserProfile, on_delete=models.SET_NULL, null=True)
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(validators=[phone_regex], max_length=17) # validators should be a list
line1 = models.CharField(max_length=100)
line2 = models.CharField(max_length=100, blank=True)
city = models.CharField(max_length=25)
state = models.CharField(max_length=25)
postcode = models.CharField(max_length=8)
country = models.CharField(max_length=25)
views.py
#login_required
def address(request):
existing_order = get_user_pending_order(request)
form = AddressBookForm()
context = {
'addressbook': AddressBook.objects.all(),
'form' : form,
'order' : existing_order,
}
return render(request, 'cart/user_address.html', context)
#login_required
def process_payment(request, order_id):
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
form.save()
return redirect (reverse('update-records', kwargs={'order_id': order_id}))
forms.py
from django import forms
from .models import AddressBook
class AddressBookForm(forms.ModelForm):
ADDRESS_TYPE = (
('Home', 'Home'),
('Work', 'Work'),
)
address_type = forms.ChoiceField(choices=ADDRESS_TYPE, widget=forms.RadioSelect)
class Meta:
model = AddressBook
fields = ['name', 'phone_number', 'line1', 'line2', 'city', 'state', 'postcode', 'country','address_type']
Database

You can save the form with commit=False, set the owner, and then save to the database:
if request.method == 'POST':
form = AddressBookForm(request.POST)
if form.is_valid():
address = form.save(commit=False)
address.owner = request.user.profile
address.save()

Related

Two of my custom user models cannot fail to login

I have created 3 custom user models. However only one user under the models Users() is able to login in into a sells dashboard that I have created. I want the two user namelly, Buyer() and Supplier() to be able to login to the dashboard but not to the admin area. The following is my code. Please help me see the error.
# models.py
# These are my three custom models
from django.db import models
from django.contrib.auth.models import AbstractUser, AbstractBaseUser, UserManager, BaseUserManager, PermissionsMixin
from django.conf import settings
# Superuser model
class Users(AbstractUser):
username = models.CharField(max_length=25, unique=True)
email = models.EmailField(unique=True, null="True")
objects = UserManager()
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
# Returns username
def __str__(self):
return self.username
# Supplier user model
class Supplier(AbstractBaseUser):
sname = models.CharField(max_length=255, verbose_name='Supplier Name', unique=True)
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address', null=True)
physical_address = models.CharField(max_length=255, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe yourself')
is_active = models.BooleanField(default=True)
objects = Users()
USERNAME_FIELD = 'sname'
def __str__(self):
return self.sname
# This model save inventory of a supplier
class Inventory(models.Model):
pname = models.CharField(max_length=255, verbose_name='Product Name')
quantity = models.PositiveIntegerField(verbose_name='Quantity (kgs)')
measurement = models.CharField(max_length=255, verbose_name='Measurement')
orginal_price = models.PositiveIntegerField(verbose_name='Original Price')
commission = models.PositiveIntegerField(verbose_name='Commission')
selling_price = models.PositiveIntegerField(verbose_name='Selling Price (MWK)')
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, verbose_name='Supplier')
def __str__(self):
return self.pname
# This model saves the transaction a buyer has made
class Transaction(models.Model):
cust_name = models.CharField(max_length=255, verbose_name='Customer Name')
pid = models.ForeignKey(Inventory, on_delete=models.CASCADE, verbose_name='Product')
quantity_r = models.PositiveIntegerField(verbose_name='Quantity (KGS)')
success = models.BooleanField(default=False)
uid = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name='User Id')
# Calculates actual price
def actual_price(self):
return int(self.quantity_r) * int(self.pid.selling_price)
# Returns customer name
def __str__(self):
return self.cust_name
# Calculates total costs of suppliers products
class SupplierProductCostView(models.Model):
id = models.PositiveIntegerField(primary_key=True)
sname = models.CharField(max_length=255)
price = models.PositiveIntegerField()
class Meta:
db_table = 'home_supplierproductcostview'
managed = False
def __str__(self):
return str(self.id) + ' ' + self.sname + ' ' + str(self.price)
# Buyer user model
class Buyer(AbstractBaseUser):
username = models.CharField(max_length=255, unique=True)
company_name = models.CharField(max_length=255, verbose_name='Company Name')
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address')
address = models.CharField(max_length=500, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe your company')
is_active = models.BooleanField(default=True)
objects = Users()
USERNAME_FIELD = 'username'
# Returns username
def __str__(self):
return self.username
# forms.py
# This is my registration and login form
from django import forms
from .models import Supplier, Buyer
# Custom supplier registration form
class SupplierRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
# Supplier registration form fields
class Meta:
model = Supplier
fields = ('sname', 'phone_number', 'email_address', 'physical_address', 'description')
# Password check
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
# Custom buyer registration form
class BuyerRegistrationForm(forms.ModelForm):
password = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Repeat password', widget=forms.PasswordInput)
# Buyer registration form fields
class Meta:
model = Buyer
fields = ('username', 'company_name', 'phone_number', 'email_address', 'address', 'description')
# Password check
def clean_password2(self):
cd = self.cleaned_data
if cd['password'] != cd['password2']:
raise forms.ValidationError('Passwords don\'t match.')
return cd['password2']
# Login form
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(widget=forms.PasswordInput)
#views.py
# These are my login and logout views
from django.shortcuts import render, redirect, reverse
from django.contrib.auth import authenticate, login, logout
from users.forms import LoginForm
# User logs in to dashboard
def index(request):
if request.method == 'POST':
loginform = LoginForm(request.POST)
# Check if form is valid
if loginform.is_valid():
username = loginform.cleaned_data['username']
password = loginform.cleaned_data['password']
user = authenticate(username=username, password = password)
# If user does not exist
if user is not None:
login(request, user)
return redirect(reverse('home'))
else:
context = {
'form':loginform,
'error': 'Could not login, Please try again...',
}
return render(request, 'users/index.html', context)
loginform = LoginForm()
context = {
'form' : loginform,
}
# Returns login form
return render(request, 'users/index.html', context)
# Logout
def logout_user(request):
logout(request)
return redirect(reverse('login'))
I extended the custom user model with a OneToOneField but now I Am getting this error "django.db.utils.IntegrityError: null value in column "users_id" violates not-null constraint" apparently there is something wrong with my registration view. Can you help?
# Buyer registration view
def buyer_form_register(request):
if request.method == 'POST':
buyer_form = BuyerRegistrationForm(request.POST)
if buyer_form.is_valid():
# Create a new user object but avoid saving it yet
new_user = buyer_form.save(commit=False)
# Set the chosen password
new_user.set_password(
buyer_form.cleaned_data['password'])
# Save the User object
new_user.save()
# Create the user profile
return render(request, 'register/register_done.html')
else:
buyer_form = BuyerRegistrationForm()
return render(request, 'register/register_buyer.html', {'buyer_form': buyer_form})
# Edited model
class Buyer(AbstractBaseUser):
# New field
users = models.OneToOneField(Users, on_delete=models.CASCADE)
username = models.CharField(max_length=255, unique=True)
company_name = models.CharField(max_length=255, verbose_name='Company Name')
phone_number = models.CharField(max_length=255, verbose_name='Phone Number')
email_address = models.CharField(max_length=255, verbose_name='Email Address')
address = models.CharField(max_length=500, verbose_name='Physical Address')
description = models.TextField(max_length=255, verbose_name='Describe your company')
objects = Users()
USERNAME_FIELD = 'username'
def __str__(self):
return self.username
You can't have 3 custom user models, in settings.py you can only set AUTH_USER_MODEL to one model.
Extend your user model with profiles (OneToOneField) instead to differentiate between the different user types.

Avoid duplicates using django ModelForm

I have the following Model, ModelForm and View:
class Clinic(models.Model):
clinicid = models.AutoField(primary_key=True, unique=True)
name = models.CharField(max_length=60)
label = models.SlugField(max_length=25)
# logo =
email = models.EmailField(max_length=50, default='')
mobile = models.CharField(max_length=15, default='')
alternate = models.CharField(max_length=15, default='', blank=True)
about = models.CharField(max_length=250, blank=True)
state = models.CharField(max_length=25)
city = models.CharField(max_length=35)
locality = models.CharField(max_length=35)
pincode = models.IntegerField(default=0)
address = models.TextField(max_length=80, default='', blank=True)
website = models.URLField(blank=True)
class ClinicMetaForm(ModelForm):
class Meta:
model = Clinic
fields = [
'name',
'label',
'email',
'mobile',
'alternate',
'about',
'state',
'city',
'locality',
'pincode',
'address',
'website'
]
unique_together = ["name", "mobile", "email"]
def newclinic(request):
if request.method == 'POST':
print('New clinic setup')
form = ClinicMetaForm(request.POST)
form.save()
msg = "Successfully saved new clinic"
print(msg)
else:
form = ClinicMetaForm()
msg=''
return render(request, 'clinic/newclinic.html', {'form': form, 'msg': msg})
The problem is that when the same data is submitted, I get duplicate entries being saved, even though I am using unique_together. Why is this happening? How can I avoid it?
You should move unique_together to model.
And if you want to add some logic in your form just overwrite validate_unique
def validate_unique(self):
#your logic here
try:
self.instance.validate_unique(exclude=exclude)
except ValidationError, e:
self._update_errors(e.message_dict)

UNIQUE constraint failed: accounts_user.username

Let's get to the problem
I have a page where I want users to fill info about themselves, and i would like to save that data. But I'm getting this error.
IntegrityError at /accounts/profile/edit/1/change-profile/
UNIQUE constraint failed: accounts_user.username
this is my view.py
def change_profile(request, pk):
form = ChangeProfile(request.POST or None)
user_ = request.user
if request.method == "POST":
if form.is_valid():
form.save()
return redirect("/accounts/profile/edit/{}/".format(user_.pk))
args = {'form': form}
return render(request, 'change_profile.html', args)
my models.py
class GradeUser(models.Model):
grade = models.CharField(max_length=20, null=True)
class Country(models.Model):
country = models.CharField(max_length=30, null=True)
class User(AbstractBaseUser):
email = models.EmailField(
verbose_name = 'email address',
max_length=255,
unique=True
)
real_name = models.CharField(max_length=20, blank=True)
username = models.CharField(max_length=40, unique=True, verbose_name='username')
grade = models.ForeignKey(GradeUser, on_delete=models.CASCADE, blank=True, null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE, blank=True, null=True)
reputation = models.IntegerField(default=0)
image = models.ImageField(upload_to='accounts/media', blank=True)
about_me = models.TextField()
USERNAME_FIELD= 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
forms.py
class ChangeProfile(forms.ModelForm):
class Meta:
model = User
fields = ('real_name', 'grade', 'country', 'about_me')
What does exactly go wrong?
Why would it need a user's username?
What should I do with it to save?
You aim to perform an update on your User (that already exists) but here you are creating a whole new user instance with no username attribute and that's what generates the error.
Try this code : it gets your current user and updates it with the info provided from the form.
PS : I did not modify anything about the returns because I dunno what you're doing there but note that you don't need to pass the user pk through the arguments, the user data is already stored in the request object.
def change_profile(request, pk):
form = ChangeProfile()
user_ = request.user
if request.method == "POST":
form = ChangeProfile(request.POST)
if form.is_valid():
user_new_info=form.save(commit=false)
user_.real_name = user_new_info.real_name
user_.grade = user_new_info.grade
user_.country = user_new_info.country
user_.about_me = user_new_info.about_me
user_.save()
return redirect("/accounts/profile/edit/{}/".format(user_.pk))
args = {'form': form}
return render(request, 'change_profile.html', args)

OneToOneField is nor related

this me again. I have some trouble with my code. I made a form from ModelForm which have a model with 8 attributes, but i want to user fill only one of them,and one from the system. The one that user fill is okay, but the one filled with system is not working.
models.py
class SeminarProposal(md.Model):
# diisi oleh mahasiswa
fileProposal = models.FileField()
# This is the one is filled with system
proposal = models.OneToOneField(Proposal,
on_delete=models.CASCADE,
related_name="propSid",
unique=True, blank=True, null=True)
masabimbingan = models.BooleanField(default=True)
# disi oleh admin
tanggal = models.DateField(default=timezone.now, blank=True,null=True)
tempat = models.CharField(max_length=30, blank=True, null=True)
# diisi oleh dosen pembimbing
dospemsetuju = models.BooleanField(default=False, blank=True)
# diisi oleh kaprodi
penguji1 = models.ForeignKey(Dosen,
on_delete=models.CASCADE,
related_name="penguji1",
blank=True, null=True)
penguji2 = models.ForeignKey(Dosen,
on_delete=models.CASCADE,
related_name="penguji2",
blank=True, null=True)
def __str__(self):
return "Sidang untuk " + self.proposal.judul
view.py
def daftarSeminar(request):
if request.method == 'POST':
form = FormSeminar(request.POST, request.FILES)
print(request.user)
if form.is_valid():
form.save(commit=False)
form.cleaned_data['proposal']
print(request.user)
prop = Proposal.objects.get(akun=request.user)
form.proposal = prop
print(form.proposal) #to confirm that this is not None
form.save()
return redirect('proposal:bimbingan')
else:
return render(request, 'sidprop.html' , {'oke': 'oke'})
return redirect('proposal:index')
form.py
class FormSeminar(forms.ModelForm):
class Meta:
model = SeminarProposal
fields = ['fileProposal','proposal']
Thanks in advance. Terimakasih.
Instead of changing the form data, get the object from form and change the object's data:
if form.is_valid():
obj = form.save(commit=False)
prop = Proposal.objects.get(akun=request.user)
obj.proposal = prop
obj.save()
return redirect('proposal:bimbingan')

how to pass the an authenticated user to forms.py in django

I have a django app with which every registered user can create categories. For the authentication I am using django-all-auth. My models.py looks like this:
class Profile(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.OneToOneField(User, on_delete=models.CASCADE)
create_date = models.DateTimeField('date added', auto_now_add=True)
modify_date = models.DateTimeField('date modified', default=timezone.now)
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
user = models.ForeignKey(Profile, on_delete=models.CASCADE)
name = models.CharField(max_length=200, unique=True)
create_date = models.DateTimeField('date added', auto_now_add=True)
modify_date = models.DateTimeField('date modified', default=timezone.now)
On the index page the user can see the created categories and create new ones.
The views.py:
def CategoryView(request):
user = 0
if request.user.is_authenticated():
user = request.user
form = CategoryNameForm()
form.user = user
context = {
'categories': Category.objects.all(),
'form': form,
'user':user,
}
if request.method == 'POST':
form = CategoryNameForm(request.POST)
form.user = user
if form.is_valid():
form.save()
return render(request, 'myapp/index.html',context)
forms.py:
class CategoryNameForm(forms.ModelForm):
class Meta:
model = Category
fields = ('name',)
The authentication works. So I was thinking to just put pass the user field into the form :
class CategoryNameForm(forms.ModelForm):
class Meta:
model = Category
fields = ('name','user',)
hide it and then, just select it via JS since the user is in the context. I was just wondering if there is an easier way. This form.user = user for some reason didn't work, I get a NOT NULL constraint failure
There are couple of ways but here is one:
class CategoryNameForm(forms.ModelForm):
class Meta:
model = Category
fields = ('name',) # take out user you don't need it here
def save(self, **kwargs):
user = kwargs.pop('user')
instance = super(CategoryNameForm, self).save(**kwargs)
instance.user = user
instance.save()
return instance
Then in view:
if form.is_valid():
form.save(user=request.user, commit=False)
Make sure your CategoryView is only accessible by authenticated user. Otherwise you will still get NOT NULL constraint failure for user.