Add logged user as author of model, but keep ForeignKey - python

I want when add article, current logged user to be added as author, I'm also using ForegnKey to user and want to keep it, but right now throw error:
objects/models.py:
from django.db import models
from users.models import ProfileUser
class Object(models.Model):
author = models.ForeignKey(ProfileUser, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
address = models.CharField(max_length=300)
content = models.TextField()
def __str__(self):
return f"{self.title}"
objects/forms.py:
from django import forms
from .models import Object
class ObjectForm(forms.ModelForm):
class Meta:
model = Object
fields = [
'title',
'address',
'content',
]
objects/views.py:
def add_object(request):
form = ObjectForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
obj.author = request.user
obj.save()
return redirect('home')
context = {
'form': form
}
return render(request, "add_object.html", context)
Also I rewrite default django user model:
users/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 ProfileUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
profile_image = models.URLField()
#receiver(post_save, sender=User) # Still don't know how, but next rows create ProfileUser when User is created
def create_user_profile(sender, instance, created, **kwargs):
if created:
ProfileUser.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.profileuser.save()
def __str__(self):
return f"{self.user}"
Error:
Cannot assign "<SimpleLazyObject: <django.contrib.auth.models.AnonymousUser object at 0x04CD3B30>>": "Object.author" must be a "ProfileUser" instance.

The author must be a ProfileUser instance as the error message says, because you declared the author field (of the Object model) as a ProfileUser.
In add_object method, obj.author needs to be a ProfileUser instance, therefore you should get that instance by looking up the user.
def add_object(request):
form = ObjectForm(request.POST or None)
if form.is_valid():
obj = form.save(commit=False)
obj.author = ProfileUser.objects.get(user=request.user)
obj.save()
return redirect('home')
context = {
'form': form
}
return render(request, "add_object.html", context)
If the current user doesn't always exist for the ProfileUser instance, you could use the get_or_create method for the author. Read more about that here

Related

Django save user and profile with signals

Im still learning Django and I am stuck at user registration / profile creation.
My goal
So, the purpose of this is to save the new user and at the same time save the profile of the new user with de data from the form. I use 2 forms u_form and p_form.
What I have done so far:
Created model Profile with OneToOneField to User
Created 2 forms for User (u_form) and Profile (p_form)
Created signals.py to create new Profile when new User is created
In the view I have create function with u_form.save()
Problem
This works, but the new Profile is completely empty.. When I put p_form.save() in my view it gives me this error:
NOT NULL constraint failed
The code
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
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
voorletter = models.CharField(max_length=10)
voorvoegsel = models.CharField(max_length=10)
achternaam = models.CharField(max_length=200)
depers = models.CharField(max_length=25)
depersoud = models.CharField(max_length=25)
telefoonnummer = models.CharField(max_length=25)
class Meta:
verbose_name = "Collega"
verbose_name_plural = "Collega's"
def __str__(self):
return self.depers
signals.py
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
views.py
from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from gebruikers.forms import UserRegisterForm, ProfileRegisterForm
def gebruiker_create(request):
if request.method == "POST":
u_form = UserRegisterForm(request.POST)
p_form = ProfileRegisterForm(request.POST)
if u_form.is_valid() and p_form.is_valid():
u_form.save()
messages.success(request, f'Account is aangemaakt.')
return redirect('login')
else:
u_form = UserRegisterForm()
p_form = ProfileRegisterForm()
context = {
'u_form': u_form,
'p_form': p_form
}
return render(request, 'users/register.html', context)
forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import Profile
class UserRegisterForm(UserCreationForm):
email = forms.EmailField(label = "Email")
password1 = forms.CharField(widget=forms.TextInput(attrs={'type':'password'}), label="Wachtwoord", help_text=None)
password2 = forms.CharField(widget=forms.TextInput(attrs={'type':'password'}), label="Wachtwoord herhalen", help_text=None)
class Meta:
model = User
fields= ['username', 'email', 'password1', 'password2']
class ProfileRegisterForm(forms.ModelForm):
voorletters = forms.CharField(label="Voorletters", max_length=10)
voorvoegsel = forms.CharField(label="Voorvoegsel", max_length=50)
achternaam = forms.CharField(label='Achternaam', max_length=100)
depers = forms.CharField(label='Depers', max_length=8)
depersoud = forms.CharField(label='Oude Depers', max_length=50)
telnummer = forms.CharField(label="Telefoonnummer", max_length=20)
class Meta:
model = Profile
fields = ['voorletters', 'voorvoegsel', 'achternaam', 'depers', 'depersoud', 'telnummer']
If you want Profile fields to be empty initially just add blank=True in every model fields except for user .
voorletter = models.CharField(max_length=10, blank=True)
.....
.....
.....
telefoonnummer = models.CharField(max_length=25, blank=True)
Then run makemigrations and migrate command to successfully make the changes in the database.
it will solve NOT NULL constraint failed error

How to select a OnetoOne field from a QuerySet in a view?

See all users (that don't have search_hidden enabled) view
#login_required
def users(request):
"""List all users page"""
t_users = User.objects.all()
users = t_users.usersettings.filter(search_hidden=False).select_related('user')
context = {'users': users}
return render(request, 'users/users.html', context)
UserSettings model
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 UserSettings(models.Model):
"""Stores the user's settings."""
user = models.OneToOneField(User, related_name='usersettings', on_delete=models.CASCADE)
public_profile = models.BooleanField(default=True)
search_hidden = models.BooleanField(default=False)
class Meta:
verbose_name_plural = 'usersettings'
def __str__(self):
return f"{self.user}'s settings"
#receiver(post_save, sender=User)
def create_user_usersettings(sender, instance, created, **kwargs):
if created:
UserSettings.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_usersettings(sender, instance, **kwargs):
instance.usersettings.save()
All users have a UserSettings model tied to them when their accounts are created. In my view, I want to select all users that have search_hidden disabled, however what I've tried doesn't work.The error 'QuerySet' object has no attribute 'usersettings' is displayed whenever the page is requested. I probably need to select each user and retrieve the settings, but I don't know how to do that in an efficient manner.
iliya commented that filtering using t_users.objects.filter(search_hidden=False) would return users where search_hidden is not true in their settings object.

Own data for everyuser in django

So I am building a to do app in Django. I have created databases for the users and todo items. But I have a problem, how can each user have its own data. Like every user should add their own data. It seems like there is no answer out there.
My models.py
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
My forms.py
class CreateUserForm(UserCreationForm):
class Meta:
model = User
fields = ['username','email','password1','password2']
So how can I connect those both. I have red that I have to use foreign key. But I really don't understand how I can do it
You specify a ForeignKey [Django-doc] in the Task model that refers to the user that constructed it:
# app/models.py
from django.db import models
from django.conf import settings
class Task(models.Model):
title = models.CharField(max_length=200)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.title
You can then make a ModelForm where you exclude the user. For example:
# app/forms.py
from django import forms
from app.models import Task
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ['user']
Then in the view we can "inject" the user in the instance we create, for example:
# app/views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
from app.forms import TaskForm
#login_required
def create_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('name-of-some-view')
else:
form = TaskForm()
return render(request, 'some_template.html', {'form': form})
Note: In case of a successful POST request, you should make a redirect
[Django-doc]
to implement the Post/Redirect/Get pattern [wiki].
This avoids that you make the same POST request when the user refreshes the
browser.

UNIQUE constraint failed: new__users_profile.user_id. Python Django

django.db.utils.IntegrityError UNIQUE constraint failed
sqlite3.IntegrityError: UNIQUE constraint failed: new__users_profile.user_id
The above exception was the direct cause of the following exception:
new__users_profile.user_id
Error occurs when I'm trying to register new user, login to an existing user and when I am trying to migrate. I've tried to delete all migrations and migrate once again but it didn't help
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
class Media(models.Model):
image_name = models.CharField(max_length=50)
image_description = models.CharField(max_length=80)
image_image = models.ImageField(upload_to='media', default='default.jpg')
views
from django.shortcuts import render, redirect
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from .forms import UserRegisterForm, MediaForm
from .models import Media
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
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 log in')
return redirect('login')
else:
form = UserRegisterForm()
return render(request, 'users/register.html', {'form': form})
#login_required
def profile(request):
if request.method == 'GET':
media_images = Media.objects.all()
context = {
'media_images':media_images,
}
return render(request, 'users/profile.html', context)
#login_required
def add_media(request):
if request.method == 'POST':
form = MediaForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('http://127.0.0.1:8000/')
else:
form = MediaForm()
return render(request, 'users/add_media.html', {'form':form})
forms.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
from .models import *
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
class MediaForm(forms.ModelForm):
class Meta:
model = Media
fields = ['image_name', 'image_description', 'image_image']
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
I think you need primary_key=True,
class Profile(models.Model):
user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE, null=True)
In class profile, add primary_key=True and remove null=True
user = models.OneToOneField(User,primary_key=True, on_delete=models.CASCADE)
I hope it will work!

IntegrityError NOT NULL constraint failed

I'm building a simple blog app using Django. I want to realize the function of adding a new blog using form. Some problems occurs.
Here is my models.py
from django.db import models
from django.utils import timezone
from django.template.defaultfilters import slugify
from django.contrib.auth.models import User
class Blog(models.Model):
title=models.CharField(max_length=60)
content=models.TextField()
author=models.ForeignKey('auth.User',on_delete=models.CASCADE,)
date=models.DateTimeField(default=timezone.now)
slug=models.SlugField(null=True,unique=True)
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Blog, self).save(*args, **kwargs)
def __str__(self):
return self.title
class UserProfile(models.Model):
user=models.OneToOneField(User)
website=models.URLField(blank=True)
def __str__(self):
return self.user.username
forms.py
from django.template.defaultfilters import slugify
from blog.models import UserProfile
from django.contrib.auth.models import User
class BlogForm(forms.ModelForm):
title=forms.CharField(max_length=60,
help_text="blog title")
content=forms.CharField(help_text="blog content")
author=forms.CharField(help_text="blog author")
date=forms.DateTimeField(help_text="blog date")
class Meta:
model=Blog
fields=('title',)
class UserForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput())
class Meta:
model=User
fields = ('username','email','password')
class UserProfileForm(forms.ModelForm):
class Meta:
model=UserProfile
fields=('website',)
the add_blog method in views.py
def add_blog(request):
form=BlogForm()
if request.method =='POST':
form=BlogForm(request.POST)
if form.is_valid():
form.save(commit=True)
return index(request)
else:
print(form.errors)
return render(request, 'add_blog.html',{'form':form})
When I want to add a new blog in my webpage, I can't input the record. It shows me
IntegrityError at /add_blog/
NOT NULL constraint failed: blog_blog.author_id
Could anybody help me fix this problem? Thanks a lot!
In your models, your Blog class requires:
Title
An author, of type auth.User
content
The first step, is to remove the author field from your form:
class BlogForm(forms.ModelForm):
title=forms.CharField(max_length=60,
help_text="blog title")
content=forms.CharField(help_text="blog content")
# author=forms.CharField(help_text="blog author")
date=forms.DateTimeField(help_text="blog date")
class Meta:
model=Blog
fields=('title','content','date')
Next, is to add the logged in user as the author in your view:
from django.shortcuts import redirect
from django.contrib.auth.decorators import login_required
# makes sure this view is called with a valid user
# https://docs.djangoproject.com/en/2.0/topics/auth/default/#the-login-required-decorator
#login_required
def add_blog(request):
form = BlogForm(request.POST or {})
if form.is_valid():
temp = form.save(commit=False)
temp.author = request.user # add the logged in user, as the
# author
temp.save()
return redirect('/')
return render(request, 'add_blog.html',{'form':form})
Another way to view this problem... Perhaps you can Try clearing your migration files , and re-run makemigrations to see if it catches anything off about your models. It may ask you for a default value for some of the fields; and this should ring a bell to assign null=True where appropriate. Personally this is quite a common integrity conflict for me (i'm new to the framework) especially when i've done many unplanned on the fly mods to models on the same db.

Categories

Resources