OnetoOneField connection , can't access the related information , django - python

class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='oser')
picture = models.ImageField(upload_to='profile_images', blank=True)
So, I've added picture to user profile , it works good , but I can't access picture to show it in user profile
view.py:
def profile(request):
if request.user.is_authenticated():
user = User.objects.get_by_natural_key(request.user.get_username())
t = loader.get_template("profile.html")
c = Context({'user2': user, })
return HttpResponse(t.render(c))
else:
raise Http404
What I've found in django docs
class Employee(models.Model):
user = models.OneToOneField(User)
department = models.CharField(max_length=100)
u = User.objects.get(username='fsmith')
freds_department = u.employee.department
However, this doesn't work for me , I just can't get UserProfile.picture
u = User.objects.get(username= request.user.get_username())
s = u.UserProfile.picture
What I'm doing wrong?

You should use "related name", which specified in foreign key field, to access user profile, not class name:
s = u.oser.picture
By default "related_name" is the same as related model class name, but in lowercase. You specified related_name="oser".

Related

Django Model Not Saving All Data From Form

I currently have a Django form that saves data from a questionnaire against a user, where a user is stored as a Foreign Key from the Person model. I can successfully find the person from the Person class using get_object_or_404(), but when I try to save(commit=True), the data is not being saved in the database. See below for my code:
# models.py
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=100)
email = models.EmailField(max_length=254, primary_key=True)
tel_number = models.CharField(max_length=13, blank=True)
referral_code = models.UUIDField()
class Meta:
verbose_name_plural = 'People'
def __str__(self):
return str(self.referral_code)
class Questionnaire(models.Model):
user = models.ForeignKey(Person, related_name='questionnaire_person', on_delete=models.CASCADE)
... and some questionnaire questions here (CharFields and TextFields) ...
# views.py
def index_questionnaire(request):
template = 'questionnaire.html'
# load blank instance of template
questionnaire = UserQuestionnaire()
context = {
"questionnaire": questionnaire
}
# if user has submitted something, check form is valid
if request.method == 'POST':
answers = UserQuestionnaire(data=request.POST)
if answers.is_valid():
# submission is genuine so save as new entry to database
# get user's unique referral ID from URL
user_referral_id = request.GET.get('user')
# check legit person
try:
answers.save(commit=False)
answers.person = get_object_or_404(Person, referral_code=user_referral_id)
print('user found: {}'.format(answers.person))
answers.save(commit=True)
print('Questionnaire saved')
except:
print("user not found")
return render(
request,
template,
context
)
#forms.py
class UserQuestionnaire(forms.ModelForm):
class Meta:
model = Questionnaire
fields = (
'answers_1',
'free_text_1',
'answers_2',
'answers_3',
'answers_4',
'answers_5',
'answers_6'
)
widgets = {
'answers_2' : forms.RadioSelect(),
'answers_3' : forms.RadioSelect(),
'answers_4' : forms.RadioSelect(),
'answers_5' : forms.RadioSelect(),
}
So at the moment I'm drawing the user parameter from the URL, which is uuid.uuid4(). The print statement in the "try: except" bit successfully prints out the user UUID as expected, yet when submitted it doesn't save correctly. For further info, I am using the MultiSelectField() for one of the questionnaire questions.
If anyone has any suggestions as to why this might be, that would be amazing!
That is because asnwers.save(commit=False) creates another new object.
Do something like
f = answer.save(commit=false)
f.person = get_object_or_404(Person, referral_code=user_referral_id)
f.save()
No need to do f.save(commit=True) since the True is default.
for more info check docs:
docs.djangoproject.com/en/3.1/topics/forms/modelforms/

UNIQUE constraint failed: rango_category.name

Hi im following the tango with django tutorial.. I've searched for a solution to this but nothing!
the error:
IntegrityError at /rango/add_category/
UNIQUE constraint failed: rango_category.name
my model:
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
def __unicode__(self):
return self.name
class Page(models.Model):
category = models.ForeignKey(Category) #ForeignKey denotes a relationship between page and category
title = models.CharField(max_length=128)
url = models.URLField()
views = models.IntegerField(default=0)
def __unicode__(self):
return self.title
my add_category view:
def add_category(request):
# Get the context from the request.
context = RequestContext(request)
# A HTTP POST?
if request.method == 'POST':
form = CategoryForm(request.POST)
#Have we been provided with a valid form?
if form.is_valid():
#save the new category to the database
form.save(commit=True)
# Now call the index() view.
# The user will be shown the Homepage.
return index(request)
else:
# The supplied form contained errors - just print them to the terminal
print (form.errors)
else:
form = CategoryForm()
# Bad form (or form details), no form supplied...
# Render the form with error message(if any).
return render_to_response('rango/add_category.html', {'form':form}, context)
my forms:
from django import forms
from rango.models import Page, Category
class CategoryForm(forms.ModelForm):
names = forms.CharField(max_length=128, help_text="please enter the category name.")
views = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
likes = forms.IntegerField(widget=forms.HiddenInput(), initial=0)
#an inline class to to provide additional information on the form
class Meta:
# provide an association between the Modelform and a model
model = Category
fields = ('views', 'likes')
class PageForm(forms.ModelForm):
title = forms.CharField(max_length=128, help_text="Please enter the title of the page")
url = forms.URLField(max_length=200, help_text="Please enter the url of the page")
views = forms.IntegerField(widget=forms.HiddenInput(),initial=0)
class Meta:
# Provide an association between the ModelForm and a model
model = Page
#what fields do we want to include in our form
# this way we dont need every field in the model present
# Some fields may allow NULL values, so we may not want to include them...
# Here we are hiding.
fields = ('title', 'url', 'views')
'name' field is missing in CategoryForm's Meta 'fields'. Since Category::name is a unique field and default is not possible, any attempt to save will fail.
If the model does not allow the missing fields to be empty, and does
not provide a default value (not possible for unique) for the missing fields, any attempt to save() a ModelForm with missing fields will fail.

