I have a django web app created already, with a simple user table (username/password). I also have an iOS app (swift) set up, and was wondering what would be the best way to go about coding the login system?
From what I have gathered from research - I will have to make REST calls to an API created from the existing django app. Would it be better to use TastyPie or Django Rest Framework for this?
Are there specific things I have to keep in mind when doing the API for the django app? Also, what would be the url that i use for the rest calls, would it be the existing server that the django web app is on?
My qualifications for this answer come from 3 months of work on an identical system to the one you described. Your question holds many parts, so I will begin with the server.
From what I have gathered from research - I will have to make REST
calls to an API created from the existing django app.
Correct, your clients (app, web, or otherwise) should communicate with your server through an API.
I have a django web app created already, with a simple user table
(username/password).
Hopefully your "simple user table" uses the default Django user model, as 3rd party security frameworks are going to make your life much simpler when protecting an open API. Although it depends on your security needs, I recommend the Django OAuth Toolkit for its OAuth2 support, password reset workflow, and prebuilt URL endpoints for common authentication interactions. Even better, this library natively supports the Django Rest Framework.
Would it be better to use TastyPie or Django Rest Framework for this?
I do not have experience with TastyPie, however I can vouch for DRF. The generic views matched our major API design points well, and DRF's similarities to the Django Form API means our custom dashboard has a wonderful symmetry to the API. I recommend you first map out the major components of your API, then research both frameworks to learn which will fit your project best.
(Bonus Tip: If this is your first time designing a REST API, flip through a copy of Build APIs You Won't Hate)
Also, what would be the url that i use for the rest calls, would it be
the existing server that the django web app is on?
Common practice is to host your API URLs on a subdomain, followed by a version path, such as api.example.com/v1/
. The subdomain separates your URLs from core web pages and denotes these endpoints are specifically for your API. The version path is a good practice to support legacy APIs as you upgrade.
Are there specific things I have to keep in mind when doing the API
for the django app?
Security is a big one. Depending on your API, there could be some sensitive parts of your application exposed to the public. Write tests to ensure you are not poking new holes in your security, and leave OAuth to the pros. Other than that, make sure your server is ready to handle your traffic, and spend plenty of time perfecting your model.
I also have an iOS app (swift) set up, and was wondering what would be
the best way to go about coding the login system?
When coding client-side, always use best practices to retrieve and store credentials. Communicate with your server over SSL, store only what you need, and destroy the expected data when a user logs out. Remember, if your app stores usernames and passwords, it stores sensitive data (because people have a funny tendency to reuse passwords for important things). Finally, clearly communicate the login process to your users with helpful error messages and loading animations. As you can see by now, the login process is fairly complex, but if executed well it will feel effortless.
Login Form
class ViewController: UIViewController, UITextViewDelegate, UITextFieldDelegate{
@IBOutlet var txtemail: UITextField!
@IBOutlet var txtpass1: UITextField!
@IBOutlet var lbl1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
txtemail.becomeFirstResponder()
}
@IBAction func btnlogin(_ sender: UIButton) {
let useremail = txtemail.text
let userpass = txtpass1.text
if ((useremail!.isEmpty) || (userpass!.isEmpty))
{
Displayalert(usermessage: "All Fields Are Required...")
}
// MARK:- Display Id
let useremailstore = UserDefaults.standard.string(forKey: "useremail")
let userpasswordstore = UserDefaults.standard.string(forKey: "userpass")
// MARK:- Login New Page
if useremail != useremailstore
{
Displayalert(usermessage: "Enter Valid Email")
}
else if userpass != userpasswordstore
{
Displayalert(usermessage: "Enter Valid Password..")
}
else
{
let wel = storyboard?.instantiateViewController(withIdentifier: "welcomeViewController")as! welcomeViewController
self.navigationController?.pushViewController(wel, animated: true)
}
if useremailstore == useremail
{
if userpasswordstore == userpass
{
UserDefaults.standard.set(true, forKey: "userlogin")
UserDefaults.standard.synchronize()
self.dismiss(animated: true, completion: nil)
}
}
}
@IBAction func btnforgotpass(_ sender: UIButton) {
let pass = storyboard?.instantiateViewController(withIdentifier: "NewPassViewController")as! NewPassViewController
self.navigationController?.pushViewController(pass, animated: true)
}
@IBAction func btnnewacc(_ sender: UIButton) {
let login = storyboard?.instantiateViewController(withIdentifier: "RegisterViewController")as! RegisterViewController
self.navigationController?.pushViewController(login, animated: true)
}
// MARK:- Alert function
func Displayalert(usermessage:String)
{
let Myalert = UIAlertController(title: "Alert", message: usermessage, preferredStyle: UIAlertControllerStyle.alert)
let Action = UIAlertAction(title: "ok", style: UIAlertActionStyle.default, handler: nil)
Myalert.addAction(Action)
self.present(Myalert, animated: true, completion: nil)
}
// MARK:- Password set
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == txtpass1
{
let text = txtpass1.text
let newLength = (text?.characters.count)! + string.characters.count - range.length
return newLength <= 8 // Bool
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
txtemail.resignFirstResponder()
txtpass1.resignFirstResponder()
return false
}
override func viewWillAppear(_ animated: Bool) {
txtemail.text = ""
txtpass1.text = ""
}
Register Form
class RegisterViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
@IBOutlet var txtmail: UITextField!
@IBOutlet var txtpass: UITextField!
@IBOutlet var txtrepass: UITextField!
var defaults = UserDefaults.standard
var dict : NSMutableDictionary = ["":""]
override func viewDidLoad() {
super.viewDidLoad()
txtmail.becomeFirstResponder()
return
// Do any additional setup after loading the view.
}
// MARK:- Register
@IBAction func btnregister(_ sender: UIButton) {
let useremail = txtmail.text
let userpass = txtpass.text
let userrepass = txtrepass.text
if((useremail!.isEmpty) || (userpass!.isEmpty) || (userrepass!.isEmpty))
{
Displayalert(usermessage: "All Fields Are Required....")
}
if userpass != userrepass
{
Displayalert(usermessage: "Your Re-Password is Not valid....")
txtrepass.text = ""
}
let validEmail = isValidEmail(stringValue: txtmail.text!)
if validEmail
{
print("Email is Valid")
}
else
{
Displayalert(usermessage: "Email Is Not Valid...")
}
//MARK:- Store Data
UserDefaults.standard.set(useremail, forKey: "useremail")
UserDefaults.standard.set(userpass, forKey: "userpass")
UserDefaults.standard.synchronize()
//MARK:- Conformation message
let Myalert = UIAlertController(title: "Alert", message: "Registation is Successful.Thank you...", preferredStyle: UIAlertControllerStyle.alert)
let Action = UIAlertAction(title: "ok", style: UIAlertActionStyle.default) { action in self.performSegue(withIdentifier: "firstview", sender: self)}
Myalert.addAction(Action)
self.present(Myalert, animated: true, completion: nil)
}
//MARK:- Alert Call
func Displayalert(usermessage:String)
{
let Myalert = UIAlertController(title: "Alert", message: usermessage, preferredStyle: UIAlertControllerStyle.alert)
let Action = UIAlertAction(title: "ok", style: UIAlertActionStyle.default, handler: nil)
Myalert.addAction(Action)
self.present(Myalert, animated: true, completion: nil)
}
//MARK:- Email Valid
func isValidEmail(stringValue: String) ->Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailTest.evaluate(with: stringValue)
}
//MARK:- Same & re-Password
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
if textField == txtpass
{
let text = txtpass.text
let newLength = (text?.characters.count)! + string.characters.count - range.length
return newLength <= 8 // Bool
}
if textField == txtrepass
{
let text = txtrepass.text
let newLength = (text?.characters.count)! + string.characters.count - range.length
return newLength <= 8 // Bool
}
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
txtmail.resignFirstResponder()
txtpass.resignFirstResponder()
txtrepass.resignFirstResponder()
return false
}