diff --git a/django_project/django_project/urls.py b/django_project/django_project/urls.py index 03e8563781e11a71dda1e3da7ad511d65c2b0bd4..408ad439f7fb6443c3afc83897b80e141888df57 100644 --- a/django_project/django_project/urls.py +++ b/django_project/django_project/urls.py @@ -21,7 +21,7 @@ from myapp import views urlpatterns = [ path('admin/', admin.site.urls), path('register/', views.register_view, name='register'), - path('login/', views.login_view, name='login'), + path('', views.login_view, name='login'), # default view path('account/', views.account_view, name='account'), path('delete/', views.delete_account_view, name='delete_account'), path('logout/', views.logout_view, name='logout'), @@ -29,4 +29,5 @@ urlpatterns = [ path('groups/create/', views.group_create_view, name='group_create'), path('groups/<int:group_id>/update/', views.group_update_view, name='group_update'), path('groups/<int:group_id>/delete/', views.group_delete_view, name='group_delete'), + path('groups/<int:group_id>/', views.group_detail_view, name='group_detail'), ] diff --git a/django_project/myapp/templates/myapp/account.html b/django_project/myapp/templates/myapp/account.html index df2a9210d563ba4b01a2990f9e753e58f6d98005..8df43ed821325b1807c9bc7c046f364ceef7070e 100644 --- a/django_project/myapp/templates/myapp/account.html +++ b/django_project/myapp/templates/myapp/account.html @@ -1,14 +1,12 @@ -<!DOCTYPE html> -<html> -<head> - <title>Account</title> -</head> -<body> +{% extends 'myapp/base.html' %} + +{% block title %}Account{% endblock %} + +{% block content %} <h1>Account Page</h1> <p>Username: {{ user.username }}</p> <p>Email: {{ user.email }}</p> <p><a href="{% url 'delete_account' %}">Delete Account</a></p> <p><a href="{% url 'logout' %}">Logout</a></p> -</body> -</html> +{% endblock %} diff --git a/django_project/myapp/templates/myapp/base.html b/django_project/myapp/templates/myapp/base.html new file mode 100644 index 0000000000000000000000000000000000000000..eb5f228c51ad17fc0a11d15815ac25d85c8c5f9d --- /dev/null +++ b/django_project/myapp/templates/myapp/base.html @@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>{% block title %}My Project{% endblock %}</title> + <style> + nav { + background-color: #333; + overflow: hidden; + } + nav ul { + list-style-type: none; + margin: 0; + padding: 0; + } + nav li { + float: left; + } + nav li a { + display: block; + color: #fff; + text-align: center; + padding: 14px 20px; + text-decoration: none; + } + nav li a:hover { + background-color: #111; + } + .container { + margin: 20px; + } + </style> +</head> +<body> + <!-- Menu Bar --> + <nav> + <ul> + <li><a href="{% url 'account' %}">Account</a></li> + <li><a href="{% url 'group_list' %}">Groups</a></li> + <li><a href="{% url 'logout' %}">Logout</a></li> + </ul> + </nav> + + <!-- Page Content --> + <div class="container"> + {% block content %} + <!-- Content from child templates goes here --> + {% endblock %} + </div> +</body> +</html> + diff --git a/django_project/myapp/templates/myapp/group_detail.html b/django_project/myapp/templates/myapp/group_detail.html new file mode 100644 index 0000000000000000000000000000000000000000..590ab3c9e2dc75e4699c17019800e1d33973ed8e --- /dev/null +++ b/django_project/myapp/templates/myapp/group_detail.html @@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="UTF-8"> + <title>Group Details</title> + <style> + body { font-family: Arial, sans-serif; margin: 2em; } + </style> +</head> +<body> + <h1>Group Details</h1> + {% if error %} + <p style="color: red;">{{ error }}</p> + {% else %} + <p><strong>Group Name:</strong> {{ group.name }}</p> + <p><strong>Group ID:</strong> {{ group.id }}</p> + {% endif %} + <p><a href="{% url 'group_list' %}">Back to Groups</a></p> +</body> +</html> + diff --git a/django_project/myapp/templates/myapp/group_list.html b/django_project/myapp/templates/myapp/group_list.html index 1c5ee84cfac799186bf595191e51b23401d5f14a..d98d05149c284cea3feaeeb1a67befcdd48e8e87 100644 --- a/django_project/myapp/templates/myapp/group_list.html +++ b/django_project/myapp/templates/myapp/group_list.html @@ -3,24 +3,27 @@ <head> <meta charset="UTF-8"> <title>Group List</title> + <style> + body { font-family: Arial, sans-serif; margin: 2em; } + ul { list-style-type: none; padding: 0; } + li { margin-bottom: 0.5em; } + a { text-decoration: none; color: #2a5d9f; } + a:hover { text-decoration: underline; } + </style> </head> <body> <h1>Groups</h1> {% if error %} - <p style="color: red;">{{ error }}</p> + <p style="color: red;">{{ error }}</p> {% endif %} <ul> {% for group in groups %} - <li> - {{ group.name }} - <a href="{% url 'group_update' group.id %}">Edit</a> - <a href="{% url 'group_delete' group.id %}">Delete</a> - </li> + <li> + <a href="{% url 'group_detail' group.id %}">{{ group.name }}</a> + </li> {% empty %} - <li>No groups available.</li> + <li>No groups available.</li> {% endfor %} </ul> - <p><a href="{% url 'group_create' %}">Create New Group</a></p> </body> </html> - diff --git a/django_project/myapp/templates/myapp/register.html b/django_project/myapp/templates/myapp/register.html index 11169e8491878c01c7e7af63143b9aff42bafc99..9bcfe10ab406c074ebc6ff3f36f843b265355a3b 100644 --- a/django_project/myapp/templates/myapp/register.html +++ b/django_project/myapp/templates/myapp/register.html @@ -17,8 +17,11 @@ {% csrf_token %} <label for="id_name">Name:</label> <input type="text" name="name" id="id_name" required><br><br> + + <label for="id_username">Username:</label> + <input type="text" name="username" id="id_username" required><br><br> - <label for="id_email">Email:</label> + <label for="id_email">Email:</label> <input type="email" name="email" id="id_email" required><br><br> <label for="id_password">Password:</label> diff --git a/django_project/myapp/views.py b/django_project/myapp/views.py index 5bf7b2825ea0542ae8981db4edf47c2c3c9416f5..2285b2f3b88075d57aaa77eb9614e07abf2da999 100644 --- a/django_project/myapp/views.py +++ b/django_project/myapp/views.py @@ -27,14 +27,14 @@ def register_view(request): name = request.POST.get('name', '').strip() email = request.POST.get('email', '').strip() password = request.POST.get('password', '').strip() - + username = request.POST.get('username', '').strip() if not name or not email or not password: - context['error'] = "Name, email, and password are required." + context['error'] = "Name, email, username and password are required." return render(request, 'myapp/register.html', context) try: # Create the user with the hashed password via the Rust extension. - rust_crud_api.create_user(db_url, name, email, password) + rust_crud_api.create_user(db_url, name, email, password, username) # Redirect to the login page after successful registration. return redirect('login') except Exception as e: @@ -135,11 +135,13 @@ def group_list_view(request): List all groups. """ db_url = settings.DATABASE_URL + context = {} try: groups = rust_crud_api.get_all_groups(db_url) + context['groups'] = groups except Exception as e: - return render(request, 'myapp/group_list.html', {'error': str(e)}) - return render(request, 'myapp/group_list.html', {'groups': groups}) + context['error'] = f"An error occurred: {e}" + return render(request, 'myapp/group_list.html', context) def group_create_view(request): """ @@ -216,3 +218,18 @@ def group_delete_view(request, group_id): except Exception as e: context['error'] = f"Error retrieving group: {e}" return render(request, 'myapp/group_delete.html', context) + +def group_detail_view(request, group_id): + """ + Fetch a single group's details using the Rust extension and display them. + """ + db_url = settings.DATABASE_URL + context = {} + try: + group = rust_crud_api.get_group(db_url, group_id) + if group is None: + return HttpResponseNotFound("Group not found.") + context['group'] = group + except Exception as e: + context['error'] = f"An error occurred: {e}" + return render(request, 'myapp/group_detail.html', context) diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs index deea586e00b30a52073d49d7632842abf0750ec1..3425e87583d1b5dc0034022e07374e0c23181fa1 100644 --- a/rust_crud_api/src/db/groups.rs +++ b/rust_crud_api/src/db/groups.rs @@ -81,6 +81,7 @@ pub fn get_group_members(db_url: &str, group_id: i32) -> PyResult<Vec<User>> { id: row.get(0), name: row.get(1), email: row.get(2), + username: row.get(3), }).collect(); Ok(users) diff --git a/rust_crud_api/src/db/init.rs b/rust_crud_api/src/db/init.rs index e0ecf0e7cf9af6dbde7aabc53288cbea51464efd..cf571d25c58fc1e88de75039f53c2698ac5cf6a0 100644 --- a/rust_crud_api/src/db/init.rs +++ b/rust_crud_api/src/db/init.rs @@ -15,7 +15,8 @@ pub fn init_db(db_url: &str) -> PyResult<()> { id SERIAL PRIMARY KEY, name VARCHAR NOT NULL, email VARCHAR NOT NULL UNIQUE, - password_hash VARCHAR NOT NULL + password_hash VARCHAR NOT NULL, + username VARCHAR NOT NULL ); CREATE TABLE IF NOT EXISTS groups ( id SERIAL PRIMARY KEY, diff --git a/rust_crud_api/src/db/users.rs b/rust_crud_api/src/db/users.rs index 3549b008f102297a6cafbb4192dbbe59b2823b31..e430dfcdf68a25effd5af63bf156efba7d55c7b3 100644 --- a/rust_crud_api/src/db/users.rs +++ b/rust_crud_api/src/db/users.rs @@ -12,12 +12,12 @@ fn pg_err(e: postgres::Error) -> PyErr { /// Create a new user by inserting into the database. #[pyfunction] -pub fn create_user(db_url: &str, name: &str, email: &str, password: &str) -> PyResult<()> { +pub fn create_user(db_url: &str, name: &str, email: &str, password: &str, username: &str) -> PyResult<()> { let password_hash = hash_password(password)?; let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; client.execute( - "INSERT INTO users (name, email, password_hash) VALUES ($1, $2, $3)", - &[&name, &email, &password_hash] + "INSERT INTO users (name, email, password_hash, username) VALUES ($1, $2, $3, $4)", + &[&name, &email, &password_hash, &username] ).map_err(pg_err)?; Ok(()) } @@ -27,7 +27,7 @@ pub fn create_user(db_url: &str, name: &str, email: &str, password: &str) -> PyR pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; let row_opt = client.query_opt( - "SELECT id, name, email FROM users WHERE id = $1", + "SELECT id, name, email, username FROM users WHERE id = $1", &[&user_id] ).map_err(pg_err)?; @@ -36,6 +36,7 @@ pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { id: row.get(0), name: row.get(1), email: row.get(2), + username: row.get(3), }; Ok(Some(user)) } else { @@ -47,7 +48,7 @@ pub fn get_user(db_url: &str, user_id: i32) -> PyResult<Option<User>> { #[pyfunction] pub fn get_all_users(db_url: &str) -> PyResult<Vec<User>> { let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; - let rows = client.query("SELECT id, name, email FROM users", &[]) + let rows = client.query("SELECT id, name, email, username FROM users", &[]) .map_err(pg_err)?; let mut users = Vec::new(); @@ -56,6 +57,7 @@ pub fn get_all_users(db_url: &str) -> PyResult<Vec<User>> { id: row.get(0), name: row.get(1), email: row.get(2), + username: row.get(3), }); } Ok(users) diff --git a/rust_crud_api/src/models/user.rs b/rust_crud_api/src/models/user.rs index 042512cd2401ed57993a509ecbd3f67f3b052ae6..6145fdd02952f836f0dca5915b99bb549f05a364 100644 --- a/rust_crud_api/src/models/user.rs +++ b/rust_crud_api/src/models/user.rs @@ -10,5 +10,7 @@ pub struct User { pub name: String, #[pyo3(get, set)] pub email: String, + #[pyo3(get,set)] + pub username: String, }