Customizing Django-PayPal View - django

I am using django paypal to allow users to make a payment on my site however i have a few queries.
The way how it is currently working for me is that i have a template called profile.html. When a user clicks the button "Click for more subscription options" he will be redirected to the subscriptions.html template showing a table of the subscriptions and a paypal button. When the button is clicked, the user gets redirected to another template called paypal.html which shows another paypal button derived from django-paypal's forms.py
My question here would be how i can modify the paypal view such that i can do away with the paypal.html and direct the user directly to the actual paypal website when he clicks the paypal button in subscription.html?
I hope my description of the question is clear enough.
in my views.py:
def paypal(request):
paypal_dict = {"business":settings.PAYPAL_RECEIVER_EMAIL,"amount": "1.00","item_name": "Milk" ,"invoice": "12345678", "notify_url": "%s%s" % (settings.SITE_NAME, reverse('paypal-ipn')),"return_url": "http://rosebud.mosuma.net",}
# Create the instance.
form = PayPalPaymentsForm(initial=paypal_dict)
context = {"form": form.sandbox()}
return render_to_response("paypal.html", context)
in my profile.html:
....
<INPUT TYPE="submit" Value="Click to find out subscription plans" name="subscription" onClick="/subscribe/>
in my subscription.html:
<form method="post" action="paypal/">
<select name="subscription_input" id="id_subscription" style = "float: center">
<option>Monthly</option>
<option>Yearly</option>
</select></br></br>
{{ form }}
</form>
in my urls.py:
url(r'^paypal/$', 'r2.views.paypal', name='paypal'),
url(r'^profile/paypal/$', 'r2.views.paypal', name='paypal'),

If you want the user to go directly to the PayPal website the moment he clicks the PayPal button in subscription.html, you will have to render the PayPal form in subscription.html instead of paypal.html. Moreover you need to subclass the PayPalPaymentsForm in forms.py to override the default PayPal image of "Buy Now" because you want your own button to work in the first place.
forms.py
from paypal.standard.forms import PayPalPaymentsForm
from django.utils.html import format_html
class ExtPayPalPaymentsForm(PayPalPaymentsForm):
def render(self):
form_open = u'''<form action="%s" id="PayPalForm" method="post">''' % (self.get_endpoint())
form_close = u'</form>'
# format html as you need
submit_elm = u'''<input type="submit" class="btn btn-success my-custom-class">'''
return format_html(form_open+self.as_p()+submit_elm+form_close)
views.py
from .forms import ExtPayPalPaymentsForm
def paypal(request):
paypal_dict = {"business":settings.PAYPAL_RECEIVER_EMAIL,"amount": "1.00","item_name": "Milk" ,"invoice": "12345678", "notify_url": "%s%s" % (settings.SITE_NAME, reverse('paypal-ipn')),"return_url": "http://rosebud.mosuma.net",}
# Create the instance.
form = ExtPayPalPaymentsForm(initial=paypal_dict)
context = {"form": form.sandbox()}
return render_to_response("subscription.html", context)

Related

Django - redirect to home after login when session times out

If I'm on foo.html (any view/template) and the session times out, and then I click on a link to bar.html (any other view), I'm taken to the login page. After successful authentication, I am redirected to bar.html. I want it to always redirect to home.html. My settings.py has LOGIN_REDIRECT_URL = 'home'.
Users are prompted to login after the sessions expires because all my views require the user to be logged in. In CBV I use:
#method_decorator([login_required], name='dispatch')
class QuestionListView(PermissionRequiredMixin, ListView):
In functional views I have a decorator:
# login_required
def home(request):
I am using the django auth and have not overridden the login view. My login.html file contains:
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<a class="button secondaryAction" href="{% url 'password_reset' %}">Forgot Password?</a>
<button type="submit" class="btn btn-secondary mt-2 pl-4">Log In</button>
</form>
Looking at the django code, I think the answer lies in django.contrib.auth.views:
class RedirectURLMixin:
next_page = None
redirect_field_name = REDIRECT_FIELD_NAME
success_url_allowed_hosts = set()
def get_success_url(self):
return self.get_redirect_url() or self.get_default_redirect_url()
def get_redirect_url(self):
"""Return the user-originating redirect URL if it's safe."""
redirect_to = self.request.POST.get(
self.redirect_field_name, self.request.GET.get(self.redirect_field_name)
)
url_is_safe = url_has_allowed_host_and_scheme(
url=redirect_to,
allowed_hosts=self.get_success_url_allowed_hosts(),
require_https=self.request.is_secure(),
)
return redirect_to if url_is_safe else ""
def get_success_url_allowed_hosts(self):
return {self.request.get_host(), *self.success_url_allowed_hosts}
def get_default_redirect_url(self):
"""Return the default redirect URL."""
if self.next_page:
return resolve_url(self.next_page)
raise ImproperlyConfigured("No URL to redirect to. Provide a next_page.")
My guess is that def get_default_redirect is happening because I click on a link (the next_page) which triggers the login (because of the session time out).
The only reason I want to have all logins go to the home page is because I'm temporarily putting an announcement banner on the home page. It's possible for a user to not see the banner if they never go to the home page by simply logging in using the method described here.

