Skip to content

Commit

Permalink
Merge pull request #60 from ChanTsune/develop
Browse files Browse the repository at this point in the history
[release] 1.2.1
  • Loading branch information
ChanTsune authored Oct 30, 2019
2 parents c84d0d4 + cbe5ad8 commit 65460c9
Show file tree
Hide file tree
Showing 39 changed files with 1,993 additions and 99 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ python:
- "3.5"
- "3.6"
- "3.7"
- "3.8"
- "pypy3"
env:
- DJANGO_VERSION=2.0
Expand All @@ -16,4 +17,4 @@ install:
- "pip install tox-travis pillow"
script:
- tox
- python manage.py test
- "python manage.py auto_migrate_test --remove"
6 changes: 6 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@

## Versions

### 1.2.1

- Update
- new option `--name_field` to `adminsitelog` command.
- Supports cases where model has `ManyToManyField`(`RelatedModelInlineMixin`).

### 1.2

- Add
Expand Down
119 changes: 31 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ Extension library to boost django development
[![PyPI - Wheel](https://img.shields.io/pypi/wheel/django_boost)](https://pypi.org/project/django-boost/)
[![Downloads](https://pepy.tech/badge/django-boost)](https://pepy.tech/project/django-boost)

## Documentation

[https://django-boost.readthedocs.io/en/latest/](https://django-boost.readthedocs.io/en/latest/)

## Installation

```bash
Expand All @@ -33,11 +37,9 @@ INSTALLED_APPS = [
]
```

## use case

### Custom User
## Brief introduction

#### EmailUser
### EmailUser

`settings.py`

Expand All @@ -48,7 +50,7 @@ AUTH_USER_MODEL = 'django_boost.EmailUser'
Replace Django default user model
Use email address instead of username when logging in

#### AbstractEmailUser
### AbstractEmailUser

```py
from django.db import models
Expand All @@ -62,9 +64,7 @@ class CustomUser(AbstractEmailUser):

Available when you want to add a field to EmailUser

### ModelMixins

#### UUIDModelMixin
### UUIDModelMixin

```py
from django.db import models
Expand All @@ -77,7 +77,7 @@ class Stock(UUIDModelMixin):

Mixins that replace `id` from `AutoField` to `UUIDField`

#### TimeStampModelMixin
### TimeStampModelMixin

```py
from django.db import models
Expand All @@ -95,22 +95,7 @@ posted_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
```

#### Combine

```py
from django.db import models
from django_boost.models.mixins import UUIDModelMixin, TimeStampModelMixin

class Stock(UUIDModelMixin,TimeStampModelMixin):
name = models.CharField(max_length=128)
count = models.IntegerField()
```

Model mixins can also be combined in this way.

### Fields

#### ColorCodeField
### ColorCodeField

```py
from django.db import models
Expand All @@ -128,24 +113,23 @@ You can not specify both at the same time.
If neither is set, the string is saved without any changes.
Default is `upper=False`,`lower=Flase`.

#### SplitDateTimeField
### SplitDateTimeField

```py
from django.db import models
from django_boost.models.fields import SplitDateTimeField

class MyModel(models.Model):
color = SplitDateTimeField()

date = SplitDateTimeField()
```

A little convenient DateTimeField.

form_class in django.models.db.DateTimeField is replaced with
django.forms.SplitDateTimeField.
The effect on DB is the same as django.models.db.DateTimeField.
`SplitDateTimeField` is the form_class of `django.models.db.DateTimeField` replaced with `django.forms.SplitDateTimeField`.

Internal DB field is the same as `django.models.db.DateTimeField`.

#### AutoOneToOneField
### AutoOneToOneField

```py
from django.db import models
Expand All @@ -156,9 +140,7 @@ class UserProfile(models.Model):
home_page = models.URLField(max_length=255, blank=True)
```

### Middleware

#### RedirectCorrectHostnameMiddleware
### RedirectCorrectHostnameMiddleware

`settings.py`

Expand All @@ -185,7 +167,7 @@ This is useful when migrating domains

Originally it should be done with server software such as nginx and apache, but it is useful when the setting is troublesome or when using services such as heroku

#### HttpStatusCodeExceptionMiddleware
### HttpStatusCodeExceptionMiddleware

`settings.py`

Expand Down Expand Up @@ -215,11 +197,9 @@ def view(request):

```

It is necessary to set `HttpStatusCodeExceptionMiddleware` to use

### Template context
This Middleware is required when using `HttpStatusCodeExceptionMiddleware`

#### User Agent
### User Agent in Template context

```py
TEMPLATES = [
Expand Down Expand Up @@ -257,9 +237,7 @@ When given a user agent like `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) Ap

These information is obtained using [user-agents](https://github.com/selwin/python-user-agents)

### Access Mixins

#### AllowContentTypeMixin
### AllowContentTypeMixin

Restrict the content type of http request.

Expand All @@ -278,7 +256,7 @@ Restrict request based on `Content-Type` of http header.
If the content type is not allowed, http415 response will be returned.
You can disable restrictions by specifying `strictly = False`

#### ReAuthenticationRequiredMixin
### ReAuthenticationRequiredMixin

```py
from django.views.generic import TemplateView
Expand Down Expand Up @@ -306,7 +284,7 @@ Can specify `int` and `timedelta` ,`None`.
`logout=True`, Logout if the specified time limit has passed
`logout=False`, Do not logout Even if the specified time limit has passed

#### LimitedTermMixin
### LimitedTermMixin

```py
from datetime import datetime
Expand All @@ -328,9 +306,7 @@ You can change the date and time that can be accessed dynamically by overriding
You can specify the exception class to be thrown when the condition accessible to `exception_class` is not met.
The default is the `Http404` exception.

### Redirect Control Mixins

#### DynamicRedirectMixin
### DynamicRedirectMixin

You can control the redirect destination with `next=~` in the URL query string like `LoginView`.

Expand All @@ -345,9 +321,7 @@ class MyFormView(DynamicRedirectMixin, FormView):

You can change the query string parameter name by changing `redirect_field_name`.

### Adittional Attribute Mixins

#### UserAgentMixin
### UserAgentMixin

```py
from django_boost.views.generic import TemplateView
Expand All @@ -365,7 +339,7 @@ Assign `user_agent` attribute to `self.request` and switch the template file to
If the user agent can not be determined, the template specified in `template_name` will be used.
`pc_template_name`,`tablet_template_name`,`mobile_template_name` has no arms, but `template_name` is required.

#### JsonRequestMixin
### JsonRequestMixin

A specialized mixin for `AllowContentTypeMixin` for json.

Expand All @@ -386,9 +360,7 @@ You can access the dictionary object parsed from the Json string sent by the cli

If you use for the purpose of API `JsonView` below is recommended.

### ResponseMixin

#### JsonResponseMixin
### JsonResponseMixin

Returns the response in Json format

Expand All @@ -413,9 +385,7 @@ Specify `strictly = True` if you want to limit the Content-Type to Json only.

If you use for the purpose of API `JsonView` below is recommended.

### Form Mixin

#### MatchedObjectGetMixin
### MatchedObjectGetMixin

Object of the condition that matches the form input content.
Or mixin to add a method to get the queryset.
Expand Down Expand Up @@ -450,7 +420,7 @@ class CustomerSearchView(FormView):

`MatchedObjectMixin` provides `get_object` and `get_list` methods, each of which returns a `model object` or `queryset` that matches the form input content.

#### RelatedModelInlineMixin
### RelatedModelInlineMixin

Mixin that treat two related `Model`'s as a single `Model`.

Expand Down Expand Up @@ -552,31 +522,6 @@ In the template you can use as follows.

The name of the URL is defined under the namespace of the lower-cased model class name.

##### Case of Namespaced

`urls.py`

```py
from django.urls import path, include
from . import views

app_name = "myapp"
urlpatterns = [
path('views/',include(views.CustomerViews(app_name="myapp:customer").urls)),
]

```

In the template you can use as follows.

```html+django
{% url 'myapp:customer:list' %}
{% url 'myapp:customer:create' %}
{% url 'myapp:customer:detail' %}
{% url 'myapp:customer:update' %}
{% url 'myapp:customer:delete' %}
```

### Path Converters

```py
Expand Down Expand Up @@ -605,7 +550,7 @@ These are passed as `int` type to the python program.

Keywords that end with `_str` are passed as `str` type to python program.

### Short Cut Functions
### Shortcut Functions

```py
from django_boost.shortcuts import (
Expand All @@ -621,9 +566,7 @@ get_object_or_exception(MyModel, exception=Exception, id=2)

These behave like `get_object_or_404`

### Routing Utilitys

#### UrlSet
### UrlSet

If URLs corresponding to multiple models are described in one `urls.py`, it may be redundant.
As below.
Expand Down
2 changes: 1 addition & 1 deletion django_boost/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from django.utils.version import get_version

VERSION = (1, 2, 0, 'final', 0)
VERSION = (1, 2, 1, 'final', 0)

__version__ = get_version(VERSION)
27 changes: 24 additions & 3 deletions django_boost/forms/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,17 +130,38 @@ def save(self, commit=True):
rel_opts = related_model._meta
pk_field_name = rel_opts.pk.attname
rel_pk_field_name = '%s_%s' % (field, pk_field_name)
if getattr(object, rel_pk_field_name) is None:
if not hasattr(object, rel_pk_field_name): # case of reverse access
if hasattr(object, field):
target_field = getattr(object, field)
else:
name = None
for f in rel_opts.fields:
if f.related_model == type(object):
name = f.name
object.save() ##
target_field = related_model(**{name:object})
elif getattr(object, rel_pk_field_name) is None:
target_field = related_model()
else:
target_field = getattr(object, field)
for related_field in related_fields:
setattr(target_field, related_field,
self.cleaned_data['%s_%s' % (field, related_field)])
value = self.cleaned_data['%s_%s' % (field, related_field)]
if self._is_many_to_many(rel_opts, related_field):
target_field.save() ##
getattr(target_field, related_field).set(value)
else:
setattr(target_field, related_field, value)
if commit:
target_field.save()
setattr(object, rel_pk_field_name, target_field.pk)
setattr(object, field, target_field)
if commit:
object.save()
return object


def _is_many_to_many(self, rel_opts, field_name):
for f in rel_opts.many_to_many:
if f.attname == field_name:
return True
return False
9 changes: 8 additions & 1 deletion django_boost/forms/widgets.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
from django.forms.widgets import Input
from django.forms.widgets import Input, RadioSelect


class ColorInput(Input):
"""HTML <input type='color'>."""

input_type = 'color'
template_name = 'django/forms/widgets/input.html'


class StarRateSelect(RadioSelect):
"""Star styled radio select."""

template_name = "boost/forms/widgets/star_radio.html"
option_template_name = "boost/forms/widgets/star_radio_input.html"
Loading

0 comments on commit 65460c9

Please sign in to comment.