Implement Facebook Log In with Django - 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',]

Related

Redirect user to previous page after submitting form in Django

I am trying to redirect the user to the previous page once a form is submitted.
User starts on Venue_id page (http..../show_venue/23/) and clicks on product id
User is directed to Product_id page (http..../show_product.../1/) and find a form
User completes form and submit on Product_id page
user redirect to Venue_id page upon form submission (from http..../show_venue/23/)
http..../show_venue/23/ -> http..../show_product.../1/ -> http..../show_venue/23/
I found a good source of inspiration on the forum, particularly on this page (How to redirect to previous page in Django after POST request)
(I also found some posts using the history of the browser. But decided to stick to this method, as it seems using browser history doesn't always work)
I used next as suggested in the code in the above post. But there is something I don't understand which is probably why I get this wrong.
Here is the different codes in views I tried for next:
next = request.POST.get('next','/') => this sends me to '/', which
is not what i want. However it seemed to work for the person who
posted the original question even though they were trying to NOT be redirect to '/';
next = request.POST.get('next','') => sends me to my product_id page url, but the page is empty
next = request.POST.get('next') => this one was suggested in other posts, but I get Field 'id' expected a number but got 'None'.
I might be completely wrong, but I feel the key is probably there. How to do refer to "show_venue/<venue_id>" into "next = request.POST.get('next','show_venue/<venue_id>')"?
In terms of code
Views
def show_product_from_venue(request, product_id):
product = Product.objects.get(pk=product_id)
form = ReviewForm()
venue_form = VenueForm()
submitted = False
next = request.POST.get('next')
if request.method == "POST" and 'btnvenue_form' in request.POST:
venue_form = VenueForm(request.POST)
if venue_form.is_valid():
venue_form.save()
return HttpResponseRedirect(next)
else:
venue_form = VenueForm
if 'submitted' in request.GET:
submitted = True
else:
print(form.errors)
return render(request,"main/show_product_from_venue.html", {'form':form, 'submitted':submitted, 'product':product, 'venue_form':venue_form, 'data':data})
Venue_id (template)
<a href="{% url 'show-product-from-venue' product.id %}?next={{ request.path|urlencode }} method="POST">
Product_id(template with form)
<form action="{% url 'show-product-from-venue' product.id%}" method="POST">
{% csrf_token %}
{{ form}}
<input type="submit" name="btnreview_form" name="next" value="{{ request.GET.next }}" class="btn btn-primary custom-btn">
</form>
urls
#VENUE PAGE
path('show_venue/<venue_id>', views.show_venue,name="show-venue"),
#PRODUCT
path('show_product_from_venue/<product_id>', views.show_product_from_venue,name="show-product-from-venue"),
If you want to go previous pages then just add the root where exactly you want to go:
In views:
EX:
return HttpResponseRedirect("/users/")

File Uploads via FormModel (Official description), but form.is_valid is always false

I'm trying to use FormModel to handle a file upload, but form.is_valid() is always returning false, and never shows any kind of error.Following is the code snippet from models.py,forms.py,views.py and my POST request.
models.py
class Pics(models.Model):
id = models.AutoField(primary_key=True,)
username = models.CharField(max_length=45)
path = models.ImageField(upload_to=img_path)
forms.py
class PicsForm(forms.ModelForm):
class Meta:
model = Pics
fields = ['username','path']
views.py
def uploads(request:HttpRequest):
form = PicsForm(request.POST,request.FILES)
if form.is_valid():
# instance = Pics(username=request.POST['username'],path=request.FILES['file'])
# instance.save()
form.save()
print('***')
else:
print('&&&&&&&&&&&&&')
return HttpResponse("succeed")
here is my postman set
I expect the output of '***', but the actual output is '&&&&&&&&&&&&&'
Be sure that your html form has 'enctype="multipart/form-data"' and your file upload input has name 'path', for example, your form should be like:
<form action="some_url" method="POST" enctype="multipart/form-data">
<input type='text' name='username'>
<input type="file" name="path">
</form>
I suspect Postman is not setting a CSRF token. Is there a reason that you are testing with Postman rather than creating an HTML form and submitting to it through your browser? I would do the latter, and if there is still a problem you could show us your template.

How to correctly redirect/submit POST request from a form (wtforms) to a REST api (flask-restless)?

I can't find a proper way to redirect data from submitted form to a REST api.
Currently - like in example below - "POST" method is handled in the view/route (see route "add_person()").
My sample data model (SQLAlchemy-based):
class Person(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20))
Form for rendering via html (wtforms-based):
class PersonForm(FlaskForm):
name = TextField("Person name", validators=[DataRequired()])
View/route declaration:
#views.route('add_person', methods=["GET", "POST"])
def add_person():
form = PersonForm()
if request.method == 'POST' and form.validate_on_submit():
person = Person()
person.name = form.name.data
db.session.add(person)
db.session.commit()
return redirect(url_for('view.add_person'))
return render_template('person_add.html', form=form)
HTML template:
<form method="POST" action="/add_person">
{{ form.csrf_token }}
{{ form.name.label }} {{ form.name(size=20) }}
<input type="submit" value="Submit">
</form>
Now I'd like to delegate database/CRUD related actions to a REST api.
API endpoint generated for a "Person" data model is: "/api/person".
If I switch form's "action" from:
"/add_person"
to:
"/api/person",
then I'm redirected to the API url, so I guess that's not a proper way of doing that.
I think I still should be using the view/route handling and make a POST api call there instead of persisting the "Person" object. Is this the cleanest solution? How could I approach this?
I'll answer this myself.
I ended up with staying with form's "/add_person" POST action that's handled in Flask, and then making request to API endpoint using Python "requests" library.

Scrapy FormRequest How to check if URL is needed

I am new to scrapy and in general web tech.
While working on a scrapy example to perform auto login. I came across 1 field , referrer url . I am wondering when do i need to this.
return scrapy.FormRequest.from_response(
response,
url='www.myreferrer.com', #when do i need this ???
formnumber=1,
formdata=self.data['formdata'],
callback=self.after_login
)
I tested with and without it and it works in both instances.
I understand that referrer url is for security but how do i determine from html code that i need or dont need this ?
ADDON
The following html form required the url to be defined :
<form id="login" enctype="multipart/form-data" method="post" action="https:///myshop.com/login/index.php?route=account/login">
I am a returning customer.<br>
<br>
<b>E-Mail Address:</b><br>
<input type="text" name="email">
<br>
<br>
<b>Password:</b><br>
<input type="password" name="password">
<br>
Forgotten Password<br>
<div style="text-align: right;"><a class="button" onclick="$('#login').submit();"><span>Login</span></a></div>
</form>`
class FormRequest(Request):
# delete some code here
#classmethod
def from_response(cls, response, formname=None, formid=None, formnumber=0, formdata=None,
clickdata=None, dont_click=False, formxpath=None, formcss=None, **kwargs):
url = _get_form_url(form, kwargs.pop('url', None))
def _get_form_url(form, url):
if url is None:
return urljoin(form.base_url, form.action)
return urljoin(form.base_url, url)
if the url is empty, it uses form tag's action attribute to get the URL.
if the url is not empty, then it use the URL you give to it.
the base_url comes from the response.
def _get_form(response, formname, formid, formnumber, formxpath):
"""Find the form element """
root = create_root_node(response.text, lxml.html.HTMLParser,
base_url=get_base_url(response))
so, when the action attribute does not exist or the login requests is not sent to the action URL, you need to pass the argument.

"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);
}