I've have the following forms:
class UpdateProfile(forms.ModelForm):
username = forms.CharField(required=True)
email = forms.EmailField(required=True)
first_name = forms.CharField(required=True)
last_name = forms.CharField(required=True)
class Meta:
model = User
fields = ('username', 'email', 'first_name', 'last_name')
def clean_email(self):
username = self.cleaned_data.get('username')
email = self.cleaned_data.get('email')
if email and User.objects.filter(email=email).exclude(username=username).count():
raise forms.ValidationError('This email address is already in use. Please supply a different email address.')
return email
class UserDetailForm (forms.ModelForm):
linked_user = forms.CharField (required = True)
linked_password = forms.CharField (required = True, widget = forms.PasswordInput())
connections = forms.IntegerField (required = True)
class Meta:
model = User_detail
fields = ('linked_user','linked_password','connections')
I'm trying to save them at the same time if both valid using:
if request.method == 'POST':
form = UpdateProfile(request.POST, instance=request.user)
linked_form = UserDetailForm(request.POST, instance=request.user)
if all((form.is_valid(),linked_form.is_valid())):
user = form.save()
linked = linked_form.save(commit=False)
linked.user = user
linked.save()
msg = "Profile Updated"
else:
return error(request)
This is the User_detail model:
class User_detail (models.Model):
user = models.OneToOneField (
User,
on_delete = models.CASCADE
)
linked_user = models.CharField (
verbose_name = 'LinkedIn Username',
max_length = 50,
)
linked_password = models.CharField (
max_length = 50,
verbose_name = 'LinkedIn Password',
)
connections = models.IntegerField (
verbose_name = 'Connections per day',
default = 24,
)
def __unicode__(self):
return u'%s' % (self.user.first_name + ' ' + self.user.last_name)
The first form is being saved, the second isn't and I don't understand what I'm missing
Help much appreciated.
The problem is in linked_form = UserDetailForm(request.POST, instance=request.user). request.user is not an instance of model User_detail.
What is happening is that, django is trying to find the instance in the model and not finding any. You need to provide a valid User_detail instance so that django can update that instance.
Reference: save() method
Related
i crated a model name address and connected with user by foreign key so a user can have multiple address but it is not saving i want form to take that user id to save but i don't how to do that
here is my models.py
class Address(models.Model):
phoneNumberRegex = RegexValidator(regex = r"^\d{10,10}$")
pincodeRegex = RegexValidator(regex = r"^\d{6,6}$")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='address')
reciever_name = models.CharField(max_length=200, blank=False)
phone_no = models.CharField(validators = [phoneNumberRegex], max_length = 10, blank=False)
alt_phone_no = models.CharField(validators = [phoneNumberRegex], max_length = 10, blank=True)
state = models.CharField(max_length=50, choices=state_choice, blank=False)
pincode = models.CharField(validators = [pincodeRegex], max_length = 6, blank=False)
eighteen = models.CharField(blank=False, choices=eighteen_choice, default='Yes', max_length=4 )
city = models.CharField(max_length=100, blank=False)
address = models.CharField(max_length=500, blank=False)
locality = models.CharField(max_length=300, blank=True)
joined_date = models.DateTimeField(default=timezone.now,editable=False)
update_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user.username
my views.py
#login_required
def add_address(request, username):
if request.method == 'POST':
form = Addressform(request.POST)
if form.is_valid():
form.save()
return redirect('accounts:home')
else:
form = Addressform()
return render(request, 'add_address.html', {'form': form})
my form.py
class Addressform(forms.ModelForm):
class Meta:
model = Address
fields = '__all__'
exclude = ['user', 'joined_date', 'updated_at']
labels = {
'reciever_name':'Reciever Name',
'phone_no':'Phone No',
'alt_phone_no':'Alternate Phone No',
'state':'State/Union Territory',
'pincode':'Area Pincode',
'eighteen':'Is reciever is 18+',
'city':'City',
'address':'Address',
'locality':'Locality',
}
widgets = {
'eighteen': forms.RadioSelect()
}
what i want is in user field it take that user who his login automatically but i don't understand how i can achieve that
since you are excluding the user field from the form, it gets a null value on the post request. With a foreign key you cannot have a null field in the database. You have 2 options:
1) Add the request user
#login_required
def add_address(request, username):
if request.method == 'POST':
form = Addressform(request.POST)
if form.is_valid():
form = form.save(commit=False)
form.user = request.user
form.save(commit=True)
return redirect('accounts:home')
else:
form = Addressform()
return render(request, 'add_address.html', {'form': form})
This will add the primary key of the user who is submitting the form as the foreign key of the address and hence associate the user with the address.
2) Allow user to select the user to associate with the address (not suggested)
The alternative method is to allow the user to select the user you want to associate with the address but it is not suggested as any user can associate any user with a particular address.
class Addressform(forms.ModelForm):
class Meta:
model = Address
fields = '__all__'
exclude = ['joined_date', 'updated_at']
labels = {
'reciever_name':'Reciever Name',
'phone_no':'Phone No',
'alt_phone_no':'Alternate Phone No',
'state':'State/Union Territory',
'pincode':'Area Pincode',
'eighteen':'Is reciever is 18+',
'city':'City',
'address':'Address',
'locality':'Locality',
}
widgets = {
'eighteen': forms.RadioSelect()
}
I want to update user model in a views.py. Is there a way to do that? What I want to do is minus user point in views.py and update into models without a form. but it gave me " 'int' object has no attribute 'save'"
views.py
def buy_item(request, item_name):
item = ShopItem.objects.get(item_name=item_name)
price = item.item_price
user = request.user
user_point = user.point
if user_point >= price:
user_point = user_point - price
point_left = user_point
point_left.save()
msg = messages.success(request, 'You bought item!')
return redirect('/shop', msg)
else:
msg = messages.success(request, 'You do not have enough point')
context = ({
'point': user_point,
'item': item,
'form': form
})
return render(request, 'item.html', context)
item models.py
class ShopItem(models.Model):
item_name = models.CharField(max_length=16)
item_image = models.ImageField(upload_to='media_items')
item_description = models.CharField(max_length=255)
item_command = models.CharField(max_length=255)
item_price = models.IntegerField(default=0)
def __str__(self):
return self.item_name
def snippet(self):
return self.item_description[:45]
user models.py
class UserProfile(AbstractUser):
username = models.CharField(max_length=16, unique=True)
email = models.EmailField(default='', unique=True)
phone = models.CharField(max_length=10)
point = models.IntegerField(default=0)
password1 = models.CharField(max_length=255)
password2 = models.CharField(max_length=255)
USERNAME_FIELD = 'username'
What I want is to save the point after changed.
What should I do? Please help! I'm really new to this. Sorry for my English.
Sadly, I don't have enough reputation to make a comment, but you need to use save() method in a model, not in an Integer.
So, you should replace
point_left = user_point
point_left.save()
for this
user.point = user_point # Assign the new point to the user
user.save() # Update your user model
i have an UpdateView with a couple of forms and i'm trying to understand how to set the instance for the other form because the first form work just fine but the second form is always empty and i cant figure out how to set the instance for that modelform .
class ProfileUpdateView(UpdateView):
# model = User
queryset = User.objects.all()
form_class = UserForm
second_form_class = ClientForm
template_name = 'accounts/update.html'
def get_object(self):
user = get_object_or_404(User , username__iexact=self.kwargs.get('username'))
return user
def get_context_data(self, **kwargs):
user = self.object
profile = Client.objects.get(id = user.clients.id)
context = super(ProfileUpdateView, self).get_context_data(**kwargs)
if user.is_client and 'ClientForm' not in context:
context['client_form'] = self.second_form_class(self.request.GET, instance=profile )
return context
models
class User(AbstractUser):
gender_choice =(
('Male','Male'),
('Female','Female'),
)
is_artisan = models.BooleanField('artisan status', default=False)
is_client = models.BooleanField('client status', default=False)
avatar = models.ImageField(null=True ,blank=True)
birth_day = models.DateField(null=True,blank=True)
birth_location = models.CharField(max_length=30, null=True ,blank=True)
adresse = models.CharField(max_length=30, null=True ,blank=True)
gender = models.CharField(max_length=6,choices=gender_choice,)
phone = models.CharField(max_length=10 ,null=True ,blank=True)
class Client(models.Model):
client_choice = (
('erson','person'),
('company','company'),
)
client_type = models.CharField(max_length=10,choices=client_choice,)
user = models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, related_name='clients')
forms
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email','avatar','adresse','birth_location','birth_day' ,'gender' ,'phone')
class ClientForm(forms.ModelForm):
class Meta:
model = Client
fields = ('client_type',)
the question now how/where can i set the instance for the second form and where is the first form instance is set .
Is that a typo in get_context_data? Should it be:
if user.is_client and 'client_form' not in context:
context['client_form'] = self.second_form_class(self.request.GET, instance=profile)
The first form is set in UpdateView's super class FormMixin.get_context_data (which in turn calls FormMixin.get_form()). Docs for FormMixin
I created a custom user model called Agent by extending AbstractUser. Now for some reason, my signup page is stuck and I can't figure out why (it was working fine before I created the custom user). When I click the Sign Up button, the page is stuck on Waiting for localhost...
There are 2 additional models on top of Agent that are created during registration - AgentBasicInfo and AgentPremiumInfo. AgentBasicInfo is displayed on the sign up page, while AgentPremiumInfo is created in the background, and not actually displayed during registration.
When I check my admin page, I see that an Agent model has been created, but no AgentBasicInfo and AgentPremiumInfo instances have been created. This leads me to believe something is getting stuck at or after agent_basic_info = basic_info_form.save(commit=False), but I can't figure out what it is.
Here is my code:
views.py
def signup(request):
if request.user.is_authenticated:
return HttpResponseRedirect('../dashboard/')
if request.method == 'POST':
signup_form = SignupForm(request.POST)
basic_info_form = AgentBasicInfoForm(request.POST)
if signup_form.is_valid() and basic_info_form.is_valid():
agent = signup_form.save(commit=False)
agent.is_active = False
agent.save()
# Creates a basic info form with user input
agent_basic_info = basic_info_form.save(commit=False)
agent_basic_info.agent = agent
agent_basic_info = agent_basic_info.save()
# Creates a profile model with the agent's premium information, empty except for 'agent' field. No actual form displayed on sign up page.
agent_premium_info = AgentPremiumInfo.objects.create(agent=agent)
agent_premium_info.save()
current_site = get_current_site(request)
message = render_to_string('acc_active_email.html', {
'agent':agent,
'domain':current_site.domain,
'uid': urlsafe_base64_encode(force_bytes(agent.pk)),
'token': account_activation_token.make_token(agent),
})
mail_subject = 'Activate your blog account.'
to_email = signup_form.cleaned_data.get('email')
email = EmailMessage(mail_subject, message, to=[to_email])
email.send()
return HttpResponse('Please confirm your email address to complete the registration')
else:
signup_form = SignupForm()
basic_info_form = AgentBasicInfoForm()
return render(request, 'signup.html', {'signup_form': signup_form, 'basic_info_form': basic_info_form})
def activate(request, uidb64, token):
try:
uid = force_text(urlsafe_base64_decode(uidb64))
agent = Agent.objects.get(pk=uid)
except(TypeError, ValueError, OverflowError, Agent.DoesNotExist):
agent = None
if agent is not None and account_activation_token.check_token(agent, token):
agent.is_active = True
agent.save()
login(request, agent)
# return redirect('home')
return HttpResponse('Thank you for your email confirmation. Now you can login your account.')
else:
return HttpResponse('Activation link is invalid!')
models.py
class Agent(AbstractUser):
pass
class AgentBasicInfo(models.Model):
TITLE = (
('Salesperson', 'Salesperson'),
('Sales Representative', 'Sales Representative'),
('Broker', 'Broker'),
('Broker of Record', 'Broker of Record'),
)
agent = models.OneToOneField(Agent, on_delete=models.CASCADE)
agent_first_name = models.CharField(max_length=30)
agent_last_name = models.CharField(max_length=30)
agent_preferred_email = models.EmailField()
office_phone_number = models.CharField(max_length=10)
agent_brokerage = models.CharField(max_length=50)
agent_title = models.CharField(max_length=20, choices=TITLE)
class AgentPremiumInfo(models.Model):
agent = models.OneToOneField(Agent, on_delete=models.CASCADE)
agent_phone_number = models.CharField(max_length=10, blank=True, null=True)
agent_website = models.CharField(max_length=50, blank=True, null=True)
agent_biography = models.TextField(blank=True, null=True)
agent_address_street = models.CharField(max_length=50, blank=True, null=True)
agent_address_city = models.CharField(max_length=25, blank=True, null=True)
agent_address_province = models.CharField(max_length=2, choices=PROVINCE, blank=True, null=True) # Add province choices later
agent_address_postal_code = models.CharField(max_length=6, blank=True, null=True)
agent_picture = models.ImageField(height_field=200, width_field=100, blank=True, null=True)
forms.py
class SignupForm(UserCreationForm):
email = forms.EmailField(max_length=200, help_text='Required')
def clean_email(self):
data = self.cleaned_data['email']
if not data.endswith('#gmail.com'):
raise forms.ValidationError("You must use your #gmail.com Email")
return data
class Meta:
model = Agent
fields = ('username', 'email', 'password1', 'password2')
class AgentBasicInfoForm(forms.ModelForm):
class Meta:
model = AgentBasicInfo
fields = ['agent_first_name', 'agent_last_name', 'agent_preferred_email', 'office_phone_number', 'agent_brokerage', 'agent_title']
class AgentPremiumInfoForm(forms.ModelForm):
class Meta:
model = AgentPremiumInfo
fields = ['agent_phone_number', 'agent_website', 'agent_biography', 'agent_picture', 'agent_address_street', 'agent_address_city', 'agent_address_province', 'agent_address_postal_code']
It seems something was wrong in the database despite me doing a reset_db. I did another reset_db and it magically fixed the issue.
When the user is required to fill his profile, he picks a city from the Google Places Autocomplete and posts the form, in the view I extract the city Id from the Google API based on the posted text (I use the same id as pk in my db) and try to extract a city from my db.
These are the models:
class City(models.Model):
#extracted from the Google API
city_id = models.CharField(primary_key=True, max_length=150)
name = models.CharField(max_length=128, blank=True)
country = models.CharField(max_length=128, blank=True)
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='profile', primary_key=True)
city = models.ForeignKey(City, blank=True, null=True)
prof_pic = models.ImageField(blank=True, upload_to='profile_pictures')
This is the view:
def createprofile(request):
if request.method =='POST':
user = User.objects.get(username=request.user.username)
user_form = UserForm(data=request.POST, instance=user)
profile_form = UserProfileForm(data=request.POST)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.save()
profile = profile_form.save(commit=False)
profile.user = user
#brings back the city search result as text
searched_city = request.POST['city']
#brings back city ID from the Google API
searched_city_id = population_script.get_city_json(searched_city.replace(" ", ""))['results'][0]['id']
#If it's a valid city
if searched_city_id != -1:
city = City.objects.get(city_id = searched_city_id)
profile.city = city#this is what I want to happen!
else:
return HttpResponse("There's no such city, please try a different query.")
if 'prof_pic' in request.FILES:#now save the profile pic
profile.prof_pic = request.FILES['prof_pic']
print("PROF PIC IS: " + profile.prof_pic.url)
else:
profile.prof_pic = 'images/anon.png'
profile.save()
if 'next' in request.GET:
return redirect(request.GET['next'])
else:
print (user_form.errors, profile_form.errors)
else:
user_form = UserForm()
profile_form = UserProfileForm()
return render(request,
'excurj/createprofile.html', {'user_form':user_form, 'profile_form':profile_form})
However, I keep receiving an error that what's been posted is just text while the city needs to be a City object. I can save the profile pic ok though.
Cannot assign "'Dubai - United Arab Emirates'": "UserProfile.city"
must be a "City" instance.
edit: these are the forms:
class UserForm(forms.ModelForm):
first_name = forms.CharField(
label = "First Name:",
max_length = 80,
required = True
)
last_name = forms.CharField(
label = "Last Name:",
max_length = 80,
required = True,
)
class Meta:
model = User
fields = ('first_name', 'last_name')
class UserProfileForm(forms.ModelForm):
city = forms.CharField(
label = "Your Current City:",
max_length = 200,
required = True,
)
class Meta:
model = UserProfile
fields = ('city','prof_pic', 'dob', 'sex', 'education', 'career', 'about_you',
'music_movies_books', )
Please provide a related_name to the city field in the UserProfile.
I worked around this by creating a new UserProfile field called city_search_text which saves the searched text thus it of course does not return any error. I then receive it in the POST request and comfortable pull the proper city in the view.
I handled a similar issue by overriding my forms' clean method. Something like the following will work:
def clean(self):
# fix city problem
if self.cleaned_data.get("city") is not None:
self.cleaned_data['city'] = City.objects.get(id=self.cleaned_data.get("city"))
return self.cleaned_data