Saving django OneToOneField current user with modelform - python

I have spent a good few hours looking over the documentation and on here as well and i still can't find an answer to my issue. please if you know of one direct me to it. otherwise please look at the following issue. I receive a KeyError when trying to register a user as a host for an open source homestay project im working on: https://github.com/castaway2000/OpenStay this is yet to be pushed to the master branch. i have tried setattr() and instance as well. something just isn't clicking with me on this one.
models.py
class HostRegistration(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
city = models.CharField(max_length=100)
state = models.CharField(max_length=30)
zipcode = models.CharField(max_length=15)
country = models.CharField(max_length=30)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user
forms.py
class HostForm(forms.ModelForm):
#no need for charfields here because we refrence the model with the fields
class Meta:
model = HostRegistration
fields = ['address', 'city', 'state', 'zipcode', 'country']
views.py - the problem starts here XD
# become a host
def host_register(request):
user = request.user
if user.is_authenticated:
if request.method == 'POST':
host_form = HostForm(data=request.POST)
if host_form.is_valid():
host_form.fields['user'].instance = user.id # this is where its failing.
host = host_form.save(commit=False)
print host
host.save()
return HttpResponseRedirect('/edit_userpage/')
else:
print host_form.errors
else:
return HttpResponseRedirect('/')
guide_form = HostForm()
context = {'guide_form': guide_form}
return render(request, 'users/host.html', context)
please let me know how to access the model object 'user' in my views and save the currently logged in user as a reference to it with the modelform. it would be great help.

i found the answer.
i changed my model.py to
class HostRegistration(models.Model):
# user is the changed variable
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
address = models.CharField(max_length=200)
city = models.CharField(max_length=100)
state = models.CharField(max_length=30)
zipcode = models.CharField(max_length=15)
country = models.CharField(max_length=30)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user
and i updated my views.py to:
def host_register(request):
user = request.user
if user.is_authenticated:
if request.method == 'POST':
host_form = HostForm(data=request.POST)
if host_form.is_valid():
instance = host_form.save(commit=False) # this is the trick.
instance.user = request.user # and this to get the currently logged in user
instance.save() # to commit the new info
return HttpResponseRedirect('/edit_userpage/')
else:
print host_form.errors
else:
return HttpResponseRedirect('/')
guide_form = HostForm()
context = {'guide_form': guide_form}
return render(request, 'users/host.html', context)

Does it work if you do host_form.cleaned_data.get("user") instead of host_form.fields['user'].instance?

Related

How to assign a user to an employee in Django

I am a beginner in django and trying to create a web application for my task.
I am trying to assign a user to every to employee.
The idea is that user(in my class Employee) brings a list of user options that have not yet been assigned to the new employee to be registered.
My model:
class Employee():
name = models.CharField(max_length=100)
job = models.CharField(max_length=30)
user = models.OneToOneField(User,on_delete=models.CASCADE)
def __str__(self):
return'{}'.format(self.name,self.job,self.user)
My form:
class EmployeeForm(forms.ModelForm):
user= forms.ModelChoiceField(queryset=User.objects.filter(id=Employee.user))
class Meta:
model = Employee
fields = [
'name',
'job',
'user'
]
My view:
def register_employee(request):
if request.method == 'POST':
form = EmployeeForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
return redirect('list_employee')
else:
form = EmployeeForm()
return render(request, 'employee/employee_form.html',{'form': form})
I guess your code to be modified as,
class EmployeeForm(forms.ModelForm):
user= forms.ModelChoiceField(queryset=User.objects.filter(employee=None))
Please try the above.

I'm trying to link the post created by the specific user account in Django

models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Customer(models.Model):
user = models.OneToOneField(User,null=True,blank=True,on_delete=models.CASCADE)
name = models.CharField(max_length=200,null=True)
## phone = models.IntegerField(null=True)
email = models.EmailField(max_length=250)
profile_pic = models.ImageField(default='default_pic.png',null=True,blank=True)
date_created = models.DateTimeField(auto_now_add=True,null=True)
def __str__(self):
return self.name
class Task(models.Model):
customer = models.ForeignKey(Customer,on_delete=models.CASCADE,null=True)
title = models.CharField(max_length=200)
description = models.TextField(null=True,blank=True)
complete = models.BooleanField(default=False)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
class Meta:
ordering = ['complete']
views.py
#login_required(login_url='login')
def taskCreate(request):
if request.method == 'POST':
form = TaskForm(request.POST or None)
if form.is_valid():
form.instance.customer = request.user
form.save()
return redirect('tasks')
else:
form = TaskForm()
context = {'form':form}
return render(request,'todo_list/task_create.html',context)
Error:
ValueError at /create_task/
Cannot assign "<SimpleLazyObject: <User: Dominic>>": "Task.customer" must be a "Customer" instance.
I am trying to link the username in the user account to be shown on the model Task.customer that represents the post is created by that user. May I ask any methods could be done in order to specify the customer in the model Task? Also I do not understand the error message in detail because my admin panel already has the current username in the Customer model. However if I used request.user.customer the username does not show up instead returning None so how to solve this issue?
I don't know form.instance.customer = request.user
but I think I understood what you meant and the below code does the same thing
#login_required(login_url='login')
def taskCreate(request):
if request.method == 'POST':
form = TaskForm(request.POST or None)
if form.is_valid():
t = form.save(commit = False)
t.customer = request.user # assigning current user to created task.customer
t.save()
return redirect('tasks')
else:
form = TaskForm()
context = {'form':form}
return render(request,'todo_list/task_create.html',context)
if the code is still not working then try changing your line
customer = models.ForeignKey(Customer,on_delete=models.CASCADE,null=True) to
customer = models.ForeignKey(User,on_delete=models.CASCADE,null=True) in your models.py
The error comes from the following snippet
form.instance.customer = request.user
request.user is not a Customer instance, you can try extracting the information from request.user and create a Customer object from it and then assign it back

How to change a field in parent class while creating chiled class fields in forms.py and views.py?

I'm was creating ModelForm I try to make change the parent class while saving child class fields to the database, in the views.py I made but it didn't save to the database.
here is my model.py
class Table(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
book = models.BooleanField(default=False)
class People(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
taple = models.OneToOneField(Table, on_delete=models.CASCADE, null=True, blank=True)
#receiver(post_save, sender=User)
def update_people_profile(sender, instance, created, **kwargs):
try:
instance.people.save()
except ObjectDoesNotExist:
People.objects.create(user=instance)
Class People is the child class and Table is the parent class so I'm using People class for making forms. here is my forms.py
class Booking(forms.ModelForm):
class Meta:
model = People
fields = [
'taple',
]
So I want to make True book field in Table class and save it to the database when saving Booking form. here is my views.py
def booking(request):
if request.method == 'POST':
try:
people_instance = People.objects.get(user=request.user)
except Table.DoesNotExist:
people_instance = People(user=request.user)
form = Booking(request.POST, instance=people_instance)
if form.is_valid():
user = form.save(commit=False)
user.taple.booking = True
user.refresh_from_db()
user.user = request.user
user.taple = form.cleaned_data.get('taple')
user.save()
print(user.taple.booking, user.taple.id)
return redirect('booked')
else:
form = Booking()
return render(request, 'main/booking.html', {'form': form})
Any Idea?
What I understand from the snippets is that you want to be able to record if a table is booked (book Boolean Field in your Table model and if so by whom, which is the object of your People model.
If my understanding is correct, then I don't think you really need a join table (People model). Instead, I would change your model as follow:
class Table(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
booked_by = models.OneToOneField(User, null=True, on_delete=models.SET_NULL, related_name='table_booked')
#property
def is_booked(self):
# This returns True if booked_by is set, False otherwise
return self.booked_by_id is not None
This way you don't need the People model. The property decorator will allow you to use is_booked as a calculated field.
Also, note the related name which will be used in the form:
class BookingForm(forms.ModelForm):
table_booked = forms.ModelChoiceField(queryset=Table.objects.filter(booked_by__isnull=True))
class Meta:
model = User
fields = ['table_booked',]
In the form, you will see that we define a custom queryset for table_booked. THe aim is to filter for free tables only.
Then you can hopefully simplify as well your view as follow:
Update:
As table_booked is a reverse foreign key, we actually need to save the table object which contains the relation. Here is the modified view:
#login_required
def booking(request):
form = BookingForm(request.POST or None, instance=request.user)
if form.is_valid():
user = form.save(commit=False)
tbl = form.cleaned_data['table_booked']
tbl.booked_by = request.user
tbl.save()
user.save()
print(request.user.table_booked.id, request.user.table_booked.is_booked)
return redirect('/')
return render(request, 'booking/booking.html', {'form': form})
Note: I haven't tested the code so there could be some typos but that should help you getting started.

Related Field got invalid lookup: icontains

I am trying to include a search field inside my home page. It works for some of the module field. My problem is when I use a ForeignKey field (correct me please if I am wrong).
models.py
class Location(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
my_location = models.CharField(max_length=120, choices=LOCATION_CHOICES)
update_date = models.DateField(auto_now=True, null=True)
def __str__(self):
return self.my_location
class UserProfile(models.Model):
user = models.ForeignKey(User)
# The additional attributes we wish to include.
user_base = models.CharField(max_length=120, choices=LOCATION_CHOICES)
user_position = models.CharField(max_length=120)
user_phone = models.PositiveIntegerField()
def __unicode__(self):
return self.user.username
views.py
def search_by_location(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
locations = Location.objects.filter(my_location__icontains=q).order_by('-update_date')
else:
locations = Location.objects.order_by('-update_date')
context = {'locations': locations}
return render(request, 'index.html', context)
My problem is if I use user inside the filter query instead of my_location I receive the error:
Related Field got invalid lookup: icontains
Please any advice on how to troubleshoot or any documentation I can read.
You can use icontains lookup on text fields. user is related (integer) field. Instead of user use user__username.
locations = Location.objects.filter(user__username__icontains=q)
class SearchView(ListView):
model = Profile
template_name = 'blog/search_results.html'
context_object_name = 'all_search_results'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user_name = self.request.GET.get('search', '')
context['all_search_results'] = Profile.objects.filter(user__username__icontains=user_name )
return context
here is another example on how to filter objects. if searching for a user, remember to user user_username__icontains=user_name
also remember that if you use Profile your'll get a different id than if you use User

how to assign current logined user to a models object in django

i have a user , who will create a company profile.The user is created by the django's django.contrib.auth.models. so the problem is to assign the currently logined user to the company profile's user.
my models.py is:
class Company_Profile(models.Model):
user = models.ForeignKey(User)
logo = models.ImageField(_('Company Logo'), upload_to='image', null=True, blank=True)
address = models.TextField(_('Contact Address'), max_length=50)
phone_no = models.IntegerField(_('Contact No'), max_length=12)
my forms.py is:
class Company_Prof(forms.ModelForm):
class Meta:
model = Company_Profile
fields = ('logo','address','phone_no')
my view for company profile is:
#login_required()
def company_prof(request):
if request.method == 'POST':
comp_prof = Company_Prof(request.POST or None)
comp_prof.user = User.objects.get(username=request.user)
if comp_prof.is_valid():
save_prof = comp_prof.save(commit=False)
save_prof.save()
messages.success(request, 'Thank you for Registration')
return HttpResponseRedirect('company/'+str(save_prof.id))
else:
comp_prof =Company_Prof()
variables = RequestContext(request, {
'comp_form': Company_Prof()})
return render_to_response("comp_profile.html",
locals(),
context_instance = RequestContext(request))
please help me..
comp_prof.user = User.objects.get(username=request.user)
Incorrect. request.user is already a User.
comp_prof.user = request.user
Two things: One, saving an object with commit=False will create the object, but will not COMMIT it to the database until save with commit =True is called. Therefore, your object is available for modification between these two lines.
Two: The current user object is available in your request as 'user'. Calling request.user will return the user object.
So for your case, you need to assign the user object before calling save again, like this:
save_prof = comp_prof.save(commit=False)
save_prof.user = request.user
save_prof.save()

Categories

Resources