So I am trying to connect my Django rest framework backend with my Flutter UI and I'm having some issues. I currently only have a register, login and logout links that are fully function on the backend, I tested them in postman and they work. But when I try to connect to them through my Flutter app I get a 404 error saying that it couldn't find the API link. I can't seem to figure out what the problem is and I've been trying at it for a couple of days now lol any help is help.
Here is my code:
DRF Backend:
views.py:
from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view, authentication_classes, permission_classes
from rest_framework.authentication import TokenAuthentication
from rest_framework.permissions import IsAuthenticated, AllowAny
from .serializers import RegistrationSerializer
from rest_framework.authtoken.models import Token
@api_view(['POST'])
@permission_classes([AllowAny])
def registration_view(request):
print("got here first")
if request.method == 'POST':
print("got here")
serializer = RegistrationSerializer(data=request.data)
data = {}
if serializer.is_valid():
print("got valid")
user = serializer.save()
data['response'] = "succesfully registered a new user."
data['email'] = user.email
data['username'] = user.username
token = Token.objects.get(user=user).key
data['token'] = token
else:
data = serializer.errors
return Response(data)
@api_view(['POST'])
@permission_classes([IsAuthenticated])
def logout_view(request):
cToken = Token.objects.get(user=request.user)
cToken.delete()
return Response("Succesfully logged out")
urls.py:
from django.urls import path
from .views import registration_view, logout_view
from rest_framework.authtoken.views import obtain_auth_token
# from rest_framework.permissions import IsAuthenticated
app_name = "backApp"
urlpatterns = [
path('register', registration_view, name="register"),
path('login', obtain_auth_token, name="login"),
path('logout', logout_view, name="logout")
]
serializers.py:
from rest_framework import serializers
from backApp.models import User
class RegistrationSerializer(serializers.ModelSerializer):
password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)
class Meta:
model = User
fields = ['email', 'username', 'password', 'password2']
extra_kwargs = {
'password': {'write_only': True}
}
def save(self):
user = User(
email=self.validated_data['email'],
username=self.validated_data['username'],
)
password = self.validated_data['password']
password2 = self.validated_data['password2']
if password != password2:
raise serializers.ValidationError({'password': 'Passwords must match.'})
user.set_password(password)
user.save()
return user
models.py:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings
from django.db.models.signals import post_save
from django.dispatch import receiver
from rest_framework.authtoken.models import Token
class MyUserManager(BaseUserManager):
def create_user(self, email, username, first_name, last_name,password=None):
if not email:
raise ValueError("Users must have an email address.")
if not username:
raise ValueError("Users must have a username.")
if not first_name:
raise ValueError("Users must have a first name.")
if not last_name:
raise ValueError("Users must have a last name.")
user = self.model(
email=self.normalize_email(email),
username=username,
first_name=first_name,
last_name=last_name
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password, first_name, last_name):
user = self.create_user(
email=self.normalize_email(email),
username=username,
password=password,
first_name=first_name,
last_name=last_name
)
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=80, unique=True)
first_name = models.CharField(verbose_name="first name", max_length=80)
last_name = models.CharField(verbose_name="last name", max_length=80)
tap_coins = models.IntegerField(default=0)
username = models.CharField(max_length=80, unique=True)
date_joined = models.DateTimeField(verbose_name="date joined", auto_now_add=True)
last_login = models.DateTimeField(verbose_name="last login", auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username", "first_name", "last_name"]
objects = MyUserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
Flutter:
main.dart:
import 'package:TapCoinsApp/api/api.dart';
import 'package:TapCoinsApp/screens/profile.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './screens/register.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => UserProvider()),
// ChangeNotifierProvider(create: (context) => BankProvider())
],
child: MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: HomePage(),
),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
final userP = Provider.of<UserProvider>(context);
// final bankP = Provider.of<BankProvider>(context);
int prizeCoins = 0;
int coinsTapped = 0;
return MaterialApp(
home: SafeArea(
child: DefaultTabController(
length: 2,
child: Scaffold(
appBar: TabBar(
tabs: [
Tab(icon: new Icon(Icons.home)),
Tab(icon: new Icon(Icons.person_outline_rounded)),
],
labelColor: Colors.red,
unselectedLabelColor: Colors.yellow,
indicatorSize: TabBarIndicatorSize.label,
indicatorPadding: EdgeInsets.all(5.0),
indicatorColor: Colors.red,
),
backgroundColor: Colors.purple,
body: Stack(
children: <Widget>[
TabBarView(children: [
new Scaffold(
backgroundColor: Colors.purple,
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (ctx) => RegisterUser()));
},
),
),
ProfilePage(),
]),
],
),
),
),
),
);
}
}
register.dart:
import 'package:TapCoinsApp/api/api.dart';
import 'package:TapCoinsApp/models/user.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class RegisterUser extends StatefulWidget {
@override
_RegisterUserState createState() => _RegisterUserState();
}
class _RegisterUserState extends State<RegisterUser> {
final userFirstNameController = TextEditingController();
final userLastNameController = TextEditingController();
final userEmailController = TextEditingController();
final userUserNameController = TextEditingController();
final userPasswordController = TextEditingController();
final userPassword2Controller = TextEditingController();
void _onRegister() {
final String firstVal = userFirstNameController.text;
final String lastVal = userLastNameController.text;
final String emailVal = userEmailController.text;
final String userVal = userUserNameController.text;
final String passwordVal = userPasswordController.text;
final String password2Val = userPassword2Controller.text;
if (firstVal.isNotEmpty &&
lastVal.isNotEmpty &&
emailVal.isNotEmpty &&
userVal.isNotEmpty &&
passwordVal.isNotEmpty &&
password2Val.isNotEmpty) {
final User user = User(
firstName: firstVal,
lastName: lastVal,
email: emailVal,
userName: userVal,
password: passwordVal,
password2: password2Val);
print(user);
Provider.of<UserProvider>(context, listen: false).registerUser(user);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Register!")),
body: ListView(
children: [
Container(
child: Column(
children: [
TextField(
controller: userFirstNameController,
decoration: InputDecoration(labelText: "First Name: "),
),
TextField(
controller: userLastNameController,
decoration: InputDecoration(labelText: "Last Name: ")),
TextField(
controller: userEmailController,
decoration: InputDecoration(labelText: "Email: ")),
TextField(
controller: userUserNameController,
decoration: InputDecoration(labelText: "Username: ")),
TextField(
controller: userPasswordController,
decoration: InputDecoration(labelText: "Password: ")),
TextField(
controller: userPassword2Controller,
decoration:
InputDecoration(labelText: "Confirm Pas