Skip to content

Commit cfd5076

Browse files
committed
djangox demo with things app
1 parent b400d5d commit cfd5076

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1066
-0
lines changed
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# OSX #
2+
.DS_Store
3+
4+
# Byte-compiled / optimized / DLL files #
5+
__pycache__/
6+
*.py[cod]
7+
*$py.class
8+
9+
# Django #
10+
*.log
11+
db.sqlite3
12+
media
13+
14+
.venv
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Contributing
2+
3+
Thank you for help improving DjangoX. All kinds of contributions are welcome. Please note that this starter project is *intentionally* basic: I don't plan to add environment variables, Docker, or other production-appropriate features as I feel they will overwhelm beginners. But I'm open to suggestions!
4+
5+
Please submit an Issue or even better a PR and I'll review :)
+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
djangox: Copyright (c) 2020 William Vincent
2+
django-allauth: Copyright (c) 2010 Raymond Penners and contributors
3+
cookie-cutter-django: Copyright (c) 2013-2020 Daniel Greenfeld
4+
5+
Permission is hereby granted, free of charge, to any person
6+
obtaining a copy of this software and associated documentation
7+
files (the "Software"), to deal in the Software without
8+
restriction, including without limitation the rights to use,
9+
copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the
11+
Software is furnished to do so, subject to the following
12+
conditions:
13+
14+
The above copyright notice and this permission notice shall be
15+
included in all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24+
OTHER DEALINGS IN THE SOFTWARE.
+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
> A batteries-included Django starter project. To learn more try the books [Django for Beginners](https://djangoforbeginners.com), [Django for APIs](https://djangoforapis.com), and [Django for Professionals](https://djangoforprofessionals.com).
2+
3+
## 🚀 Features
4+
5+
- Django 4.1 & Python 3.10
6+
- Install via [Pip](https://pypi.org/project/pip/), [Pipenv](https://pypi.org/project/pipenv/), or [Docker](https://www.docker.com/)
7+
- User log in/out, sign up, password reset via [django-allauth](https://github.com/pennersr/django-allauth)
8+
- Static files configured with [Whitenoise](http://whitenoise.evans.io/en/stable/index.html)
9+
- Styling with [Bootstrap v5](https://getbootstrap.com/)
10+
- Debugging with [django-debug-toolbar](https://github.com/jazzband/django-debug-toolbar)
11+
- DRY forms with [django-crispy-forms](https://github.com/django-crispy-forms/django-crispy-forms)
12+
13+
![Homepage](homepage_41.png)
14+
----
15+
16+
## Table of Contents
17+
* **[Installation](#installation)**
18+
* [Pip](#pip)
19+
* [Pipenv](#pipenv)
20+
* [Docker](#docker)
21+
* [Next Steps](#next-steps)
22+
* [Contributing](#contributing)
23+
* [Support](#support)
24+
* [License](#license)
25+
26+
----
27+
28+
## 📖 Installation
29+
DjangoX can be installed via Pip, Pipenv, or Docker. To start, clone the repo to your local computer and change into the proper directory.
30+
31+
```
32+
$ git clone https://github.com/wsvincent/djangox.git
33+
$ cd djangox
34+
```
35+
36+
### Pip
37+
38+
```
39+
$ python -m venv .venv
40+
41+
# Windows
42+
$ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
43+
$ .venv\Scripts\Activate.ps1
44+
45+
# macOS
46+
$ source .venv/bin/activate
47+
48+
(.venv) $ pip install -r requirements.txt
49+
(.venv) $ python manage.py migrate
50+
(.venv) $ python manage.py createsuperuser
51+
(.venv) $ python manage.py runserver
52+
# Load the site at http://127.0.0.1:8000
53+
```
54+
55+
### Pipenv
56+
57+
```
58+
$ pipenv install
59+
$ pipenv shell
60+
(.venv) $ python manage.py migrate
61+
(.venv) $ python manage.py createsuperuser
62+
(.venv) $ python manage.py runserver
63+
# Load the site at http://127.0.0.1:8000
64+
```
65+
66+
### Docker
67+
68+
To use Docker with PostgreSQL as the database update the `DATABASES` section of `django_project/settings.py` to reflect the following:
69+
70+
```python
71+
# django_project/settings.py
72+
DATABASES = {
73+
"default": {
74+
"ENGINE": "django.db.backends.postgresql",
75+
"NAME": "postgres",
76+
"USER": "postgres",
77+
"PASSWORD": "postgres",
78+
"HOST": "db", # set in docker-compose.yml
79+
"PORT": 5432, # default postgres port
80+
}
81+
}
82+
```
83+
84+
The `INTERNAL_IPS` configuration in `django_project/settings.py` must be also be updated:
85+
86+
```python
87+
# config/settings.py
88+
# django-debug-toolbar
89+
import socket
90+
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
91+
INTERNAL_IPS = [ip[:-1] + "1" for ip in ips]
92+
```
93+
94+
And then proceed to build the Docker image, run the container, and execute the standard commands within Docker.
95+
96+
```
97+
$ docker-compose up -d --build
98+
$ docker-compose exec web python manage.py migrate
99+
$ docker-compose exec web python manage.py createsuperuser
100+
# Load the site at http://127.0.0.1:8000
101+
```
102+
103+
## Next Steps
104+
105+
- Add environment variables. There are multiple packages but I personally prefer [environs](https://pypi.org/project/environs/).
106+
- Add [gunicorn](https://pypi.org/project/gunicorn/) as the production web server.
107+
- Update the [EMAIL_BACKEND](https://docs.djangoproject.com/en/4.0/topics/email/#module-django.core.mail) and connect with a mail provider.
108+
- Make the [admin more secure](https://opensource.com/article/18/1/10-tips-making-django-admin-more-secure).
109+
- `django-allauth` supports [social authentication](https://django-allauth.readthedocs.io/en/latest/providers.html) if you need that.
110+
111+
I cover all of these steps in my three books: [Django for Beginners](https://djangoforbeginners.com), [Django for APIs](https://djangoforapis.com), and [Django for Professionals](https://djangoforprofessionals.com).
112+
113+
----
114+
115+
## 🤝 Contributing
116+
117+
Contributions, issues and feature requests are welcome! See [CONTRIBUTING.md](https://github.com/wsvincent/djangox/blob/master/CONTRIBUTING.md).
118+
119+
## ⭐️ Support
120+
121+
Give a ⭐️ if this project helped you!
122+
123+
## License
124+
125+
[The MIT License](LICENSE)

class-29/in-class-demo-djangox/accounts/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from django.contrib import admin
2+
from django.contrib.auth import get_user_model
3+
from django.contrib.auth.admin import UserAdmin
4+
5+
from .forms import CustomUserCreationForm, CustomUserChangeForm
6+
from .models import CustomUser
7+
8+
class CustomUserAdmin(UserAdmin):
9+
add_form = CustomUserCreationForm
10+
form = CustomUserChangeForm
11+
model = CustomUser
12+
list_display = ['email', 'username',]
13+
14+
admin.site.register(CustomUser, CustomUserAdmin)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from django.apps import AppConfig
2+
3+
4+
class AccountsConfig(AppConfig):
5+
default_auto_field = 'django.db.models.AutoField'
6+
name = 'accounts'
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from django import forms
2+
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
3+
from .models import CustomUser
4+
5+
class CustomUserCreationForm(UserCreationForm):
6+
7+
class Meta(UserCreationForm.Meta):
8+
model = CustomUser
9+
fields = ('email', 'username',)
10+
11+
class CustomUserChangeForm(UserChangeForm):
12+
13+
class Meta:
14+
model = CustomUser
15+
fields = ('email', 'username',)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Generated by Django 3.1.2 on 2020-10-01 13:52
2+
3+
import django.contrib.auth.models
4+
import django.contrib.auth.validators
5+
from django.db import migrations, models
6+
import django.utils.timezone
7+
8+
9+
class Migration(migrations.Migration):
10+
11+
initial = True
12+
13+
dependencies = [
14+
('auth', '0012_alter_user_first_name_max_length'),
15+
]
16+
17+
operations = [
18+
migrations.CreateModel(
19+
name='CustomUser',
20+
fields=[
21+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22+
('password', models.CharField(max_length=128, verbose_name='password')),
23+
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
24+
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
25+
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
26+
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
27+
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
28+
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
29+
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
30+
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
31+
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
32+
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
33+
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),
34+
],
35+
options={
36+
'verbose_name': 'user',
37+
'verbose_name_plural': 'users',
38+
'abstract': False,
39+
},
40+
managers=[
41+
('objects', django.contrib.auth.models.UserManager()),
42+
],
43+
),
44+
]

class-29/in-class-demo-djangox/accounts/migrations/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.contrib.auth.models import AbstractUser
2+
from django.db import models
3+
4+
class CustomUser(AbstractUser):
5+
pass
6+
7+
def __str__(self):
8+
return self.email
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.shortcuts import render
2+
3+
# Create your views here.

class-29/in-class-demo-djangox/django_project/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import os
2+
3+
from django.core.asgi import get_asgi_application
4+
5+
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_project.settings")
6+
7+
application = get_asgi_application()

0 commit comments

Comments
 (0)