Saving django OneToOneField current user with modelform

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?

Django - Creating two user types, where one type can be both

We're required to have two separate forms for two different types of users. Call them Client and Provider. Client would be the parent, base user, while Provider is a sort of extension. At any point a Client could become a Provider as well, while still maintaining status and information as a Client. So a Provider has both permissions as a Client and as a Provider.
I'm new to Django. All we're trying to do is register either user type, but have a one to one relation between Provider and Client tables if a user registers as a Provider straight away.
The issue we're having is in the adapter, we think. A provider registers fine, but ends up in the users_user table with no entry in the generated users_provider table. Is it the way we're trying to save and relate these two entities in the database, or something else?
We're trying to utilize allauth for authentication and registration.
Our code:
models.py:
class User(AbstractUser):
name = models.CharField(_('Name of User'), blank=True, max_length=255)
def __str__(self):
return self.username
def get_absolute_url(self):
return reverse('users:detail', kwargs={'username': self.username})
SEX = (
("M","MALE"),
("F","FEMALE"),
)
birthdate = models.DateField(_('Birth Date'), default=django.utils.timezone.now, blank=False)
sex = models.CharField(_('Sex'), choices=SEX, max_length=1, default="M")
isProvider = models.BooleanField(_('Provider'), default=False)
#Using User, not models.Model
class Provider(User):
HAS_BUSINESS = (
('YES','YES'),
('NO','NO'),
)
#Resolving asociation 1:1 to User
#NOTE: AUTH_USER_MODEL = users.User in setting
owner = models.OneToOneField(settings.AUTH_USER_MODEL)
has_business = models.CharField(_('Do you have your own business?'),max_length=2, choices=HAS_BUSINESS, default='NO')
isProvider = True
our forms.py
class ProviderForm(SignupForm,ModelForm):
name = forms.CharField(label='Name', strip=True, max_length=50)
lastname = forms.CharField(label='Last Name', strip=True, max_length=50)
Provider.isProvider = True
class Meta:
model = Provider
fields = '__all__'
exclude = GENERAL_EXCLUSIONS + [
'owner',
]
class ClientForm(SignupForm,ModelForm):
name = forms.CharField(label='Name', strip=True, max_length=50)
lastname = forms.CharField(label='Last Name', strip=True, max_length=50)
class Meta:
model = User
fields = "__all__"
exclude = GENERAL_EXCLUSIONS
def is_active(self):
return False
def __init__(self, *args, **kwargs):
super(ClientForm, self).__init__(*args, **kwargs)
views.py:
class ProviderRegisterView(SignupView):
template_name = 'account/form_provider.html'
form_class = ProviderForm
redirect_field_name = 'next'
view_name = 'registerprovider'
success_url = None
def get_context_data(self, **kwargs):
ret = super(ProviderRegisterView, self).get_context_data(**kwargs)
ret.update(self.kwargs)
return ret
registerprovider = ProviderRegisterView.as_view()
#View para el formulario de registro de usuarios clientes
class ClientRegisterView(SignupView):
template_name = 'account/form_client.html'
form_class = ClientForm
redirect_field_name = 'next'
view_name = 'registerclient'
success_url = None
def get_context_data(self, **kwargs):
ret = super(ClienteRegisterView, self).get_context_data(**kwargs)
ret.update(self.kwargs)
return ret
registerclient = ClienteRegisterView.as_view()
finally, our adapter.py:
#Per allauth documentation, settings changed:
#ACCOUNT_ADAPTER = 'projectname.users.adapters.RegisterUserAdapter'
class RegisterUserAdapter(DefaultAccountAdapter):
def save_user(self, request, user, form, commit=True):
data = form.cleaned_data
user.first_name = data['name']
user.last_name = data['lastname']
#Saving Client info
user.sex = data['sex']
user.birthdate = data['birthdate']
#Normal allauth saves
user.username = data['username']
user.email = data['email']
if user.isProvider:
p = Provider()
p.owner = user
p.has_business = data['has_business']
if 'password1' in data:
user.set_password(data['password1'])
else:
user.set_unusable_password()
self.populate_username(request, user)
if commit:
#Save user
user.save()
#If it's also a Provider, save the Provider
if user.isProvider:
p.save()
return user
Any help or tips would be greatly appreciated. If I left something out, please let me know. I'm not sure if the problem is in the model itself, the way we represent the form, or the adapter. The way it stands, it doesn't matter what form we use, it's always saved as the base User table (our Client) and the Provider table never gets information saved to it.
With Django's new custom user model, only one user model can be set as settings.AUTH_USER_MODEL. In your example, you can set this to your User model.
Then for the optional provider data, create a separate model that is referenced by OneToOneField from your User model.
class User(AbstractUser):
...
provider = models.OneToOneField(Provider, null=True)
class Provider(models.Model):
...
This is the easiest way to work with multiple user types in Django, given the AUTH_USER_MODEL constraint.
Also, it's best to only subclass abstract models, otherwise you get multitable inheritance which results in hidden implied JOINs, degrading performance.
Finally, you can create the Provider object in your custom form's form.is_valid() method and assign user.provider = provider.

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

Categories

Resources