How to create instance of model during user registration process? Django - django

I am writing a simple event app in django. I have register and login process.
I have two models. Model creator has one OneToOneField with attribute User.
Event model has attribute creator as ForeignKey which contain specific User.
What is my problem? When I create new user, I want to create new instance of Creator model at the same time and when I log in as that user and create new event, I want to set value of creator in Event as this user.
How can I do it? models.py and views.py below:
models.py
class Event(models.Model):
SPORT = (
('Football', 'Football'),
('Volleyball', 'Volleyball'),
('Basketball', 'Basketball'),
('Futsal', 'Futsal'),
('Tennis', 'Tennis'),
('Handball', 'Handball'),
('Ice Hockey', 'Ice Hockey'),
('Paintball', 'Paintball')
)
creator = models.ForeignKey(Creator, null=True, on_delete=models.SET_NULL)
sport = models.CharField(max_length=20, null=True, choices=SPORT)
event_name = models.CharField(max_length=30)
event_date = models.DateTimeField(default=date.today())
end_event_date = models.DateTimeField(default=date.today())
current_members = models.IntegerField(default=1)
total_members = models.IntegerField(default=0)
event_location = models.CharField(max_length=50)
cost = models.FloatField(default=0, max_length=5)
description = models.CharField(max_length=300, blank=True)
def __str__(self):
return self.event_name
class Creator(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
views.py
#unauthenticated_user
def registerPage(request):
form = CreateUserForm()
if request.method == 'POST':
form = CreateUserForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, 'Account created successfully!')
return redirect('login')
context = {'form': form}
return render(request, 'events/register.html', context)

To create a new Creator at signup:
views.py
...
from django.contrib.auth import User
from .models import Creator
...
...
if form.is_valid():
new_user = form.save()
Creator.objects.create(user=new_user)
messages.success(request, 'Account created successfully!')
To add the creator to Event, you would get() the currently logged in user (request.user) from the Creator model, then pass that to the creator field when creating a new Event

Related

Autofill my author field with foreign key

I am trying to autofill my user foreign key in my note project with authentication in django. I tried, but it's not working and asking that owner is required field. Please, help! Thanks in an advance.
views.py
#login_required(login_url='login')
def index(request):
tasks = Task.objects.filter(owner=request.user)
form = TaskForm()
if request.method=='POST':
form = TaskForm(request.POST)
if form.is_valid():
instance = form.save(commit=False)
instance.owner = request.user
instance.save()
context = {
'tasks':tasks,
'form':form,
}
return render(request, 'list.html',context)
models.py
class Task(models.Model):
title = models.CharField(max_length=200)
completed = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
def __str__(self):
return self.title
Since you fill in the owner yourself, it makes no sense to specify the owner as a form field. You thus should exclude it, and let this be handled by the view. The form thus looks like:
class TaskForm(forms.ModelForm):
class Meta:
model = Task
exclude = ['owner']
If no ModelForm will need to specify the owner, you can mark the field as non-editable:
class Task(models.Model):
# …
owner = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
# …

Updating django form without prompting the user to enter their ID

So i'm working on job application portal.
the logic is as follows :
Applicant ---> Applies for ---> Job
Models are (Job, User, Application)
I used the User model from django and i extend it.
Now the dilemma is when i render the ApplicationForm, because i have to update the foreign key and i want it to be updated automatically.
Here is my code :
Models.py
class Job(models.Model):
owner = models.ForeignKey(User,related_name='job_owner',on_delete=models.CASCADE)
title = models.CharField(max_length=100)
#location
job_type = models.CharField(max_length=15,choices=JOB_TYPE)
description= models.TextField(max_length=1000)
published_at = models.DateTimeField(auto_now=True)
vacancy = models.IntegerField(default=1)
salary = models.IntegerField(default=0)
experience = models.IntegerField(default=1)
category = models.ForeignKey('Category',on_delete=models.CASCADE)
icon = models.ImageField(upload_to ='job_icons/',default='job_icons/job.png')
slug = models.SlugField(blank = True,null=True)
class Application(models.Model):
job = models.ForeignKey(Job, related_name="job_applied",on_delete=models.CASCADE)
applicant = models.ForeignKey(User,related_name='job_applicant',on_delete=models.CASCADE)
first_name= models.CharField(max_length=40)
last_name= models.CharField(max_length=40)
email = models.EmailField(max_length=60)
website = models.URLField()
cv = models.FileField(upload_to='application/')
coverletter = models.TextField(max_length=550)
application_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.last_name+"\t"+self.first_name
Forms.py
class JobApplication(ModelForm):
class Meta:
model = Application
fields = ['first_name', 'last_name','email', 'website','cv','coverletter']
vews.py
def job_detail(request,slug):
job_specific = Job.objects.get(slug=slug)
form = JobApplication(instance=request.user)
if request.method == 'POST':
form = JobApplication(request.POST,request.FILES)
if form.is_valid():
my_form = form.save(commit=False)
my_form.job = job_specific
Application.applicant.user = request.user
Application.job = job_specific
my_form.save()
context ={'job_specific':job_specific, 'form':form,}
return render(request,"job/job_details.html",context)
So once the user submit their application, i wanted to updated the fields that are "foreign key" without prompting the user.
I do not know how to arrange this in the views.py or if it's even possible this way?
thanks to everyone in advance
So i solved the problem, it was really simple solution:
my_form = form.save(commit=False)
my_form.job = job_specific
my_form.applicant = request.user

Django Unique Constraint doesn't Work on creating unique project titles for each user

