diff --git a/django_project/django_project/settings.py b/django_project/django_project/settings.py index 6260cbced2f92b344065d49fb2a6d41dd22a8abe..b8db6642a7907e9256490f9a282e6cb9af22b896 100644 --- a/django_project/django_project/settings.py +++ b/django_project/django_project/settings.py @@ -71,7 +71,10 @@ ROOT_URLCONF = 'django_project.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [BASE_DIR / "templates"], + 'DIRS': [ + BASE_DIR / "myapp" / "templates" / "myapp", + BASE_DIR / "myapp" / "templates", + ], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ @@ -79,6 +82,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'myapp.context_processors.global_search', ], }, }, @@ -86,7 +90,6 @@ TEMPLATES = [ WSGI_APPLICATION = 'django_project.wsgi.application' - # Database # https://docs.djangoproject.com/en/5.1/ref/settings/#databases diff --git a/django_project/django_project/urls.py b/django_project/django_project/urls.py index 0e0131b7b98113ac7e6c3714fdf502c56c13e4a7..5a365f397788d1b18cccfe501ae9ae2abd3f1b34 100644 --- a/django_project/django_project/urls.py +++ b/django_project/django_project/urls.py @@ -21,7 +21,7 @@ from django.conf.urls.static import static from myapp.views.authviews import login_view, logout_view from myapp.views.userviews import register_view, account_view, delete_account_view, welcome_view, edit_account_view -from myapp.views.groupviews import group_list_view, group_create_view, group_update_view, group_delete_view, group_detail_view +from myapp.views.groupviews import group_list_view, group_create_view, group_update_view, group_delete_view, group_detail_view, group_search_view from myapp.views.postviews import create_post_view, feed_view from myapp.views.initview import init_db_view @@ -41,7 +41,8 @@ urlpatterns = [ path('post/create/', create_post_view, name='create_post'), path('feed/', feed_view, name='feed'), path('welcome/', welcome_view, name='welcome'), - path('edit_account/', edit_account_view, name='edit_account') + path('edit_account/', edit_account_view, name='edit_account'), + path('group_search', group_search_view, name='group_search') ] if settings.DEBUG: diff --git a/django_project/myapp/context_processors.py b/django_project/myapp/context_processors.py new file mode 100644 index 0000000000000000000000000000000000000000..e49d6ecfa19d5cfb98137a0ebd4eda1a40938bca --- /dev/null +++ b/django_project/myapp/context_processors.py @@ -0,0 +1,5 @@ +def global_search(request): + """ + Makes the search query globally available in all templates. + """ + return {"search_query": request.GET.get("q", "")} diff --git a/django_project/myapp/templates/myapp/base.html b/django_project/myapp/templates/myapp/base.html index 13acf3d718fbd5534050952c66bd78dfe2f73eac..e1e4c4ee583317f2196a9018da3028102fd3902f 100644 --- a/django_project/myapp/templates/myapp/base.html +++ b/django_project/myapp/templates/myapp/base.html @@ -40,7 +40,13 @@ <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> + + <form method="GET" action="{% url 'group_search' %}"> + <input type="text" name="q" placeholder="Search for groups..." value="{{ search_query }}"> + <button type="submit">Search</button> + </form> </nav> <!-- Page Content --> diff --git a/django_project/myapp/templates/myapp/group_search.html b/django_project/myapp/templates/myapp/group_search.html new file mode 100644 index 0000000000000000000000000000000000000000..aebe2a294cdbf82608e6406b51ceed8a6ff2c3fb --- /dev/null +++ b/django_project/myapp/templates/myapp/group_search.html @@ -0,0 +1,29 @@ +{% extends "base.html" %} + +{% block content %} + <h2>Search for Groups</h2> + + <!-- Search Form --> + <form method="GET" action="{% url 'group_search' %}"> + <input type="text" name="q" placeholder="Search for groups..." value="{{ query }}"> + <button type="submit">Search</button> + </form> + + <!-- Error Message --> + {% if error %} + <p style="color: red;">{{ error }}</p> + {% endif %} + + <!-- Search Results --> + {% if groups %} + <h3>Results:</h3> + <ul> + {% for group in groups %} + <li>{{ group.name }}</li> + {% endfor %} + </ul> + {% else %} + <p>No groups found.</p> + {% endif %} +{% endblock %} + diff --git a/django_project/myapp/views/groupviews.py b/django_project/myapp/views/groupviews.py index e5e6b58985beee2b17a95fa524ff84c8f6b5eb22..4617d49d9c4671464b61f707f40cd88a7acba706 100644 --- a/django_project/myapp/views/groupviews.py +++ b/django_project/myapp/views/groupviews.py @@ -61,7 +61,6 @@ def group_update_view(request, group_id): context['group'] = group return render(request, 'myapp/group_update.html', context) try: - # This assumes you've implemented an `update_group` function in your Rust library. rust_crud_api.update_group(db_url, int(group_id), new_name) return redirect('group_list') except Exception as e: @@ -80,7 +79,6 @@ def group_delete_view(request, group_id): context = {} if request.method == 'POST': try: - # This assumes you have a `delete_group` function in your Rust library. success = rust_crud_api.delete_group(db_url, int(group_id)) if success: return redirect('group_list') @@ -111,3 +109,18 @@ def group_detail_view(request, group_id): context['error'] = f"An error occurred: {e}" return render(request, 'myapp/group_detail.html', context) +def group_search_view(request): + """ + Handles searching for groups using Rust. + """ + db_url = settings.DATABASE_URL + query = request.GET.get("q", "").strip() + groups = [] + if query: + try: + groups = rust_crud_api.search_groups(db_url, query) + except Exception as e: + return render(request, "group_search.html", {"error": str(e), "query": query}) + + return render(request, "group_search.html", {"groups": groups, "query": query}) + diff --git a/rust_crud_api/src/db/groups.rs b/rust_crud_api/src/db/groups.rs index 5ef592d76cbd7430e263a5aff52747a86f62f114..d98d1f78bc5f057c24822b870a9963e035d6cd8f 100644 --- a/rust_crud_api/src/db/groups.rs +++ b/rust_crud_api/src/db/groups.rs @@ -102,3 +102,21 @@ pub fn delete_group(db_url: &str, group_id: i32) -> PyResult<bool> { ).map_err(pg_err)?; Ok(deleted > 0) } + +#[pyfunction] +pub fn search_groups(db_url: &str, query: &str) -> PyResult<Vec<Group>> { + let mut client = Client::connect(db_url, NoTls).map_err(pg_err)?; + let rows = client.query( + "SELECT id, name FROM groups WHERE name ILIKE $1", + &[&format!("%{}%", query)] + ).map_err(pg_err)?; + + let groups: Vec<Group> = rows.iter() + .map(|row| Group { + id: Some(row.get(0)), + name: row.get(1), + }) + .collect(); + + Ok(groups) +} diff --git a/rust_crud_api/src/db/mod.rs b/rust_crud_api/src/db/mod.rs index b59c637b26f04e6b51a4fba9faf5c5f4eda236ab..5d9ae31adeeb81a290ef7f34d2a49b695f0fedb2 100644 --- a/rust_crud_api/src/db/mod.rs +++ b/rust_crud_api/src/db/mod.rs @@ -5,5 +5,5 @@ pub mod posts; pub use init::init_db; pub use users::{create_user, get_user, get_all_users, update_user, delete_user, update_first_login}; -pub use groups::{create_group, get_group, get_all_groups, add_user_to_group, get_group_members, delete_group}; +pub use groups::{create_group, get_group, get_all_groups, add_user_to_group, get_group_members, delete_group, search_groups}; pub use posts::{create_post, get_user_posts, get_group_posts, get_feed}; diff --git a/rust_crud_api/src/lib.rs b/rust_crud_api/src/lib.rs index 6daa866acc7cb88bbd9eb89c270a01da6c62d320..05e21a9104ffb375f94f24b6166ed266b08cf65f 100644 --- a/rust_crud_api/src/lib.rs +++ b/rust_crud_api/src/lib.rs @@ -36,6 +36,7 @@ fn rust_crud_api(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(db::groups::add_user_to_group, m)?)?; m.add_function(wrap_pyfunction!(db::groups::get_group_members, m)?)?; m.add_function(wrap_pyfunction!(db::groups::delete_group, m)?)?; + m.add_function(wrap_pyfunction!(db::groups::search_groups, m)?)?; // Posts m.add_function(wrap_pyfunction!(db::posts::create_post, m)?)?; m.add_function(wrap_pyfunction!(db::posts::get_user_posts, m)?)?;