64172

Passing context to django-registration's views

Question:

I'm utilizing <a href="http://django-registration.readthedocs.io/en/2.0.1/index.html" rel="nofollow">django-registration</a> with a set of premade templates I found on Github for doing a two-step (registration-activation) workflow <a href="http://django-registration.readthedocs.io/en/2.0.1/hmac.html" rel="nofollow">using HMAC</a>.

I want to pass global variables (defined in context-processors) like my website's name to the emails sent by django-registration. the activation email sent to a new registrant, for example, or the password change one.

The "problem" is I don't directly have access to those views. That's kinda the point of django-registration, you include its path in the urls.py file, and everything works:

urlpatterns = [ url(r'^', include('core.urls')), url(r'^admin/', admin.site.urls), url(r'^accounts/', include('registration.backends.hmac.urls')), ]

What's the minimum effort way of adding context to those views? I've already created and am successfully <a href="https://stackoverflow.com/questions/48053428/django-display-website-name-in-template-emails-without-using-sites-framework" rel="nofollow">passing context to emails in my own views</a> (using context processors):

def send_some_email_view(request): msg_plain = render_to_string('email_change_email.txt', context, request=request) msg_html = render_to_string('email_change_email.html', context, request=request)

But what about views I didn't create?

Edit: So I made some progress, finding django-registration's registration view, and this method inside of it:

def send_activation_email(self, user): """ Send the activation email. The activation key is simply the username, signed using TimestampSigner. """ activation_key = self.get_activation_key(user) context = self.get_email_context(activation_key) context.update({ 'user': user }) subject = render_to_string(self.email_subject_template, context) # Force subject to a single line to avoid header-injection # issues. subject = ''.join(subject.splitlines()) message = render_to_string(self.email_body_template, context) user.email_user(subject, message, settings.DEFAULT_FROM_EMAIL)

I don't want to override it inside the source code because that would prevent me from updating. So now the question becomes: Is my only way out writing a view that subclasses this view, and overriding the method? This means I'm writing separate views for every view provided by django-registartion that needs to send an email...

Answer1:

First create your own view based on the vendor view and overwrite your desired method:

from registration.backends.hmac.views import RegistrationView class CustomRegistrationView(RegistrationView): def get_email_context(self, user): context = super().get_email_context(user) return RequestContext(self.request, context)

Than have a look at registration.backends.hmac.urls.py (<a href="https://github.com/ubernostrum/django-registration/blob/master/registration/backends/hmac/urls.py" rel="nofollow">source</a>). They just define a bunch of urls there.

You can easily overwrite just one of them by adding your own <strong>before</strong> you include the one from the app.

from yourapp import views urlpatterns = [ # [...] url(r'^accounts/register/$', views.CustomRegistrationView.as_view(), name='registration_register'), url(r'^accounts/', include('registration.backends.hmac.urls')), # [...] ]

While changing just the necessary things you also get some insight of whats going on in your 3rd party app, which is always an advantage. This applies to most 3rd party apps not just the one you are currently using.

Answer2:

Here's what I ended up doing, Thanks to the direction dahrens' answer sent me to:

# myapp/processors.py def get_website_name(request): website_name = 'ExcitingWebsiteThatsComingSoon' return {'mysite_name': website_name} # some views.py file from myapp.processors import get_website_name class RegistrationViewWithContext(RegistrationView): def get_email_context(self, user): context = super().get_email_context(user) context['req'] = get_website_name(self.request) return context

Basically, I'm simply using my custom processor to inject the website's name. It isn't as clean as I hoped it would be: While in my templates I can simply use {{ mysite_name}}, in the email template I have to use {{req.mysite_name}}. But this does have the DRY-ness I aimed for: all templates updating accordingly if the variable in the function changes.

I'll mark my answer as correct for now and will update accordingly if any new answers come in.

Recommend

  • Adding contact to gmail programatically by python and django through send mail
  • render_to_string() got an unexpected keyword argument 'status'
  • dismiss Progress Dialog in another Activity … Android
  • Reading XML into Datatable gives incorrect DateTime when the time has Time Zone info
  • How to save dynamically created textboxes and their values
  • How to synchronize two scrollview in Android?
  • How do you create a Fuseki SPARQL server using the Apache Jena Java API?
  • pip in virtualenv gets ConnectTimeoutError
  • Run multiple queries from 1 SQL file showing result in multiple tables
  • Installed module is empty
  • Blackberry - Custom EditField Cursor
  • Test if a set exists before trying to drop it
  • D3 nodes and links from JSON with nested arrays of children
  • How to create a file in java without a extension
  • Alert pop up with LWUIT
  • Django: Count of Group Elements
  • NHibernate Validation Localization with S#arp Architecture
  • ilmerge with a PFX file
  • Java Scanner input dilemma. Automatically inputs without allowing user to type
  • Adding a button at the bottom of a table view
  • C# - Is there a limit to the size of an httpWebRequest stream?
  • Read text file and split every line in MSBuild
  • req.body is undefined - nodejs
  • Fetching methods from BroadcastReceiver to update UI
  • Counter field in MS Access, how to generate?
  • Get object from AWS S3 as a stream
  • Java applet as stand-alone Windows application?
  • How to redirect a user to a different server and include HTTP basic authentication credentials?
  • MySQL WHERE-condition in procedure ignored
  • Symfony2: How to get request parameter
  • Adding custom controls to a full screen movie
  • GridView Sorting works once only
  • Comma separated Values
  • File upload with ng-file-upload throwing error
  • WPF Applying a trigger on binding failure
  • log4net write single file for each call to log.info
  • Error creating VM instance in Google Compute Engine
  • Getting error when using KSoap library to consume .NET web services
  • Hits per day in Google Big Query
  • how does django model after text[] in postgresql [duplicate]