So I have this project where I have several supervisors that can create projects. I want that for each supervisor they can't make a project with the same title. I tried to use UniqueConstraint but now it's not working. Supervisors can still create a project with the same title. Note: Project's supervisor is automatically assigned to the project creator.
models.py
class Project(models.Model):
title = models.CharField(max_length=100)
due_date = models.DateField()
due_time = models.TimeField()
supervisor = models.ForeignKey(User, default=None, on_delete=models.SET_DEFAULT)
class Meta:
constraints = [models.UniqueConstraint(fields=['title', 'supervisor'], name="unique title")]
verbose_name = "Project"
def __str__(self):
return str(self.title) + "-" + str(self.supervisor)
forms.py
class CreateProjects(forms.ModelForm):
class Meta:
model = models.Project
fields = ['title', 'due_date', 'due_time']
widgets = {
'due_date': DateInput()
}
views.py
#login_required(login_url="/signin")
def create_project(response):
if response.user.is_staff:
if response.method == 'POST':
form = forms.CreateProjects(response.POST, response.FILES)
if form.is_valid():
# save project to db
instance = form.save(commit=False)
instance.supervisor = response.user
print(instance.supervisor)
instance.save()
return redirect('/dashboard')
else:
form = forms.CreateProjects(initial={'supervisor': response.user})
ctx = {'form': form, 'FullName': response.user.get_full_name}
else:
form = "Only Teachers can create projects"
ctx = {'form': form, 'FullName': response.user.get_full_name}
return render(response, "create_project.html", ctx)
The simplest way is to define unique on the field.
class Project(models.Model):
title = models.CharField(max_length=100,unique=True)
repeat on any field(s) you want it to be unique.

how to update a extended Django User model?

I have created the user authentication system which includes both the default User model and an extended User model. They are as below:
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
Photo = models.ImageField(upload_to='documents/%Y/%m/%d/', null=True)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
dob = models.DateField(max_length=20, null=True)
country = models.CharField(max_length=100, null=True)
State = models.CharField(max_length=100, null=True)
District = models.CharField(max_length=100, null=True)
phone = models.CharField(max_length=10, null=True)
def get_absolute_url(self):
return reverse('profile', kwargs={'id': self.id})
forms.py
class UserProfileForm(forms.ModelForm):
Photo = forms.ImageField( max_length=100)
dob = forms.DateField(widget=forms.TextInput(attrs={'type': 'date'}))
country = forms.CharField(max_length=100)
State = forms.CharField(max_length=100)
District = forms.CharField(max_length=100)
phone = forms.CharField(max_length=10)
class Meta:
model = UserProfile
fields = ('Photo', 'dob', 'country', 'State', 'District', 'phone')
With the help of the above model and form, I am able to create user, and enter values for those custom model fields and see the user profile. So far so good.
However, I am facing issues while I update those custom fields. I have used the Django's in-built modules to update the default User fields(email). But I am not able to find a way to update those custom fields('dob', 'country', 'State', 'District', 'phone'). Below is the method from views.
views.py
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user) # default User profile update
obj = UserProfile.objects.get(id=request.user.id)
form1 = UserProfileForm(request.POST or None, instance=obj) # custom fields update.
if form.is_valid() and form1.is_valid():
obj.Photo = form1.cleaned_data['Photo']
obj.dob = form1.cleaned_data['dob']
obj.country = form1.cleaned_data['country']
obj.State = form1.cleaned_data['State']
obj.District = form1.cleaned_data['District']
obj.phone = form1.cleaned_data['phone']
form.save()
form1.save()
messages.success(request, f'updated successfully')
return redirect('/profile1')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileUpdateForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form, 'form1': form1})
I have an update button on my profile page, on clicking I could only see the "email" field with pre-populated data to update(I can update this default field successfully).
I have seen other stackoverflow posts, but they are not helping.
I am not able to figure out the mistakes.
Please help
Thank you,
I think the problem is in this line
obj = UserProfile.objects.get(id=request.user.id)
here left id is id from UserProfile model. so it will be something like this
obj = UserProfile.objects.get(user__id=request.user.id)

How to use a submit a one-to-many form

I have a list of employees who work at a site. Each site is owned by a User (using Django's standard user model).
I want to create a form that adds an employee and automatically links them to a site dependent on who the authenticated user is:
models.py:
class Employee(models.Model):
site = models.ForeignKey(Site, null=True)
employee_name = models.CharField(default='name', max_length=128, blank=False, null=False)
class Site(models.Model):
user = models.ForeignKey(User)
site_name = models.CharField(max_length=128, blank=False, null=False)
views.py:
site_profile = Site.objects.get(user=request.user)
if request.method == "POST":
form = EmployeeAddForm( request.POST )
if form.is_valid():
obj = form.save(commit=False)
obj.site = site_profile
obj.save()
return redirect('dashboard_home')
form = EmployeeAddForm()
return render(request, "dashboard/employees.html", {'form': form })
forms.py:
class EmployeeAddForm(forms.ModelForm):
class Meta:
model = Employee
fields = ( 'employee_name')
This code will add the employee to the database, but in django admin, list_display = 'site' results in Site object not the actual site name. It does not appear that the employee is linked to the site.
If I use obj.site = site_profile.id (adding .id), I get the error Cannot assign "1": "Employee.site" must be a "Site" instance.
Found the error: the above code is correct, I simply had a tab ordering error in my Site modeL
class Site(models.Model):
...
def __str__(self):
return self.site_name
def should have been inserted 1 tab inwards.