I have gone through each step of adding a new database column in postgresql, however when I press a button to save the information to postgresql database after filling in an outlinedtextfield, nothing happens. The information is not saved. I am trying to figure out why but without success at the moment. Any idea as of why it does not work? Appreciate the feedback as usual.
Frontend: Jetpack compose
Backend: Flask App
Database: Postgresql
OBS! If any additional information is needed let me know and I will update the code!
UPDATED CODE:
Kotlin constants and websocket that is taken from renders webservice:
const val BASE_URL="your_render_webservice_api"
constant usually starting with: "https://flask-render... .com"
the websocket is mostly just used for creating a chat with messages (live chats) hence should not affect the general code of posting data.
Flask-app code:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "postgresql: Your_external_render_api_here"
socketio = SocketIO(app)
db = SQLAlchemy(app)
class RelationshipData(db.Model):
__tablename__ = 'relationshipData'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_auth_id = db.Column(db.Integer, db.ForeignKey('userdetails.id'), nullable=False)
relationships = db.Column(db.String(255))
user = db.relationship('Task', backref=db.backref('relationship_Data', lazy=True))
# POSTING Relationships DATA TO DATABASE
@app.route('/relationshipData', methods=['POST'])
def postRelationshipsData():
try: # Added closing parenthesis here
data = request.get_json()
newEmail = data['email']
user = Task.query.filter_by(email=newEmail).first()
if not user:
return jsonify({'error': "No User registered with this mail"}), 400
user_auth_id = user.id
relationships = data['relationships']
# Check if user details already exist
userRelationships = RelationshipData.query.filter_by(user_auth_id=user_auth_id).first()
if userRelationships:
# Update existing user details
userRelationships.relationships = relationships
message = "Updated user details"
else:
# Add new user details
userRelationships = RelationshipData(
user_auth_id=user_auth_id,
relationships=relationships,
)
db.session.add(userRelationships)
message = "Added user details"
db.session.commit()
return jsonify({'message': message}), 201
except Exception as e:
return jsonify({'error': 'Internal Server Error'}), 500
RelationshipModel:
@Keep
@Entity(tableName = "UserRelationDB", indices = [Index(value = ["id"], unique = true)])
@Serializable
data class UserRelationshipModel(
@PrimaryKey
val id: Int? = null,
val relationship: String? = null,
)
User Relation Model:
@Serializable
class UserRelationModel (
val users:List<UserRelationshipModel>
)
Interface UserService (Contains all the methods of posting and getting userdata from all the 3 other database columns. This is connected to AppModule!):
@POST("relationshipData")
suspend fun postUserRelationshipData(@Body data: UserRelationshipModel): Response<Void>
UserAPI class:
class UserApi @Inject constructor(
private val userService: UserService,
private val webSocketManager: WebSocketManager
) {
suspend fun postRelationshipsData(data: UserRelationshipModel): Response<Void> {
return userService.postRelationshipsData(data)
}
}
User Repo:
class Repo @Inject constructor(private val userApi: UserApi) {
suspend fun postRelationshipsData(data: UserRelationshipModel): Response<Void> {
return userApi.postRelationshipsData(data)
}
}
Interface Dao:
@Dao
interface UserRelationshipDataModelDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertUserRelationship(user: UserRelationshipModel)
@Update
suspend fun updateUserRelationship(user: UserRelationshipModel)
@Query("SELECT * FROM UserRelationDB WHERE id = :userId")
suspend fun getUserById(userId: Int): UserRelationshipModel?
@Query("SELECT * FROM UserRelationDB LIMIT 1")
suspend fun getLoggedInUser(): UserRelationshipModel?
@Query("DELETE FROM UserRelationDB")
suspend fun deleteAllUsers()
}
UserRelationshipLayoutScreen:
var relationship by remember { mutableStateOf("") }
......
item {
UserInfo(
initialUserData = relationship,
label = "Relationship",
onValueChange = { relationship = it }
)
}
....
Button OnClick:
onClick = {
scope.launch {
val userData = UserRelationshipModel(
relationships = relationship
)
userCredentialsRelationshipViewModel.postUserRelationshipData(context, userData) { result ->
when (result) {
NetworkResult.Loading -> {
showLoadingAnim = true
}
is NetworkResult.Error -> {
showLoadingAnim = false
}
is NetworkResult.Success -> {
showLoadingAnim = false
userRelationshipHiltViewModel.insertUserRelationship(userData)
// Navigate the user forward
navController.navigate("${NavigationItem.UserDetails.route}/${selectedGender}")
}
}
}
Log.d("relationship model clicked", userData.toString())
}
},
UserCredentialsRelationshipViewModel:
@HiltViewModel
class UserCredentialsRelationshipViewModel@Inject constructor(private val repo: Repo) : ViewModel() {
fun postUserRelationshipData(
context: Context, userData: UserRelationshipModel,
handleResult: (NetworkResult<String>) -> Unit
) {
viewModelScope.launch {
try {
handleResult(NetworkResult.Loading)
val result = repo.postRelationshipsData(data = userData)
if (result.isSuccessful) {
handleResult(NetworkResult.Success("User relationship added successfully"))
Toast.makeText(context, "User relationship added successfully", Toast.LENGTH_SHORT)
.show()
} else {
handleResult(NetworkResult.Error("Something went wrong"))
}
} catch (e: Exception) {
handleResult(NetworkResult.Error("Something went wrong"))
Toast.makeText(context, e.message.toString(), Toast.LENGTH_LONG).show()
Log.d("postDataError", e.message.toString())
e.printStackTrace()
}
}
}
}
UserRelationshipHiltViewModel:
@HiltViewModel
class UserRelationshipHiltViewModel @Inject constructor(private val userRelationshipDataModelDao: UserRelationshipDataModelDao)
: ViewModel() {
private val _loggedInUser = MutableLiveData<UserRelationshipModel?>()
val loggedInUser: LiveData<UserRelationshipModel?> get() = _loggedInUser
fun insertUserRelationship(user: UserRelationshipModel) {
viewModelScope.launch {
try {
userRelationshipDataModelDao.insertUserRelationship(user)
} catch (e: Exception) {
e.printStackTrace()
}
}
}
fun deleteUser() {
viewModelScope.launch {
try {
userRelationshipDataModelDao.deleteAllUsers()
} catch (e: Exception) {
e.printStackTrace()
}
}
}
// Update an existing user
fun updateUser(user: UserRelationshipModel) {
viewModelScope.launch {
_loggedInUser.postValue(user)
userRelationshipDataModelDao.updateUserRelationship(user)
}
}
// Get a user by their ID
fun getUserById(userId: Int) {
viewModelScope.launch {
val user = userRelationshipDataModelDao.getUserById(userId)
}
}
fun getLoggedInUser() {
viewModelScope.launch {
try {
val user = userRelationshipDataModelDao.getLoggedInUser()
_loggedInUser.postValue(user)
} catch (e: Exception) {
_loggedInUser.postValue(null) // or handle the exception as needed
}
}
}
}
UserInfoDatabase:
@Database(entities = [UserDataModel::class,UserMatchEntity::class, UserRelationshipModel::class,],version =6,exportSchema = true)
@TypeConverters(Converters::class)
abstract class UserInfoDatabase:RoomDatabase() {
abstract fun userDataModelDao():UserDataModelDao
abstract fun userMatch():UserMatchDao
abstract fun userRelationshipDataModelDao(): UserRelationshipDataModelDao
}
AppModule:
@Singleton
@Provides
fun provideRelationshipDao(userInfoDatabase: UserInfoDatabase): UserRelationshipDataModelDao{
return userInfoDatabase.userRelationshipDataModelDao()
}
Based on the provided code, it seems like the issue might be related to the communication between your Jetpack Compose frontend and the Flask backend. Here are a few steps to debug and ensure that the data is being sent and saved correctly:
Check Network Requests: Ensure that the network request is being made correctly from your Jetpack Compose app to the Flask backend. You can use tools like Logcat
in Android Studio to log the request and response.
Verify Backend Endpoint: Ensure that the Flask endpoint /relationshipData
is correctly set up and accessible. You can test this using tools like Postman
or curl
.
Check for Errors: Ensure that there are no errors in the backend when processing the request. Check the Flask logs for any errors.
Debugging Steps:
Here is an updated version of the relevant parts of your code with added logging for debugging:
@app.route('/relationshipData', methods=['POST'])
def postRelationshipsData():
try:
data = request.get_json()
print(f"Received data: {data}") # Log the received data
newEmail = data['email']
user = Task.query.filter_by(email=newEmail).first()
if not user:
return jsonify({'error': "No User registered with this mail"}), 400
user_auth_id = user.id
relationships = data['relationships']
userRelationships = RelationshipData.query.filter_by(user_auth_id=user_auth_id).first()
if userRelationships:
userRelationships.relationships = relationships
message = "Updated user details"
else:
userRelationships = RelationshipData(
user_auth_id=user_auth_id,
relationships=relationships,
)
db.session.add(userRelationships)
message = "Added user details"
db.session.commit()
return jsonify({'message': message}), 201
except Exception as e:
print(f"Error: {e}") # Log the error
return jsonify({'error': 'Internal Server Error'}), 500
Add logging to the UserCredentialsRelationshipViewModel
to ensure the request is being made and the response is handled correctly:
@HiltViewModel
class UserCredentialsRelationshipViewModel @Inject constructor(private val repo: Repo) : ViewModel() {
fun postUserRelationshipData(
context: Context, userData: UserRelationshipModel,
handleResult: (NetworkResult<String>) -> Unit
) {
viewModelScope.launch {
try {
handleResult(NetworkResult.Loading)
val result = repo.postRelationshipsData(data = userData)
Log.d("postUserRelationshipData", "Response: ${result.code()} - ${result.message()}") // Log the response
if (result.isSuccessful) {
handleResult(NetworkResult.Success("User relationship added successfully"))
Toast.makeText(context, "User relationship added successfully", Toast.LENGTH_SHORT).show()
} else {
handleResult(NetworkResult.Error("Something went wrong"))
}
} catch (e: Exception) {
handleResult(NetworkResult.Error("Something went wrong"))
Toast.makeText(context, e.message.toString(), Toast.LENGTH_LONG).show()
Log.d("postDataError", e.message.toString())
e.printStackTrace()
}
}
}
}
Ensure that the UserRelationshipModel
is correctly populated and logged:
onClick = {
scope.launch {
val userData = UserRelationshipModel(
relationships = relationship
)
Log.d("ButtonOnClick", "UserData: $userData") // Log the user data
userCredentialsRelationshipViewModel.postUserRelationshipData(context, userData) { result ->
when (result) {
NetworkResult.Loading -> {
showLoadingAnim = true
}
is NetworkResult.Error -> {
showLoadingAnim = false
}
is NetworkResult.Success -> {
showLoadingAnim = false
userRelationshipHiltViewModel.insertUserRelationship(userData)
navController.navigate("${NavigationItem.UserDetails.route}/${selectedGender}")
}
}
}
}
}
By adding these logs, you can trace the flow of data and identify where the issue might be occurring. Ensure that the data is correctly sent from the frontend, received by the backend, and saved to the database.