(Django 1.8, Django-Registration-Redux 1.4)
After following the answer in this SO post: django-registration-redux add extra field
I've implemented a custom view with my own template to register a user, and my custom form is correctly rendered.
user_views.py
class SignupView(RegistrationView):
form_class = MyRegistrationForm
def register(self, request, form):
print form
print request
new_user = super(SignupView, self).register(request, form)
my_user_model = MyUserModel()
my_user_model.user = new_user
my_user_model.save()
return new_user
However, register doesn't seem to get called. But, when I define post() - the request comes through with all of the form data.
urls.py
url(
r'^accounts/register/',
user_views.SignupView.as_view(),
name='signup'
), # Customized-Register
url(
r'^accounts/',
include('registration.backends.default.urls')
), # Registration-Redux
Would appreciate guidance on the correct usage, thanks!
Ok - I've determined the solution. It had to do with my custom form not collecting the (required) username field.
Incase it helps, I figured it out by implementing form_invalid(self, form) as RegistrationView is a derived class of Django's FormView, which hinted me towards it.
This SO answer helped override the username requirement: Django Registration Redux: how to change the unique identifier from username to email and use email as login
Hope it helps
Try this line:
new_user = super(MyRegistrationView, self).register(form_class)
and change the url to:
url(r'^accounts/register/$', MyRegistrationView.as_view(),
name='registration_register'),
Hope it works!
Related
I've to try make a change password page with Django.contrib.auth.views.PasswordChangeView like:
[views.py]
class ChangePasswordView(LoginRequiredMixin, PasswordChangeView):
template_name = 'accounts/password_change.html'
success_url = reverse_lazy('account:password_change_done')
class ChangePasswordDoneView(LoginRequiredMixin, PasswordChangeDoneView):
template_name = 'accounts/password_change_done.html'
With URL like:
[urls.py]
path('profile/update/password/', views.ChangePasswordView.as_view(),
name='password_change'),
path('profile/update/password/success/', views.ChangePasswordDoneView.as_view(),
name='password_change_done'),
I use custom user, but I look the source code, Django get the user by request.user so its not be a problem if I use the custom user.
But why my change password not work, if I change the password with right old password and new password the form return the success page but not changing my password and I try to use wrong password in old password but always return the success page. What's the problem?
iam so sory, my problem is in my form action not to password_change url but in my success url. my fail not check this. thanks
Is there anyway to prevent the Allauth Signup form from automatically logging in the User?
I found a similar post here with no answers:
prevent user login after registration using django-allauth
You get logged in because this behavior is baked into the signup view of the allauth. When the form is valid, the view calls the function called complete_signup that does two things:
Emits the user_signed_up signal
Logs a user in
To solve this, we need to leave the step 1 and replace the step 2 with a simple redirect.
Here's how this can be done:
Extend the SignupView from allauth/account/views.py and override its form_valid method like this:
class CustomSignupView(SignupView):
def form_valid(self, form):
# By assigning the User to a property on the view, we allow subclasses
# of SignupView to access the newly created User instance
self.user = form.save(self.request)
try:
signals.user_signed_up.send(
sender=self.user.__class__,
request=self.request,
user=self.user,
**{}
)
return HttpResponseRedirect(self.get_success_url())
except ImmediateHttpResponse as e:
return e.response
Haven't tested the code, but it should be working.
Wire your new view up in urls.py, so it replaces the old Signup view url.
I am using django-allauth 0.42.0
There is no need to extend the SignUp view, it can be achieved by the setting:
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
in your project settings.py file.
I want that the landing page of my homepage is a form with an input and the user puts in stuff. So I followed a couple of tutorials and now I have this:
views.py:
def create2(request):
if request.method =='POST':
form = LocationForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('')
else:
form = LocationForm()
args = {}
args.update(csrf(request))
args['form'] = form
return render_to_response('location/index.html', args)
and in my urls.py:
url(r'^$', 'core.views.create2'),
which works perfectly fine, if I go to 127.0.0.1:8000 I get to index.html and when put in something in the input it gets saved in the database. However, the old part of my homepage looks like this
class LandingView(TemplateView):
model = Location
template_name="location/index.html"
def search
...
and the urls.py:
url(r'^$', core.views.LandingView.as_view(), name='index'),
which has a function search I So my question is, is there a way how I can merge the def create2 into my LandingView. I tried several things, but I am always ending up having the index.html without the input field. I also tried
def create2
...
def search
...
but didn't work.
Does anyone know how to merge that together?
EDIT
Thank you the working solution looks like this now
class Create(CreateView):
model = coremodels.Location
template_name = 'location/test.html'
fields = ['title']
def form_valid(self, form):
form.save()
return HttpResponseRedirect('')
return super(Create, self).form_valid(form)
Depending on the results you are looking for, there are multiple ways to solve this:
1. Use CreateView and UpdateView
Django already provides some classes that render a form for your model, submit it using POST, and re-render the form with errors if form validation was not successful.
Check the generic editing views documentation.
2. Override get_context_data
In LandingView, override TemplateView's get_context_data method, so that your context includes the form you are creating in create2.
3. Use FormView
If you still want to use your own defined form instead of the model form that CreateView and UpdateView generate for you, you can use FormView, which is pretty much the same as TemplateView except it also handles your form submission/errors automatically.
In any case, you can keep your search function inside the class-based view and call it from get_context_data to include its results in the template's context.
I am new to django. I made a form. I want that if the form is filled successfully then django should redirect to a success page showing the name entered in the form but no parameters should be present in the url itself.
I searched on the internet and the solution I got was to redirect to url with pk as a get parameter which fetches the data and shows in the view. But I don't want to pass any thing in the url itself. and some websites say that http can't redirect with post data.
Here's my views.py
class UserRegistrationView(CreateView):
model = UserForm
template_name = 'userregistration.html'
form_class = UserForm
success_url = 'success'
def get_success_url(self):
return reverse('success',kwargs = {'name' : self.object.firstName})
and here's the template to which I want to redirect:
<h2>Congratualations for registering {{name}} </h2>
Basically what I want is that if the person fill form mentioning his/her firstName as "xyz" then the redirected success page should say that "Congratulations for registering xyz"
You can use django sessions, which I believe installed by default in 1.8
Look here
# Set a session value:
request.session["fav_color"] = "blue"
# Get a session value -- this could be called in a different view,
# or many requests later (or both):
fav_color = request.session["fav_color"]
# Clear an item from the session:
del request.session["fav_color"]
You can pass your pk via session and extract your object in another view without affecting your url.
Make sure you clean up after yourself.
Let me know if more help needed.
One of the possible ways of passing data between views is via sessions. So, in your UserRegistrationView you need to override the form_valid method as shown below.
class UserRegsitrationView(CreateView):
def form_valid(self,form):
self.request.session['name'] = self.object.firstName
return super(UserRegistrationView,self).form_valid(form)
class SuccessView(TemplateView):
template_name = "success_template.html"
def get_context_data(self,**kwargs):
context = super(SuccessView,self).get_context_data(**kwargs)
context['name'] = self.request.session.get('name')
del self.request.session['name']
return context
One more thing that you can modify in your code is that you need not declare success_url if you are overriding get_success_url
I am designing an admin interface where invite mails will be sent to users. My Invitation model is ready & in my invitation admin interface I am able to see my added users for which the admin can send email invites.
now I want to customize this a bit. I want to add for each row a SEND button which will actually send an email to that user. Sending email function etc. are all ready. I am not getting as to how I can customize this admin template to add a send button. Can someone help ?? or atleast point me in the right direction...
P.S: it need not be a send button, it could be part of "action" dropdown where for the selected users I can jointly send emails.
Regarding the send button for each row, you can give your model (or ModelAdmin) a new function which returns the corresponding HTML pointing to your views (or calling corresponding AJAX functions). Just add your function to the ModelAdmin's "list_display" and make sure that HTML tags don't get escaped:
class MyModelAdmin(admin.ModelAdmin):
...
list_display = ('name', 'email', 'sender', 'send_email_html')
def send_email_html(self, obj):
# example using a javascript function send_email()
return 'Send Now' % obj.id
send_email_html.short_description = 'Send Email'
send_email_html.allow_tags = True
Regarding the use of an action, define "actions" in your ModelAdmin as a list containing your function which takes modeladmin, request, queryset as parameters:
def send_email_action(modeladmin, request, queryset):
whatever_you_want_to_do_with_request_and_queryset
send_email.short_description = 'Send email'
class MyModelAdmin(admin.ModelAdmin):
...
actions = [
send_email_action
]
My solution below is for adding the "send invite" action in admin interface
"Send Invite" action
You can refer to the django admin-actions documentation here.
Here is what your admin.py should look like:
from django.contrib import admin
from myapp.models import MyModel
from django.core.mail import send_mail
class MyModelAdmin(admin.ModelAdmin):
actions = ['send_invite']
def send_invite(self, request, queryset):
# the below can be modified according to your application.
# queryset will hold the instances of your model
for profile in queryset:
send_email(subject="Invite", message="Hello", from_eamil='myemail#mydomain.com', recipient_list=[profile.email]) # use your email function here
send_invite.short_description = "Send invitation"
admin.site.register(MyModel, MyModelAdmin)
I have not tested this code, but it is pretty much what you need. Hope this helps.