Django - how to go back to previous view with parameters

I am relatively new with Django, this must be a common problem.
I have created a view to show a form to input date (using widget that returns separate fields):
when date is inserted, I call a function userPage(request, my_date)
that filters, processes and renders a page (user.html) showing a list of items.
def datePage(request):
user=request.user
context = {}
context['form'] = UserDateForm()
if request.GET:
date_yr = request.GET['food_date_year']
date_mo = request.GET['food_date_month']
date_day = request.GET['food_date_day']
my_date_string = date_yr+'-'+date_mo+'-'+date_day
my_date = datetime.strptime(my_date_string, "%Y-%m-%d").date()
return userPage(request,my_date)
return render(request, "date.html", context)
def userPage(request, my_date):
user=request.user
# process context using user, my_date
context={...:..., 'my_date': my_date}
return render(request,'user.html',context)
In user.html I include a URL to add an item:
</div>
<form action="{% url 'My_ItemCreate' %}" method="POST">
{%csrf_token%}
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-plus"></span>
</button>
</form>
</div>
'My_ItemCreate' points to a django.views.generic CreateView that creates an item.:
path('MyItemCreate/',views.My_ItemCreate.as_view(),name='My_ItemCreate'),
class My_ItemCreate(CreateView):
model = MyItem
fields = ...
After creating the item in the CreateView, how do I go back to the user page
after I inserted the date? I have lost the date in the new URL.
If I use URL resolver to go to userPage, how do I pass a date in the format?
It would be nice that I am able to pass initial values in the CreateView, and
make some fields read-only, how do I modify/override CreateView ?
Many Thanks for your help!
I have found an answer to my problem: using request.session
to store a value and retrieving in other views, it works fine.
I am still curious to know if there are experts who
would provide a more elegant solution, and if someone
could be so kind to answer point 2) regarding CreateView read_only fields
Thanks
D

Implement Facebook Log In with Django

