Skip to content

Commit 37040b1

Browse files
authored
Revert "django_q2 no longer needs to be installed even if not used"
1 parent 0a40f93 commit 37040b1

File tree

8 files changed

+73
-137
lines changed

8 files changed

+73
-137
lines changed

README.md

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,6 @@ see their [release notes](https://github.com/adamspd/django-appointment/tree/mai
6868
```bash
6969
pip install django-appointment
7070
```
71-
Optionally installing django_q2 if you need email reminders:
72-
73-
```bash
74-
pip install django_q2
75-
```
7671

7772
2. Add "appointment" (& "django_q" if you want to enable email reminders) to your `INSTALLED_APPS` setting like so:
7873

@@ -189,13 +184,13 @@ If you're using a base.html template, you must include the following block in yo
189184
{% endblock %}
190185
```
191186

192-
At least the block for css, body and js are required; otherwise the application will not work properly.
187+
At least the block for css, body and js are required; otherwise the application will not work properly.
193188
Jquery is also required to be included in the template.
194189

195190
The title and description are optional but recommended for SEO purposes.
196191

197-
See an example of a base.html
198-
template [here](https://github.com/adamspd/django-appointment/blob/main/appointment/templates/base_templates/base.html).
192+
See an example of a base.html template [here](https://github.com/adamspd/django-appointment/blob/main/appointment/templates/base_templates/base.html).
193+
199194

200195
## Customization 🔧
201196

@@ -205,6 +200,7 @@ template [here](https://github.com/adamspd/django-appointment/blob/main/appointm
205200
2. Modify these values as needed for your application, and the app will adapt to the new settings.
206201
3. For further customization, you can extend the provided models, views, and templates or create your own.
207202

203+
208204
## Docker Support 🐳
209205

210206
Django-Appointment now supports Docker, making it easier to set up, develop, and test.
@@ -301,6 +297,7 @@ Here's how you can set it up:
301297
> **Note:** I used the default database settings for the Docker container.
302298
> If you want to use a different database, you can modify the Dockerfile and docker-compose.yml files to use your
303299
> preferred database.
300+
304301
305302
## Compatibility Matrix 📊
306303
@@ -336,12 +333,9 @@ information.
336333
337334
## Notes 📝⚠️
338335
339-
I'm working on a testing website for the application that is not fully functional yet, no hard feelings. Before using
340-
it,
341-
it's important to me that you read the terms of use, only then you can use it if you agree to them. The demo website is
342-
located
343-
at [https://django-appt.adamspierredavid.com/](https://django-appt.adamspierredavid.com/terms-and-conditions/). Ideas
344-
are welcome.
336+
I'm working on a testing website for the application that is not fully functional yet, no hard feelings. Before using it,
337+
it's important to me that you read the terms of use, only then you can use it if you agree to them. The demo website is located
338+
at [https://django-appt.adamspierredavid.com/](https://django-appt.adamspierredavid.com/terms-and-conditions/). Ideas are welcome.
345339
346340
## About the Author
347341

appointment/email_sender/email_sender.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,13 @@
33

44
from django.core.mail import mail_admins, send_mail
55
from django.template import loader
6+
from django_q.tasks import async_task
67

78
from appointment.logger_config import get_logger
89
from appointment.settings import APP_DEFAULT_FROM_EMAIL, check_q_cluster
910

1011
logger = get_logger(__name__)
1112

12-
try:
13-
from django_q.tasks import async_task
14-
15-
DJANGO_Q_AVAILABLE = True
16-
except ImportError:
17-
async_task = None
18-
DJANGO_Q_AVAILABLE = False
19-
logger.warning("django-q is not installed. Email will be send synchronously.")
20-
2113

2214
def has_required_email_settings():
2315
"""Check if all required email settings are configured and warn if any are missing."""
@@ -53,7 +45,7 @@ def send_email(recipient_list, subject: str, template_url: str = None, context:
5345
from_email = from_email or APP_DEFAULT_FROM_EMAIL
5446
html_message = render_email_template(template_url, context)
5547

56-
if get_use_django_q_for_emails() and check_q_cluster() and DJANGO_Q_AVAILABLE:
48+
if get_use_django_q_for_emails() and check_q_cluster():
5749
# Asynchronously send the email using Django-Q
5850
async_task(
5951
"appointment.tasks.send_email_task", recipient_list=recipient_list, subject=subject,
@@ -77,7 +69,7 @@ def notify_admin(subject: str, template_url: str = None, context: dict = None, m
7769

7870
html_message = render_email_template(template_url, context)
7971

80-
if get_use_django_q_for_emails() and check_q_cluster() and DJANGO_Q_AVAILABLE:
72+
if get_use_django_q_for_emails() and check_q_cluster():
8173
# Enqueue the task to send admin email asynchronously
8274
async_task('appointment.tasks.notify_admin_task', subject=subject, message=message, html_message=html_message)
8375
else:

appointment/settings.py

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,29 @@ def check_q_cluster():
3737
logger.info("Checking missing configuration for django q cluster")
3838
# Check if Django Q is installed
3939
if 'django_q' not in settings.INSTALLED_APPS:
40-
missing_conf.append("Django Q is not in settings.INSTALLED_APPS. Please add it to the list. "
41-
"See https://django-appt-doc.adamspierredavid.com/getting-started/#installation "
42-
"for more information")
40+
missing_conf.append("Django Q is not in settings.INSTALLED_APPS. Please add it to the list.\n"
41+
"Example: \n\n"
42+
"INSTALLED_APPS = [\n"
43+
" ...\n"
44+
" 'appointment',\n"
45+
" 'django_q',\n"
46+
"]\n")
4347

4448
# Check if Q_CLUSTER configuration is defined
4549
if not hasattr(settings, 'Q_CLUSTER'):
46-
missing_conf.append("Q_CLUSTER is not defined in settings. Please define it. "
47-
"See https://django-appt-doc.adamspierredavid.com/project-structure/#configuration "
48-
"for more information.")
50+
missing_conf.append("Q_CLUSTER is not defined in settings. Please define it.\n"
51+
"Example: \n\n"
52+
"Q_CLUSTER = {\n"
53+
" 'name': 'DjangORM',\n"
54+
" 'workers': 4,\n"
55+
" 'timeout': 90,\n"
56+
" 'retry': 120,\n"
57+
" 'queue_limit': 50,\n"
58+
" 'bulk': 10,\n"
59+
" 'orm': 'default',\n"
60+
"}\n"
61+
"Then run 'python manage.py qcluster' to start the worker.\n"
62+
"See https://django-q.readthedocs.io/en/latest/configure.html for more information.")
4963

5064
# Log warnings if any configurations are missing
5165
if missing_conf:

appointment/tests/test_settings.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ def test_check_q_cluster_with_django_q_missing(self, mock_logger, mock_settings)
2222
self.assertFalse(result)
2323
# Verify logger was called with the expected warning about 'django_q' not being installed
2424
mock_logger.warning.assert_called_with(
25-
"Django Q is not in settings.INSTALLED_APPS. Please add it to the list. "
26-
"See https://django-appt-doc.adamspierredavid.com/getting-started/#installation "
27-
"for more information")
25+
"Django Q is not in settings.INSTALLED_APPS. Please add it to the list.\n"
26+
"Example: \n\n"
27+
"INSTALLED_APPS = [\n"
28+
" ...\n"
29+
" 'appointment',\n"
30+
" 'django_q',\n"
31+
"]\n")
2832

2933
@patch('appointment.settings.settings')
3034
@patch('appointment.settings.logger')

appointment/tests/utils/test_db_helpers.py

Lines changed: 14 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# Path: appointment/tests/utils/test_db_helpers.py
33

44
import datetime
5-
from unittest import skip
65
from unittest.mock import MagicMock, PropertyMock, patch
76

87
from django.apps import apps
@@ -13,8 +12,8 @@
1312
from django.test.client import RequestFactory
1413
from django.urls import reverse
1514
from django.utils import timezone
15+
from django_q.models import Schedule
1616

17-
from appointment.logger_config import get_logger
1817
from appointment.models import Config, DayOff, PaymentInfo
1918
from appointment.tests.base.base_test import BaseTest
2019
from appointment.tests.mixins.base_mixin import ConfigMixin
@@ -32,25 +31,6 @@
3231
staff_change_allowed_on_reschedule, update_appointment_reminder, username_in_user_model, working_hours_exist
3332
)
3433

35-
logger = get_logger(__name__)
36-
37-
# Check if django-q is installed
38-
try:
39-
from django_q.models import Schedule
40-
from django_q.tasks import schedule
41-
42-
DJANGO_Q_AVAILABLE = True
43-
except ImportError:
44-
DJANGO_Q_AVAILABLE = False
45-
Schedule = None
46-
schedule = None
47-
48-
49-
@skip("Django-Q is not available")
50-
class DjangoQUnavailableTest(TestCase):
51-
def test_placeholder(self):
52-
self.skipTest("Django-Q is not available")
53-
5434

5535
class TestCalculateSlots(TestCase):
5636
def setUp(self):
@@ -185,12 +165,18 @@ def test_another_staff_member_no_day_off(self):
185165
self.assertFalse(check_day_off_for_staff(self.staff_member2, "2023-10-06"))
186166

187167

188-
class TestCreateAndSaveAppointment(BaseTest, TestCase):
168+
class TestCreateAndSaveAppointment(BaseTest):
169+
189170
def setUp(self):
190-
super().setUp()
171+
super().setUp() # Call the parent class setup
172+
# Specific setups for this test class
173+
self.ar = self.create_appt_request_for_sm1()
191174
self.factory = RequestFactory()
192175
self.request = self.factory.get('/')
193-
self.ar = self.create_appt_request_for_sm1()
176+
177+
def tearDown(self):
178+
Appointment.objects.all().delete()
179+
AppointmentRequest.objects.all().delete()
194180

195181
def test_create_and_save_appointment(self):
196182
client_data = {
@@ -204,8 +190,7 @@ def test_create_and_save_appointment(self):
204190
'additional_info': 'Please bring a Zat gun.'
205191
}
206192

207-
with patch('appointment.utils.db_helpers.schedule_email_reminder') as mock_schedule_reminder:
208-
appointment = create_and_save_appointment(self.ar, client_data, appointment_data, self.request)
193+
appointment = create_and_save_appointment(self.ar, client_data, appointment_data, self.request)
209194

210195
self.assertIsNotNone(appointment)
211196
self.assertEqual(appointment.client.email, client_data['email'])
@@ -214,32 +199,6 @@ def test_create_and_save_appointment(self):
214199
self.assertEqual(appointment.address, appointment_data['address'])
215200
self.assertEqual(appointment.additional_info, appointment_data['additional_info'])
216201

217-
if DJANGO_Q_AVAILABLE:
218-
mock_schedule_reminder.assert_called_once()
219-
else:
220-
mock_schedule_reminder.assert_not_called()
221-
222-
@patch('appointment.utils.db_helpers.DJANGO_Q_AVAILABLE', False)
223-
def test_create_and_save_appointment_without_django_q(self):
224-
client_data = {
225-
'email': '[email protected]',
226-
'name': 'samantha.carter',
227-
}
228-
appointment_data = {
229-
'phone': '987654321',
230-
'want_reminder': True,
231-
'address': '456, SGC, Colorado Springs, USA',
232-
'additional_info': 'Bring naquadah generator.'
233-
}
234-
235-
with patch('appointment.utils.db_helpers.logger.warning') as mock_logger_warning:
236-
appointment = create_and_save_appointment(self.ar, client_data, appointment_data, self.request)
237-
238-
self.assertIsNotNone(appointment)
239-
self.assertEqual(appointment.client.email, client_data['email'])
240-
mock_logger_warning.assert_called_with(
241-
f"Email reminder requested for appointment {appointment.id}, but django-q is not available.")
242-
243202

244203
def get_mock_reverse(url_name, **kwargs):
245204
"""A mocked version of the reverse function."""
@@ -249,13 +208,6 @@ def get_mock_reverse(url_name, **kwargs):
249208

250209

251210
class ScheduleEmailReminderTest(BaseTest):
252-
@classmethod
253-
def setUpClass(cls):
254-
if not DJANGO_Q_AVAILABLE:
255-
import unittest
256-
raise unittest.SkipTest("Django-Q is not available")
257-
super().setUpClass()
258-
259211
def setUp(self):
260212
super().setUp()
261213
self.factory = RequestFactory()
@@ -265,7 +217,6 @@ def setUp(self):
265217
def tearDown(self):
266218
Appointment.objects.all().delete()
267219
AppointmentRequest.objects.all().delete()
268-
super().tearDown()
269220

270221
def test_schedule_email_reminder_cluster_running(self):
271222
with patch('appointment.settings.check_q_cluster', return_value=True), \
@@ -282,14 +233,7 @@ def test_schedule_email_reminder_cluster_not_running(self):
282233
"Django-Q cluster is not running. Email reminder will not be scheduled.")
283234

284235

285-
class UpdateAppointmentReminderTest(BaseTest, TestCase):
286-
@classmethod
287-
def setUpClass(cls):
288-
if not DJANGO_Q_AVAILABLE:
289-
import unittest
290-
raise unittest.SkipTest("Django-Q is not available")
291-
super().setUpClass()
292-
236+
class UpdateAppointmentReminderTest(BaseTest):
293237
def setUp(self):
294238
super().setUp()
295239
self.factory = RequestFactory()
@@ -299,7 +243,6 @@ def setUp(self):
299243
def tearDown(self):
300244
Appointment.objects.all().delete()
301245
AppointmentRequest.objects.all().delete()
302-
super().tearDown()
303246

304247
def test_update_appointment_reminder_date_time_changed(self):
305248
appointment = self.create_appt_for_sm1()
@@ -324,7 +267,7 @@ def test_update_appointment_reminder_no_change(self):
324267
mock_cancel_existing_reminder.assert_not_called()
325268
mock_schedule_email_reminder.assert_not_called()
326269

327-
@patch('appointment.utils.db_helpers.logger')
270+
@patch('appointment.utils.db_helpers.logger') # Adjust the import path as necessary
328271
def test_reminder_not_scheduled_due_to_user_preference(self, mock_logger):
329272
# Scenario where user does not want a reminder
330273
want_reminder = False
@@ -338,7 +281,7 @@ def test_reminder_not_scheduled_due_to_user_preference(self, mock_logger):
338281
f"Reminder for appointment {self.appointment.id} is not scheduled per user's preference or past datetime."
339282
)
340283

341-
@patch('appointment.utils.db_helpers.logger')
284+
@patch('appointment.utils.db_helpers.logger') # Adjust the import path as necessary
342285
def test_reminder_not_scheduled_due_to_past_datetime(self, mock_logger):
343286
# Scenario where the new datetime is in the past
344287
want_reminder = True
@@ -428,8 +371,6 @@ def test_staff_change_not_allowed(self, mock_config_first):
428371

429372
class CancelExistingReminderTest(BaseTest):
430373
def test_cancel_existing_reminder(self):
431-
if not DJANGO_Q_AVAILABLE:
432-
return
433374
appointment = self.create_appt_for_sm1()
434375
Schedule.objects.create(func='appointment.tasks.send_email_reminder', name=f"reminder_{appointment.id_request}")
435376

0 commit comments

Comments
 (0)