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.
Related
I have been trying to teach myself something new this week by following various tutorials on Google APIs. I am hitting a wall on the form saving bit, so helping you can help.
Basically, I am trying to offer user the possibility to enter their first line of address for Google to then submit suggestions of addresses.
This first bit works (when I enter the first line of an address, I get generated a list of suggestions).
However, when I am trying to save the form, this doesn't seem to be saved anywhere. And I am not getting any error message either (if anything I am getting the a "success message" I am supposed to receive when the form is successfully submit).
I thought there might be a field that is not getting being populated in the html. So I tried to empty one and tried to save. But on this occasion I received an error message, saying the field is missing. Which makes me thing this hasnt anything to do with the fields in the form but probably how I save my form in the views.py.
I must admit I am way out of my comfort zone here (this ajax thing proved to be difficult to make work, and all I had to do was to follow a tutorial..), so I wouldnt be surprised I am not capturing all the code needed for you to help. If so let me know what you need to see.
Views.py
def is_ajax(request):
return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
def profile(request):
result = "Error"
message = "There was an error, please try again"
form = profileform(instance = request.user)
Profile.objects.get_or_create(user=request.user)
if is_ajax(request=request):
form = profileform(data = request.POST, instance = request.user)
if form.is_valid():
obj = form.save()
obj.has_profile = True
obj.save()
result = "Success"
message = "Your profile has been updated"
else:
message = FormErrors(form)
data = {'result': result, 'message': message}
return JsonResponse(data)
else:
context = {'form': form}
context['google_api_key'] = settings.GOOGLE_API_KEY
context['base_country'] = settings.BASE_COUNTRY
return render(request, 'main/profile.html', context)
Froms.py
from .models import Profile
class ProfileForm(forms.ModelForm):
address = forms.CharField(max_length=100, required=True, widget = forms.HiddenInput())
town = forms.CharField(max_length=100, required=True, widget = forms.HiddenInput())
county = forms.CharField(max_length=100, required=True, widget = forms.HiddenInput())
post_code = forms.CharField(max_length=8, required=True, widget = forms.HiddenInput())
country = forms.CharField(max_length=40, required=True, widget = forms.HiddenInput())
longitude = forms.CharField(max_length=50, required=True, widget = forms.HiddenInput())
latitude = forms.CharField(max_length=50, required=True, widget = forms.HiddenInput())
class Meta:
model = Profile
fields = ['address','town','county','post_code','country','longitude','latitude']
Models.py
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
address = models.CharField(verbose_name="Address",max_length=100, null=True, blank=True)
town = models.CharField(verbose_name="Town",max_length=100, null=True, blank=True)
county = models.CharField(verbose_name="County",max_length=100, null=True, blank=True)
post_code = models.CharField(verbose_name="Post Code",max_length=8, null=True, blank=True)
country = models.CharField(verbose_name="Country",max_length=100, null=True, blank=True)
longitude = models.CharField(verbose_name="Longitude",max_length=50, null=True, blank=True)
latitude = models.CharField(verbose_name="Latitude",max_length=50, null=True, blank=True)
captcha_score = models.FloatField(default = 0.0)
has_profile = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
def __str__(self):
return str(self.user)
Interesting that you're getting to your success message. Your issue might be that you're passing a user instance to a form that expects a profile model (not sure why this doesn't throw an error though):
# capture the profile that is created with get_or_create
profile, created = Profile.objects.get_or_create(user=request.user)
if is_ajax(request=request):
form = profileform(data = request.POST, instance=profile) # change instance
Instead of
else:
message = FormErrors(form)
Try this
else:
message = form.errors
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 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)
in order to generate the full url in the email I send to the ticket purchaser, I have to access get_current_site in my models.py. To do so I pass request like this: get_absolute_url(request)
Is there anything wrong in doing it that way, or would you consider this as good code/approach?
def checkout_page(request):
[...]
#Send email
subject = render_to_string('checkout/email/your_ticket_subject.txt', {})
to_email = [transaction_profile.cleaned_data['email'],]
email_ticket_link = t.get_absolute_url(request, email=True)
content = render_to_string('checkout/email/your_ticket_message.txt', {'email_ticket_link': email_ticket_link,})
send_mail(subject, content, settings.DEFAULT_FROM_EMAIL, to_email)
ticket_link = t.get_absolute_url(request)
return redirect(ticket_link)
models.py
class TicketPurchase(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE) #change CASCADE
ticket = models.ForeignKey(Ticket, on_delete=models.CASCADE) #change CASCADE
ticketpurchase_id = models.CharField(max_length=10, unique=True)
refunded = models.BooleanField(default=False)
timestamp = models.DateTimeField(auto_now_add=True)
update = models.DateTimeField(auto_now=True)
def get_absolute_url(self, request, email=False):
ticket_link = reverse("ticketsgenerator:show_tickets",
kwargs={"order_id": self.order.order_id, "customer_key": self.order.customer_key}
)
if email:
current_site = get_current_site(request)
return 'https://{}{}'.format(current_site, ticket_link)
return ticket_link
If I have a model with a couple of fields that inherit from a UserProfile model:
class LeaveRequest(models.Model):
employee = models.ForeignKey(UserProfile)
supervisor = models.ForeignKey(UserProfile, related_name='+', blank=False, null=False)
submit_date = models.DateField(("submit date"), default=datetime.date.today)
leave_type = models.CharField(max_length=64, choices=TYPE_CHOICES)
start_date = models.DateField(("start date"))
return_date = models.DateField(("return date"))
...
and I use this model to create a model form:
class LeaveRequestForm(ModelForm):
class Meta:
model = LeaveRequest
how can I query for the email url in the User Profile? In this view function, I'm trying to send a notification email on form submit, to the sender(employee) and supervisor:
def create_request(request):
if request.method == 'POST':
form = LeaveRequestForm(request.POST)
if form.is_valid():
name = form.cleaned_data['employee']
subject = form.cleaned_data['leave_type']
message = form.cleaned_data['notes']
sender = form.cleaned_data['employee']
remoterq = form.save(commit=False)
remoterq.save()
form.save_m2m()
recipients = [user.email for user in remoterq.employee, user.email for user in remoterq.supervisor]
from django.core.mail import send_mail
send_mail(subject, message, 'projects.xxx#google.com', recipients, fail_silently=False)
return HttpResponseRedirect('.')
my code for the "recipients" var is invalid but I don't know how to fix it.
Try
remoterq.employee.user.email
for the employee email and
remoterq.supervisor.user.email
for the supervisor email.