Hi I would really appreciate if somebody could please paste there code here for there Facebook login created for their Django project, whether it is a separate app or not, with a couple of explanations. Pulling User Name, Email and profile pic. Thank you
It took me a week but I have implemented Facebook login the hard way. If you don't want a 3rd party app on your site (more secure and trustworthy for users) here are the steps:
Get the FB login button here: (https://developers.facebook.com/docs/facebook-login/web/login-button). You can change the settings of the button before you copy the code.
Get the javascript plugin here (https://developers.facebook.com/docs/facebook-login/web). I suggest copying the example and modifying the following:
Javascript:
if (response.status === 'connected') {
// Logged into your app and Facebook.
FB.api('/me', {fields: 'name, email'}, function(response) {
console.log('Successful login for: ' + response.name);
document.getElementById("your_name2").value = response.name;
document.getElementById("your_email").value = response.email;
document.getElementById("myForm").submit();
document.getElementById('status').innerHTML =
'Thanks for logging in, ' + response.name + response.email + '!';});
Once logged in and 'connected' you need to change the info you call. Add the {fields...} you require above. Keep the log to see if it's working.
Submit the info pulled in 2 into a hidden form in order to send it to a view and model. Here is the form (hellls just default value):
Form template:
<form action="{% url 'facebooklogin:register' %}" method="post" style="display: none;" id="myForm">
{% csrf_token %}
<label for="your_name">Your name: </label>
<input id="your_name2" type="text" name="your_name" value="helllllls">
<input id="your_email" type="text" name="your_email" value="helllllls">
<input type="submit" value="OK">
</form>
Set up your form, model and view to handle the information as you want. Get profile pic but simply adding an ImageField to form.
URL:
url(r'^registerfb/$', views.get_name, name='register')
VIEW:
def get_name(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = NameForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
logger.error('Form is valid and running')
logger.error(request.POST.get('your_name'))
logger.error(request.POST.get('your_email'))
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = NameForm()
return render(request, 'facebooklogin/name.html', {'form': form})
FORM:
class NameForm(ModelForm):
class Meta:
model = FBUser
fields = ['your_name', 'your_email',]

Django CMS Aldryn NewsBlog delete Articles from the frontend

I'm trying to get the standard Aldryn Newsblog Buttons working in my Frontend Page. So every User can Add, Delete and Edit Articles(only the articles they created themselves but thats not the question). This is the Menu with the links:
Menu in the Toolbar
So i want to add a Button in my template wich triggers the edit, add or delete prompt: Delete prompt
I hope someone can help me. Thanks in advance.
If you really don't want all employees to see the toolbars, then you're taking on quite a bit of extra work. I would still consider this as an option, as you can apply permissions so that a user can only edit the content you allow, which means that users can take full advantage of Django CMS's built in functionality, which is great.
If you still don't want to take this route then you're going to have to build your own mini admin for your article model. Below I've quickly thrown together an idea for how you can approach this to hopefully help point you in the right direction.
First, your article view should be something like:
from django.views.generic import DetailView
from .models import Article
class ArticleView(DetailView):
context_object_name = 'article'
model = Article
template_name = 'path/to/article.html'
def get_context_data(self, **kwargs):
context = super(ArticleView, self).get_context_data(**kwargs)
context['show_controls'] = (self.request.user.is_authenticated() and
context[self.context_object_name].article == self.request.user)
return context
With the article template like:
<section>
{% if show_controls %}
<div class="controls">
Delete
Edit
</div>
{% endif %}
<article>
...
</article>
</section>
The path to delete view could be a confirm page like the Django admin. So you'd have a view like:
from django.contrib.auth.decorators import login_required
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404, redirect, render
from .models import Article
#login_required
def delete_article(request, article_pk):
if request.method == "POST":
article = get_object_or_404(Article, pk=article_pk)
if request.user != article.author:
raise PermissionDenied
article.delete()
return redirect('/redirect/url')
else:
context = {}
...
return render(request, 'path/to/confirm/delete.html', context)
With a template along the lines of:
<section>
<form method="POST">
{% csrf_token %}
<p>Are you sure you want to delete?</p>
<input type="submit" value="Delete">
</form>
</section>
You'd then create a similar setup for the edit page, navigate the user to a page that has a form where the fields can be amended and submitted etc.

"Returning to that page might cause any action you took to be repeated" - Django

I have a form on my website, that creates an entry in database. So every time when I refresh a page I got this message first:
The page that you're looking for used information that you entered.
Returning to that page might cause any action you took to be repeated.
Do you want to continue?
Obviously I don't want have the same information more than once in my database.
just in case: this is my code (I know there is a lot of crap that needs to be deleted):
#views.py
#login_required
def subject(request,username, subject_name):
subject_id = Subjects.objects.filter(user = request.user).get(name=subject_name)
#Upload form
if request.method == "POST":
if "upload-b" in request.POST:
form = ContentForm(request.POST, request.FILES, instance=subject_id)
if form.is_valid(): # need to add some clean functions
up_f = FileDescription.objects.get_or_create(subject=subject_id,
subject_name=subject_name,
file_type=request.POST['file_type'],
file_uploaded_by = username,
file_name=request.POST['file_name'],
file_description=request.POST['file_description'],
image = request.FILES['image'],
)
form = ContentForm()
#Show uploaded files with respect to clicked session (Homework, Class , Random ... )
homework_files = Homework.homework.filter(subject_name__exact=subject_name,
file_uploaded_by__exact=username)
class_files = ClassPapers.classpapers.filter(subject_name__exact=subject_name)
random_files = RandomPapers.randompapers.filter(subject_name__exact=subject_name,
file_uploaded_by__exact=username)
return render_to_response('subject_content.html', {'form':form,
'subject_name': subject_name,
'class_files': class_files,
'homework_files': homework_files,
'class_files': class_files,
'random_files': random_files,
},
context_instance=RequestContext(request))
#forms.py:
class ContentForm(forms.ModelForm):
file_name =forms.CharField(max_length=255, widget=forms.TextInput(attrs={'size':20}))
file_description = forms.CharField(widget=forms.Textarea(attrs={'rows':4, 'cols':25}))
class Meta:
model = FileDescription
exclude = ('subject', 'subject_name', 'file_uploaded_by')
#template
<div id="sbj-creation-frm">
<h3>Upload File</h3>
<form action="." method="post" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" name="upload-b" class="btn-create" />
</form>
</div>
This message is from the browser; and it will display anytime you try to refresh a page that was displayed as the result of a POST request.
It has no bearing on your code, the browser will display the same message on all websites where you try to refresh the page (hit F5 for example) which was displayed as a result of a previous POST request.
To prevent this from happening, make sure all POST requests redirect to a different view upon completion; and not render templates themselves.
redirect to same page working for me :
header("Location: #");
Just redirect your page to current page after inserting
, it will clear all the values and avoid adding the Duplicate records !
example:
protected void btnAdd_Click(object sender, EventArgs e)
{
//your code
Response.Redirect("Currentpage.aspx",true);
//or
Response.Redirect(Request.Url.AbsoluteUri);
}