diff --git a/Planteer/Planteer/__init__.py b/Planteer/Planteer/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/Planteer/asgi.py b/Planteer/Planteer/asgi.py
new file mode 100644
index 0000000..7693f2d
--- /dev/null
+++ b/Planteer/Planteer/asgi.py
@@ -0,0 +1,16 @@
+"""
+ASGI config for Planteer project.
+
+It exposes the ASGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/6.0/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Planteer.settings')
+
+application = get_asgi_application()
diff --git a/Planteer/Planteer/settings.py b/Planteer/Planteer/settings.py
new file mode 100644
index 0000000..3c07e1d
--- /dev/null
+++ b/Planteer/Planteer/settings.py
@@ -0,0 +1,124 @@
+"""
+Django settings for Planteer project.
+
+Generated by 'django-admin startproject' using Django 6.0.4.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/6.0/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/6.0/ref/settings/
+"""
+
+import os
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/6.0/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'django-insecure-rwq+8)*tp(5d4#=tcxp!emmgh$fe8rz7yx6dy56))%!-g(6l)x'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+ 'main',
+ 'plants',
+ 'accounts',
+]
+
+MIDDLEWARE = [
+ 'django.middleware.security.SecurityMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.common.CommonMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ROOT_URLCONF = 'Planteer.urls'
+
+TEMPLATES = [
+ {
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [BASE_DIR / 'templates'],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [
+ 'django.template.context_processors.request',
+ 'django.contrib.auth.context_processors.auth',
+ 'django.contrib.messages.context_processors.messages',
+ ],
+ },
+ },
+]
+
+WSGI_APPLICATION = 'Planteer.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/6.0/ref/settings/#databases
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3',
+ 'NAME': BASE_DIR / 'db.sqlite3',
+ }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/6.0/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+ {
+ 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+ },
+ {
+ 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+ },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/6.0/topics/i18n/
+
+LANGUAGE_CODE = 'en-us'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/6.0/howto/static-files/
+
+STATIC_URL = '/static/'
+
+MEDIA_URL = '/media/'
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
\ No newline at end of file
diff --git a/Planteer/Planteer/urls.py b/Planteer/Planteer/urls.py
new file mode 100644
index 0000000..d227b92
--- /dev/null
+++ b/Planteer/Planteer/urls.py
@@ -0,0 +1,30 @@
+"""
+URL configuration for Planteer project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+ https://docs.djangoproject.com/en/6.0/topics/http/urls/
+Examples:
+Function views
+ 1. Add an import: from my_app import views
+ 2. Add a URL to urlpatterns: path('', views.home, name='home')
+Class-based views
+ 1. Add an import: from other_app.views import Home
+ 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
+Including another URLconf
+ 1. Import the include() function: from django.urls import include, path
+ 2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path, include
+
+from django.conf import settings
+from django.conf.urls.static import static
+
+urlpatterns = [
+ path('admin/', admin.site.urls),
+ path('', include('main.urls')),
+ path('plants/', include('plants.urls')),
+ path('accounts/', include('accounts.urls'))
+]
+
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
\ No newline at end of file
diff --git a/Planteer/Planteer/wsgi.py b/Planteer/Planteer/wsgi.py
new file mode 100644
index 0000000..f14ac6f
--- /dev/null
+++ b/Planteer/Planteer/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for Planteer project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/6.0/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Planteer.settings')
+
+application = get_wsgi_application()
diff --git a/Planteer/accounts/__init__.py b/Planteer/accounts/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/accounts/admin.py b/Planteer/accounts/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/Planteer/accounts/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/Planteer/accounts/apps.py b/Planteer/accounts/apps.py
new file mode 100644
index 0000000..d440a20
--- /dev/null
+++ b/Planteer/accounts/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AccountConfig(AppConfig):
+ name = 'accounts'
diff --git a/Planteer/accounts/migrations/__init__.py b/Planteer/accounts/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/accounts/models.py b/Planteer/accounts/models.py
new file mode 100644
index 0000000..9d61c5a
--- /dev/null
+++ b/Planteer/accounts/models.py
@@ -0,0 +1,5 @@
+from django.db import models
+
+
+# Create your models here.
+
diff --git a/Planteer/accounts/templates/accounts/signin.html b/Planteer/accounts/templates/accounts/signin.html
new file mode 100644
index 0000000..e34080b
--- /dev/null
+++ b/Planteer/accounts/templates/accounts/signin.html
@@ -0,0 +1,29 @@
+{% extends 'base.html' %}
+
+{% block title %} Sign up new user {% endblock %}
+
+{% block content %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/accounts/templates/accounts/signup.html b/Planteer/accounts/templates/accounts/signup.html
new file mode 100644
index 0000000..1bec02d
--- /dev/null
+++ b/Planteer/accounts/templates/accounts/signup.html
@@ -0,0 +1,42 @@
+{% extends 'base.html' %}
+
+{% block title %} Sign up new user {% endblock %}
+
+{% block content %}
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/accounts/tests.py b/Planteer/accounts/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/Planteer/accounts/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/Planteer/accounts/urls.py b/Planteer/accounts/urls.py
new file mode 100644
index 0000000..df0cf22
--- /dev/null
+++ b/Planteer/accounts/urls.py
@@ -0,0 +1,11 @@
+from . import views
+from django.urls import path
+
+app_name = 'accounts'
+
+urlpatterns = [
+ path('signup/', views.sign_up, name='sign_up'),
+ path('signin/', views.sign_in, name='sign_in'),
+ path('logout/', views.log_out, name='log_out'),
+
+]
\ No newline at end of file
diff --git a/Planteer/accounts/views.py b/Planteer/accounts/views.py
new file mode 100644
index 0000000..0a8b62d
--- /dev/null
+++ b/Planteer/accounts/views.py
@@ -0,0 +1,44 @@
+from django.shortcuts import render, redirect
+from django.http import HttpRequest, HttpResponse
+from django.contrib.auth.models import User
+from django.contrib.auth import authenticate, login, logout
+from django.contrib import messages
+# Create your views here.
+
+def sign_up(request:HttpRequest):
+
+ if request.method == "POST":
+
+ try:
+ new_user = User.objects.create_user(username=request.POST["username"], first_name=request.POST["first_name"], last_name=request.POST["last_name"], email=request.POST["email"], password=request.POST["password"])
+ new_user.save()
+ messages.success(request, "Registered User Successfuly", "alert-success")
+ return redirect(request.GET.get("next", "/"))
+ except Exception as e:
+ print(e)
+
+
+ return render(request, 'accounts/signup.html', {})
+
+
+def sign_in(request:HttpRequest):
+
+ if request.method == "POST":
+ user = authenticate(request, username=request.POST["username"], password=request.POST["password"])
+
+ if user:
+ login(request, user)
+ messages.success(request, "Logged in successfully", "alert-success")
+ return redirect("main:home_view")
+
+ else:
+ messages.error(request, "Please try again. You credentials are wrong", "alert-danger")
+ return render(request, 'accounts/signin.html', {})
+
+
+def log_out(request:HttpRequest):
+
+ logout(request)
+ messages.success(request, "Logged out successsfully", "alert-warning")
+
+ return redirect(request.GET.get("next", "/"))
\ No newline at end of file
diff --git a/Planteer/db.sqlite3 b/Planteer/db.sqlite3
new file mode 100644
index 0000000..30ac82a
Binary files /dev/null and b/Planteer/db.sqlite3 differ
diff --git a/Planteer/main/__init__.py b/Planteer/main/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/main/admin.py b/Planteer/main/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/Planteer/main/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/Planteer/main/apps.py b/Planteer/main/apps.py
new file mode 100644
index 0000000..833bff6
--- /dev/null
+++ b/Planteer/main/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class MainConfig(AppConfig):
+ name = 'main'
diff --git a/Planteer/main/migrations/0001_initial.py b/Planteer/main/migrations/0001_initial.py
new file mode 100644
index 0000000..e999cc0
--- /dev/null
+++ b/Planteer/main/migrations/0001_initial.py
@@ -0,0 +1,25 @@
+# Generated by Django 6.0.4 on 2026-04-17 20:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Contact',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('first_name', models.CharField(max_length=50)),
+ ('last_name', models.CharField(max_length=50)),
+ ('email', models.EmailField(max_length=254)),
+ ('message', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ ]
diff --git a/Planteer/main/migrations/__init__.py b/Planteer/main/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/main/models.py b/Planteer/main/models.py
new file mode 100644
index 0000000..2275ef7
--- /dev/null
+++ b/Planteer/main/models.py
@@ -0,0 +1,10 @@
+from django.db import models
+
+# Create your models here.
+
+class Contact(models.Model):
+ first_name = models.CharField(max_length=50)
+ last_name = models.CharField(max_length=50)
+ email = models.EmailField()
+ message = models.TextField()
+ created_at = models.DateTimeField(auto_now_add=True)
\ No newline at end of file
diff --git a/Planteer/main/static/css/style.css b/Planteer/main/static/css/style.css
new file mode 100644
index 0000000..3de32e4
--- /dev/null
+++ b/Planteer/main/static/css/style.css
@@ -0,0 +1,167 @@
+*{
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+html, body {
+ height: 100%;
+ margin: 0;
+}
+
+body{
+ padding: 60px 90px;
+ display: flex;
+ flex-direction: column;
+ margin: 0;
+}
+
+main {
+ flex: 1;
+}
+
+
+header {
+ display: flex;
+ flex-direction: row;
+ position: relative;
+ align-items: center;
+ justify-content: space-between;
+}
+
+header a{
+ text-decoration: none;
+ color: black;
+}
+
+.btn-primary{
+ background-color: black;
+ border: none;
+ padding: 13px 20px;
+ font-size: 20px;
+}
+
+.nav-links{
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 2rem;
+ font-size: 20px;
+}
+
+footer{
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ gap: 30rem;
+ border-top: 0.1rem solid black;
+ padding: 20px;
+}
+
+.nav-footer{
+ display: flex;
+ flex-direction: column;
+}
+
+.logo-footer{
+ padding-bottom: 80px;
+}
+
+.fa-brands{
+ font-size: 25px;
+}
+
+a{
+ text-decoration: none;
+ color: black;
+}
+
+.hero, .img {
+ height: 600px;
+ background-image: url("../images/element5-digital-z6i_UCBuu5Q-unsplash.jpg");
+ background-size: cover;
+ background-position: center;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ color: rgb(0, 0, 0);
+ margin-top: 60px;
+ border-radius: 15px;
+}
+
+.hero h1{
+ font-size: 80px;
+}
+
+.hero h3{
+ font-size: 60px;
+}
+
+.btn-outline-success{
+ background-color: black;
+ color: white;
+ border:none;
+}
+
+.plant-section{
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ padding-top: 60px;
+}
+
+.all-plants{
+ padding-top: 60px;
+ padding-bottom: 60px;
+}
+
+
+.btn-primary:hover{
+ background-color: #198754;
+}
+
+.btn-primary a{
+ color: white;
+}
+
+.card{
+ height: auto;
+}
+
+.card-body{
+ height: 450px;
+
+
+}
+
+.card-body img{
+ height: 270px;
+
+}
+
+.plant-img{
+ display: flex;
+ flex-direction: column;
+ align-items: start;
+ justify-items: start;
+}
+
+.more-plants a{
+ display: flex;
+ flex-direction: row;
+ gap: 0.5rem;
+}
+
+a:hover{
+ color: #000000;
+}
+
+.section-flag{
+ background-color: #00000025;
+ border-radius: 50px;
+ padding: 4px;
+}
+
diff --git a/Planteer/main/static/images/element5-digital-z6i_UCBuu5Q-unsplash.jpg b/Planteer/main/static/images/element5-digital-z6i_UCBuu5Q-unsplash.jpg
new file mode 100644
index 0000000..9e25851
Binary files /dev/null and b/Planteer/main/static/images/element5-digital-z6i_UCBuu5Q-unsplash.jpg differ
diff --git a/Planteer/main/static/images/plants-hero.jpg b/Planteer/main/static/images/plants-hero.jpg
new file mode 100644
index 0000000..bf45779
Binary files /dev/null and b/Planteer/main/static/images/plants-hero.jpg differ
diff --git a/Planteer/main/templates/base.html b/Planteer/main/templates/base.html
new file mode 100644
index 0000000..a83d3e7
--- /dev/null
+++ b/Planteer/main/templates/base.html
@@ -0,0 +1,101 @@
+{% load static %}
+
+
+
+
+ {% block title %}Planteer{% endblock %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% if messages %}
+
+ {% for message in messages %}
+
+ {{ message }}
+
+
+
+ {% endfor %}
+
+ {% endif %}
+ {% block content %}
+ {% endblock %}
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Planteer/main/templates/main/contact.html b/Planteer/main/templates/main/contact.html
new file mode 100644
index 0000000..6599535
--- /dev/null
+++ b/Planteer/main/templates/main/contact.html
@@ -0,0 +1,30 @@
+{% extends 'base.html' %}
+
+{% block content %}
+Contact Us
+Subheading for description or instructions
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/main/templates/main/home.html b/Planteer/main/templates/main/home.html
new file mode 100644
index 0000000..5769448
--- /dev/null
+++ b/Planteer/main/templates/main/home.html
@@ -0,0 +1,39 @@
+{% extends 'base.html' %}
+
+{% load static %}
+
+{% block content %}
+
+
+
+
Planteer
+ Planteer Database For Plants Lovers
+
+
+
+
+
+
+
+
+
Plants
+ Learn more about plants
+
+
+
+
+
+
+
+ {% include 'plants/card_plants.html' %}
+
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/main/templates/main/messages.html b/Planteer/main/templates/main/messages.html
new file mode 100644
index 0000000..f6b57ae
--- /dev/null
+++ b/Planteer/main/templates/main/messages.html
@@ -0,0 +1,16 @@
+{% extends 'base.html' %}
+
+{% block content %}
+Messages from Users
+
+{% for msg in messages %}
+
+
+
{{ msg.first_name }} {{ msg.last_name }}
+
{{ msg.message }}
+
{{ msg.created_at }}
+
+
+{% endfor %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/main/tests.py b/Planteer/main/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/Planteer/main/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/Planteer/main/urls.py b/Planteer/main/urls.py
new file mode 100644
index 0000000..1e8e233
--- /dev/null
+++ b/Planteer/main/urls.py
@@ -0,0 +1,11 @@
+from . import views
+from django.urls import path
+
+app_name = 'main'
+
+urlpatterns = [
+ path('', views.home_view, name='home_view'),
+ path('contact/', views.contact_view, name='contact_view'),
+ path('contact/messages/', views.messages_view, name='messages_view'),
+
+]
\ No newline at end of file
diff --git a/Planteer/main/views.py b/Planteer/main/views.py
new file mode 100644
index 0000000..82b9f86
--- /dev/null
+++ b/Planteer/main/views.py
@@ -0,0 +1,27 @@
+from django.shortcuts import redirect, render
+from django.http import HttpRequest, HttpResponse
+from .models import Contact
+from plants.models import Plant
+
+# Create your views here.
+
+def home_view(request:HttpRequest):
+ plants = Plant.objects.all()[0:3]
+ return render(request, 'main/home.html', {'plants': plants})
+
+
+def contact_view(request:HttpRequest):
+ if request.method == 'POST':
+ Contact.objects.create(
+ first_name=request.POST.get('first_name'),
+ last_name=request.POST.get('last_name'),
+ email=request.POST.get('email'),
+ message=request.POST.get('message'),
+ )
+ return redirect('main:home_view')
+
+ return render(request, 'main/contact.html')
+
+def messages_view(request:HttpRequest):
+ msgs = Contact.objects.all().order_by('-created_at')
+ return render(request, 'main/messages.html', {'messages': msgs})
\ No newline at end of file
diff --git a/Planteer/manage.py b/Planteer/manage.py
new file mode 100644
index 0000000..bd0a64a
--- /dev/null
+++ b/Planteer/manage.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+ """Run administrative tasks."""
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Planteer.settings')
+ try:
+ from django.core.management import execute_from_command_line
+ except ImportError as exc:
+ raise ImportError(
+ "Couldn't import Django. Are you sure it's installed and "
+ "available on your PYTHONPATH environment variable? Did you "
+ "forget to activate a virtual environment?"
+ ) from exc
+ execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+ main()
diff --git a/Planteer/media/media/Flag_of_Indonesia.svg.png b/Planteer/media/media/Flag_of_Indonesia.svg.png
new file mode 100644
index 0000000..ce76041
Binary files /dev/null and b/Planteer/media/media/Flag_of_Indonesia.svg.png differ
diff --git a/Planteer/media/media/Flag_of_Kuwait.svg.png b/Planteer/media/media/Flag_of_Kuwait.svg.png
new file mode 100644
index 0000000..2a09678
Binary files /dev/null and b/Planteer/media/media/Flag_of_Kuwait.svg.png differ
diff --git a/Planteer/media/media/Flag_of_Saudi_Arabia.svg.webp b/Planteer/media/media/Flag_of_Saudi_Arabia.svg.webp
new file mode 100644
index 0000000..11983d2
Binary files /dev/null and b/Planteer/media/media/Flag_of_Saudi_Arabia.svg.webp differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living.jpg b/Planteer/media/media/Lemon_-_Sprout_Living.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_0Uhe75U.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_0Uhe75U.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_0Uhe75U.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_1ev5qbW.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_1ev5qbW.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_1ev5qbW.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_KW8aRHs.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_KW8aRHs.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_KW8aRHs.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_Scg2bEG.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_Scg2bEG.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_Scg2bEG.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_eCNe13O.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_eCNe13O.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_eCNe13O.jpg differ
diff --git a/Planteer/media/media/Lemon_-_Sprout_Living_vPkhCOg.jpg b/Planteer/media/media/Lemon_-_Sprout_Living_vPkhCOg.jpg
new file mode 100644
index 0000000..0228e56
Binary files /dev/null and b/Planteer/media/media/Lemon_-_Sprout_Living_vPkhCOg.jpg differ
diff --git a/Planteer/media/media/Morangos.jpg b/Planteer/media/media/Morangos.jpg
new file mode 100644
index 0000000..d67170a
Binary files /dev/null and b/Planteer/media/media/Morangos.jpg differ
diff --git a/Planteer/media/media/Morangos_fiNDA2u.jpg b/Planteer/media/media/Morangos_fiNDA2u.jpg
new file mode 100644
index 0000000..d67170a
Binary files /dev/null and b/Planteer/media/media/Morangos_fiNDA2u.jpg differ
diff --git a/Planteer/media/media/Morangos_gwAo5KI.jpg b/Planteer/media/media/Morangos_gwAo5KI.jpg
new file mode 100644
index 0000000..d67170a
Binary files /dev/null and b/Planteer/media/media/Morangos_gwAo5KI.jpg differ
diff --git a/Planteer/media/media/Morangos_p4ox3ow.jpg b/Planteer/media/media/Morangos_p4ox3ow.jpg
new file mode 100644
index 0000000..d67170a
Binary files /dev/null and b/Planteer/media/media/Morangos_p4ox3ow.jpg differ
diff --git a/Planteer/media/media/download.jpg b/Planteer/media/media/download.jpg
new file mode 100644
index 0000000..b5b66fd
Binary files /dev/null and b/Planteer/media/media/download.jpg differ
diff --git a/Planteer/media/media/download_LTN85y3.jpg b/Planteer/media/media/download_LTN85y3.jpg
new file mode 100644
index 0000000..b5b66fd
Binary files /dev/null and b/Planteer/media/media/download_LTN85y3.jpg differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_9DmmWYX.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_9DmmWYX.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_9DmmWYX.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_ByJzIKj.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_ByJzIKj.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_ByJzIKj.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_HemZA7V.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_HemZA7V.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_HemZA7V.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_Ve3329r.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_Ve3329r.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_Ve3329r.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_XF8Rnoc.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_XF8Rnoc.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_XF8Rnoc.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_YyQuwKL.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_YyQuwKL.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_YyQuwKL.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_dMTm2wO.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_dMTm2wO.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_dMTm2wO.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_fBW4rjc.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_fBW4rjc.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_fBW4rjc.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_k9y4HyO.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_k9y4HyO.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_k9y4HyO.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_mh9LeJT.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_mh9LeJT.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_mh9LeJT.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_nBuu8bQ.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_nBuu8bQ.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_nBuu8bQ.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_srRQD2v.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_srRQD2v.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_srRQD2v.jpg" differ
diff --git "a/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_vxf8yqM.jpg" "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_vxf8yqM.jpg"
new file mode 100644
index 0000000..35a0223
Binary files /dev/null and "b/Planteer/media/media/\330\250\331\206\330\257\331\210\330\261\330\251_vxf8yqM.jpg" differ
diff --git a/Planteer/plants/__init__.py b/Planteer/plants/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/plants/admin.py b/Planteer/plants/admin.py
new file mode 100644
index 0000000..d6035e8
--- /dev/null
+++ b/Planteer/plants/admin.py
@@ -0,0 +1,7 @@
+from django.contrib import admin
+from .models import Plant, Review, Country
+# Register your models here.
+
+admin.site.register(Plant)
+admin.site.register(Review)
+admin.site.register(Country)
\ No newline at end of file
diff --git a/Planteer/plants/apps.py b/Planteer/plants/apps.py
new file mode 100644
index 0000000..478c3ce
--- /dev/null
+++ b/Planteer/plants/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class PlantsConfig(AppConfig):
+ name = 'plants'
diff --git a/Planteer/plants/migrations/0001_initial.py b/Planteer/plants/migrations/0001_initial.py
new file mode 100644
index 0000000..be2f3a9
--- /dev/null
+++ b/Planteer/plants/migrations/0001_initial.py
@@ -0,0 +1,27 @@
+# Generated by Django 6.0.4 on 2026-04-17 20:53
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Plant',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=100)),
+ ('about', models.TextField()),
+ ('used_for', models.TextField()),
+ ('image', models.ImageField(upload_to='media/')),
+ ('category', models.CharField(choices=[('Indoor', 'indoor'), ('Outdoor', 'outdoor'), ('Succulent', 'succulent'), ('Flowering', 'flowering'), ('Herb', 'herb'), ('Tree', 'tree'), ('Shrub', 'shrub'), ('Cactus', 'cactus'), ('Fern', 'fern'), ('Grass', 'grass')], max_length=20)),
+ ('is_edible', models.BooleanField(default=False)),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ],
+ ),
+ ]
diff --git a/Planteer/plants/migrations/0002_review.py b/Planteer/plants/migrations/0002_review.py
new file mode 100644
index 0000000..8af0743
--- /dev/null
+++ b/Planteer/plants/migrations/0002_review.py
@@ -0,0 +1,24 @@
+# Generated by Django 6.0.4 on 2026-04-20 19:35
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('plants', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Review',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=1024)),
+ ('comment', models.TextField()),
+ ('created_at', models.DateTimeField(auto_now_add=True)),
+ ('plant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='plants.plant')),
+ ],
+ ),
+ ]
diff --git a/Planteer/plants/migrations/0003_country_plant_countries.py b/Planteer/plants/migrations/0003_country_plant_countries.py
new file mode 100644
index 0000000..94fc8cf
--- /dev/null
+++ b/Planteer/plants/migrations/0003_country_plant_countries.py
@@ -0,0 +1,26 @@
+# Generated by Django 6.0.4 on 2026-04-21 08:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('plants', '0002_review'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Country',
+ fields=[
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=32)),
+ ('flag', models.ImageField(upload_to='media/')),
+ ],
+ ),
+ migrations.AddField(
+ model_name='plant',
+ name='countries',
+ field=models.ManyToManyField(related_name='plants', to='plants.country'),
+ ),
+ ]
diff --git a/Planteer/plants/migrations/0004_remove_review_name_review_user.py b/Planteer/plants/migrations/0004_remove_review_name_review_user.py
new file mode 100644
index 0000000..dd7b2fc
--- /dev/null
+++ b/Planteer/plants/migrations/0004_remove_review_name_review_user.py
@@ -0,0 +1,26 @@
+# Generated by Django 6.0.4 on 2026-04-27 06:32
+
+import django.db.models.deletion
+from django.conf import settings
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('plants', '0003_country_plant_countries'),
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='review',
+ name='name',
+ ),
+ migrations.AddField(
+ model_name='review',
+ name='user',
+ field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
+ preserve_default=False,
+ ),
+ ]
diff --git a/Planteer/plants/migrations/__init__.py b/Planteer/plants/migrations/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/Planteer/plants/models.py b/Planteer/plants/models.py
new file mode 100644
index 0000000..b33089a
--- /dev/null
+++ b/Planteer/plants/models.py
@@ -0,0 +1,48 @@
+from django.db import models
+from django.contrib.auth.models import User
+
+# Create your models here.
+
+class Plant(models.Model):
+
+ class TextChoices(models.TextChoices):
+ INDOOR = 'Indoor', 'indoor'
+ OUTDOOR = 'Outdoor', 'outdoor'
+ SUCCULENT = 'Succulent', 'succulent'
+ FLOWERING = 'Flowering', 'flowering'
+ HERB = 'Herb', 'herb'
+ TREE = 'Tree', 'tree'
+ SHRUB = 'Shrub', 'shrub'
+ CACTUS = 'Cactus', 'cactus'
+ FERN = 'Fern', 'fern'
+ GRASS = 'Grass', 'grass'
+
+ name = models.CharField(max_length=100)
+ about = models.TextField()
+ used_for = models.TextField()
+ image = models.ImageField(upload_to='media/')
+ category = models.CharField(max_length=20, choices=TextChoices.choices)
+ is_edible = models.BooleanField(default=False)
+ created_at = models.DateTimeField(auto_now_add=True)
+ countries = models.ManyToManyField('Country', related_name='plants')
+
+ def __str__(self):
+ return self.name
+
+
+class Review(models.Model):
+ plant = models.ForeignKey(Plant, on_delete=models.CASCADE)
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+ comment = models.TextField()
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ def __str__(self):
+ return self.user.username
+
+
+class Country(models.Model):
+ name = models.CharField(max_length=32)
+ flag = models.ImageField(upload_to='media/')
+
+ def __str__(self):
+ return self.name
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/all.html b/Planteer/plants/templates/plants/all.html
new file mode 100644
index 0000000..5421deb
--- /dev/null
+++ b/Planteer/plants/templates/plants/all.html
@@ -0,0 +1,27 @@
+{% extends 'base.html' %}
+
+{% block content %}
+All Plants
+
+
+
+ {% include 'plants/card_plants.html' %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/card_plants.html b/Planteer/plants/templates/plants/card_plants.html
new file mode 100644
index 0000000..63331c4
--- /dev/null
+++ b/Planteer/plants/templates/plants/card_plants.html
@@ -0,0 +1,29 @@
+
+ {% for plant in plants %}
+
+ {% endfor %}
+
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/country_plants.html b/Planteer/plants/templates/plants/country_plants.html
new file mode 100644
index 0000000..c9f7c25
--- /dev/null
+++ b/Planteer/plants/templates/plants/country_plants.html
@@ -0,0 +1,10 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+Plants Native to {{ country.name }}
+
+ {% include 'plants/card_plants.html' %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/delete.html b/Planteer/plants/templates/plants/delete.html
new file mode 100644
index 0000000..d0bc876
--- /dev/null
+++ b/Planteer/plants/templates/plants/delete.html
@@ -0,0 +1,12 @@
+{% extends 'base.html' %}
+
+{% block content %}
+Are you sure you want to delete {{ plant.name }}?
+
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/detail.html b/Planteer/plants/templates/plants/detail.html
new file mode 100644
index 0000000..2ac991b
--- /dev/null
+++ b/Planteer/plants/templates/plants/detail.html
@@ -0,0 +1,84 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+
+

+
+
+
+
{{ plant.name }}
+
{{ plant.category }}
+
{{ plant.about }}
+
Native to:
+
+
+ {% for c in plant.countries.all %}
+
+ {% endfor %}
+
+
+
Is Edible:
+ {% if plant.is_edible %}
+ Yes
+ {% else %}
+ No
+ {% endif %}
+
+
Used For:
{{ plant.used_for }}
+ {% if request.user.is_staff %}
+
+
+ {% endif %}
+
+
+
+
+
+
+
+
+Comments
+
+ {% for review in reviews %}
+
+
{{review.user.first_name}} {{review.user.last_name}}
+
{{review.comment}}
+
{{review.created_at}}
+
+ {% endfor %}
+
+
+
+{% if request.user.is_authenticated %}
+Add Comment
+
+
+{% endif %}
+
+
+
+
+
+
+Related Plants
+ {% include 'plants/card_plants.html' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/form.html b/Planteer/plants/templates/plants/form.html
new file mode 100644
index 0000000..d47275b
--- /dev/null
+++ b/Planteer/plants/templates/plants/form.html
@@ -0,0 +1,55 @@
+{% extends 'base.html' %}
+
+{% block content %}
+{% if plant %}Update{% else %}Add{% endif %} Plant
+
+
+
+{% if error %}
+{{ error }}
+{% endif %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/templates/plants/search.html b/Planteer/plants/templates/plants/search.html
new file mode 100644
index 0000000..6fcac71
--- /dev/null
+++ b/Planteer/plants/templates/plants/search.html
@@ -0,0 +1,60 @@
+{% extends 'base.html' %}
+
+{% block content %}
+
+
+
+
+ {% for plant in results %}
+
+ {% endfor %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/Planteer/plants/tests.py b/Planteer/plants/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/Planteer/plants/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/Planteer/plants/urls.py b/Planteer/plants/urls.py
new file mode 100644
index 0000000..3329516
--- /dev/null
+++ b/Planteer/plants/urls.py
@@ -0,0 +1,15 @@
+from . import views
+from django.urls import path
+
+app_name = 'plants'
+
+urlpatterns = [
+ path('all/', views.all_plants_view, name='all_plants_view'),
+ path('/detail/', views.plant_detail_view, name='plant_detail_view'),
+ path('new/', views.add_plant_view, name='add_plant_view'),
+ path('/update/', views.update_plant_view, name='update_plant_view'),
+ path('/delete/', views.delete_plant_view, name='delete_plant_view'),
+ path('search/', views.search_plant_view, name='search_plant_view'),
+ path('reviews/add//', views.add_review_view, name='add_review_view'),
+ path('country/', views.country_plants_view, name='country_plants_view')
+]
\ No newline at end of file
diff --git a/Planteer/plants/views.py b/Planteer/plants/views.py
new file mode 100644
index 0000000..0dcc801
--- /dev/null
+++ b/Planteer/plants/views.py
@@ -0,0 +1,151 @@
+from django.shortcuts import get_object_or_404, redirect, render
+from django.http import HttpRequest, HttpResponse
+from .models import Plant, Review, Country, User
+from django.contrib import messages
+
+# Create your views here.
+
+def all_plants_view(request:HttpRequest):
+ plants = Plant.objects.all()
+ country_id = request.GET.get('country')
+
+ category = request.GET.get('category')
+ edible = request.GET.get('is_edible')
+
+ if category:
+ plants = plants.filter(category = category)
+
+ if edible == 'true':
+ plants = plants.filter(is_edible = True)
+
+ if country_id:
+ plants = Plant.objects.filter(countries__id=country_id)
+ else:
+ plants = Plant.objects.all()
+
+ countries = Country.objects.all()
+
+
+ return render(request, 'plants/all.html', {'plants': plants, 'countries': countries})
+
+def plant_detail_view(request: HttpRequest, plant_id):
+ plant = get_object_or_404(Plant, id=plant_id)
+
+ related = Plant.objects.filter(
+ category=plant.category
+ ).exclude(id=plant_id)[0:3]
+
+ reviews = Review.objects.filter(plant=plant)
+
+ return render(request, 'plants/detail.html', {
+ 'plant': plant,
+ 'related': related,
+ 'reviews': reviews
+ })
+
+
+def add_plant_view(request):
+
+ if not request.user.is_staff:
+ messages.warning(request, "only staff can add plants", "alert-warning")
+ return redirect("main:home_view")
+
+ if request.method == "POST":
+ name = request.POST.get('name')
+ about = request.POST.get('about')
+ used_for = request.POST.get('used_for')
+ category = request.POST.get('category')
+ is_edible = request.POST.get('is_edible') == 'on'
+ image = request.FILES.get('image')
+
+ # 🔥 إنشاء النبات أولاً
+ plant = Plant.objects.create(
+ name=name,
+ about=about,
+ used_for=used_for,
+ category=category,
+ is_edible=is_edible,
+ image=image
+ )
+
+ # 🔥 بعدها تربط الدول
+ countries_ids = request.POST.getlist('countries')
+ plant.countries.set(countries_ids)
+
+ return redirect('plants:all_plants_view')
+
+ countries = Country.objects.all()
+ return render(request, 'plants/form.html', {
+ 'countries': countries
+ })
+
+def update_plant_view(request:HttpRequest, plant_id):
+
+ if not request.user.is_staff:
+ messages.warning(request, "only staff can add plants", "alert-warning")
+ return redirect("main:home_view")
+
+ plant = get_object_or_404(Plant, id=plant_id)
+
+ if request.method == 'POST':
+ plant.name = request.POST.get('name')
+ plant.about = request.POST.get('about')
+ plant.used_for = request.POST.get('used_for')
+ plant.category = request.POST.get('category')
+ plant.is_edible = request.POST.get('is_edible') == 'on'
+
+ if request.FILES.get('image'):
+ plant.image = request.FILES.get('image')
+
+ plant.save()
+ return redirect('plant_detail', id=plant_id)
+
+ return render(request, 'plants/form.html', {'plant': plant})
+
+def delete_plant_view(request:HttpRequest, plant_id):
+
+ if not request.user.is_staff:
+ messages.warning(request, "only staff can add plants", "alert-warning")
+ return redirect("main:home_view")
+
+ plant = get_object_or_404(Plant, id=plant_id)
+
+ if request.method == 'POST':
+ plant.delete()
+ return redirect('plants:all_plants_view')
+
+ return render(request, 'plants/delete.html', {'plant': plant})
+
+def search_plant_view(request:HttpRequest):
+ query = request.GET.get('q')
+ results = []
+
+ if query:
+ results = Plant.objects.filter(name__icontains=query)
+
+ return render(request, 'plants/search.html', {
+ 'results': results,
+ 'query': query
+ })
+
+def add_review_view(request:HttpRequest, plant_id):
+
+ if not request.user.is_authenticated:
+ messages.error(request, "Only registered user can add review", "alert-danger")
+ return redirect("accounts:sign_in")
+
+ if request.method == "POST":
+ plant_object = Plant.objects.get(id=plant_id)
+ new_review = Review(plant=plant_object,user=request.user, comment=request.POST["comment"])
+ new_review.save()
+
+ messages.success(request, "Added Review successfully", "alert-success")
+
+ return redirect("plant:plant_detail_view", id=plant_id)
+
+def country_plants_view(request, country_id):
+ country = get_object_or_404(Country, id=country_id)
+
+ plants = Plant.objects.filter(countries=country)
+
+ return render(request, 'plants/country_plants.html', {'country': country, 'plants': plants})
\ No newline at end of file