Giter Site home page Giter Site logo

skorokithakis / django-annoying Goto Github PK

View Code? Open in Web Editor NEW
918.0 918.0 85.0 185 KB

A django application that tries to eliminate annoying things in the Django framework. ⛺

Home Page: http://skorokithakis.github.io/django-annoying

License: BSD 3-Clause "New" or "Revised" License

Python 99.73% Shell 0.27%

django-annoying's Introduction

Description

Code Shelter

This django application eliminates certain annoyances in the Django framework.

Features

Installation instructions

  • Copy the annoying directory to your django project or put in on your PYTHONPATH.
  • You can also run python setup.py install, easy_install django-annoying, or pip install django-annoying.
  • Add "annoying" under INSTALLED_APPS in your settings.py file.
  • Django-annoying requires Django 1.11 or later.

Examples

render_to decorator

from annoying.decorators import render_to

# 1. Template name in decorator parameters

@render_to('template.html')
def foo(request):
    bar = Bar.object.all()
    return {'bar': bar}

# equals to
def foo(request):
    bar = Bar.object.all()
    return render(request, 'template.html', {'bar': bar})


# 2. Template name as TEMPLATE item value in return dictionary

@render_to()
def foo(request, category):
    template_name = '%s.html' % category
    return {'bar': bar, 'TEMPLATE': template_name}

#equals to
def foo(request, category):
    template_name = '%s.html' % category
    return render(request, template_name, {'bar': bar})

signals decorator

Note: signals is deprecated and will be removed in a future version. Django now includes this by default.

from annoying.decorators import signals

# connect to registered signal
@signals.post_save(sender=YourModel)
def sighandler(instance, **kwargs):
    pass

# connect to any signal
signals.register_signal(siginstance, signame) # and then as in example above

#or

@signals(siginstance, sender=YourModel)
def sighandler(instance, **kwargs):
    pass

#In any case defined function will remain as is, without any changes.

ajax_request decorator

The ajax_request decorator converts a dict or list returned by a view to a JSON or YAML object, depending on the HTTP Accept header (defaults to JSON, requires PyYAML if you want to accept YAML).

from annoying.decorators import ajax_request

@ajax_request
def my_view(request):
    news = News.objects.all()
    news_titles = [entry.title for entry in news]
    return {'news_titles': news_titles}

autostrip decorator

Note: autostrip is deprecated and will be removed in a future version. Django now includes this by default.

from annoying.decorators import autostrip

@autostrip
class PersonForm(forms.Form):
    name = forms.CharField(min_length=2, max_length=10)
    email = forms.EmailField()

get_object_or_None function

from annoying.functions import get_object_or_None

def get_user(request, user_id):
    user = get_object_or_None(User, id=user_id)
    if not user:
        ...

AutoOneToOneField

from annoying.fields import AutoOneToOneField


class MyProfile(models.Model):
    user = AutoOneToOneField(User, primary_key=True)
    home_page = models.URLField(max_length=255, blank=True)
    icq = models.IntegerField(blank=True, null=True)

JSONField

Note that if you're using Postgres you can use the built-in django.contrib.postgres.fields.JSONField, or if you're using MySQL/MariaDB you can use Django-MySQL's JSONField.

from annoying.fields import JSONField


#model
class Page(models.Model):
    data = JSONField(blank=True, null=True)



# view or another place..
page = Page.objects.get(pk=5)
page.data = {'title': 'test', 'type': 3}
page.save()

get_config function

from annoying.functions import get_config

ADMIN_EMAIL = get_config('ADMIN_EMAIL', '[email protected]')

StaticServer middleware

Add this middleware as first item in MIDDLEWARE_CLASSES(or MIDDLEWARE)

example:

MIDDLEWARE_CLASSES = (  # MIDDLEWARE if you're using the new-style middleware
    'annoying.middlewares.StaticServe',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.doc.XViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
)

It will serve static files in debug mode. Also it helps when you debug one of your middleware by responding to static requests before they get to debugged middleware and will save you from constantly typing "continue" in debugger.

get_object_or_this function

from annoying.functions import get_object_or_this

def get_site(site_id):
    base_site = Site.objects.get(id=1)

    # Get site with site_id or return base site.
    site = get_object_or_this(Site, base_site, id=site_id)

    ...
    ...
    ...

    return site

django-annoying's People

Contributors

ambroisie avatar artscoop avatar ashwch avatar atugushev avatar benbacardi avatar beniwohli avatar cezio avatar denis-sukhoverkhov avatar denisenkom avatar edelvalle avatar fruitschen avatar geekfish avatar iorlas avatar jdufresne avatar jrog612 avatar jshwright avatar kabakchey avatar kmike avatar mgalgs avatar mikebryant avatar moggers87 avatar mstevens avatar razpeitia avatar sir-sigurd avatar sirodoht avatar skorokithakis avatar st4lk avatar suvit avatar vladimirkuzmin avatar wrar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-annoying's Issues

Default dict value in JSONField causes non-valid JSON string stored in db.

I have a model with JSONField with default value set to constant dict value.

The default value was stored in db as non-valid json.

I was able to work around this by changing this line (in my model):
visual_config = JSONField(default=DEFAULT_PARAMETERS['visual_config'], blank=False, null=False)
With this:
visual_config = JSONField(default=lambda: CustomerConfig.DEFAULT_PARAMETERS['visual_config'], blank=False, null=False)

Notice that I added default value as lambda function.

This is caused by django default Field.get_default method, which runs force_text method on the default value if it is not callable:

def get_default(self):
        """
        Returns the default value for this field.
        """
        if self.has_default():
            if callable(self.default):
                return self.default()
            return force_text(self.default, strings_only=True)
        if (not self.empty_strings_allowed or (self.null and
                   not connection.features.interprets_empty_strings_as_nulls)):
            return None
        return ""

My idea for a fix would be to override the get_default method in JSONField.

Cheers,
Maciej

Support for django v3

I am currently trying to update to using django 3.0.3, but django-annoying throws an error:

 File "/home/dani/anaconda3/envs/artheseus/lib/python3.7/site-packages/annoying/fields.py", line 11, in <module>
    from django.utils import six
ImportError: cannot import name 'six' from 'django.utils' (/home/dani/anaconda3/envs/artheseus/lib/python3.7/site-packages/django/utils/__init__.py)

Indedd django.utils.six. was removed in version 3:
django/django@4138481

The problem with JsonField.

Hey.
Quite simply, there is a model:

class Page (models.Model):
data = JSONField (blank = True, null = True)

Save and try to bring a dictionary:

page = Page.objects.get (pk = 5)
page.data = {'title': 'test', 'type': 3}
page.save ()
page.data

u"{'title': 'test', 'type': 3}"
Page.data.get ('title')
AttributeError: 'unicode' object has no attribute 'get'

How to put a line (u "{'title': 'test', 'type': 3}") returns json to normal, to get the desired dictionary?
In patterns, the dictionary is given as a string, not as an object.
How can you get a dictionary, not a string?

Django 1.4
django-annoying - last version
Python 2.7

Sorry for my English! I'm from Russia, used the Google TRANSLATE.

New PyPi Release?

Hey there,

The last release of django-annoying to PyPi was 9 months ago, and several changes have been made since (e.g. making JSONField compatible with Python 3).

Is a new release planned for soon?

Thanks!

AutoOneToOne doesn't work

System

OS: Linux
Python: 3.5.1
Django: 1.9.5
Annoying: 0.9.0

Example

From README.md.

from annoying.fields import AutoOneToOneField

class MyProfile(models.Model):
    user = AutoOneToOneField(User, primary_key=True)
    home_page = models.URLField(max_length=255, blank=True)
    icq = models.IntegerField(blank=True, null=True)

Description

I have try your example but it doesnt't work. I have no error messages. The field works lika a regular OneToOne field.

Can't import simplejson?

I'm trying to get annoying set up with django 1.7, and am getting a namespace error when attempting to use render_to; namely that simplejson doesn't exist.

I know that simplejson has been deprecated, and that json is being used instead, but I'm not sure how to get around django-annoying looking for ``simplejson` at the moment.

I'm sure I'm not the only person to encounter this. Help please!

ValidationError hiden when use autostrip decorator

autostrip decorator quietly hides ValidationError by CharField.clean method, if the field attribute required has been changed in a form constructor.

Example models:

    from django.db import models

    class Example(models.Model):
        name = models.CharField(u'Example', null=True, blank=True, max_length=255)

Example forms:

    from annoying.decorators import autostrip
    from django.forms import ModelForm, ValidationError


    class ExampleForm(ModelForm):
        class Meta:
            model = Example

        def __init__(self, *args, **kwargs):
            super(ExampleForm, self).__init__(*args, **kwargs)
            self.fields['name'].required = True

    AutostripExampleForm = autostrip(ExampleForm)

Example test case:

    form = AutostripExampleForm(data={'name': ''})
    assert not form.is_valid()
    assert form.cleaned_data.get('name') is None

In this case form.is_valid() return True and form.cleaned_data.get('name') returns None.

Tested with versions:
Django==1.5.8 and Django==1.6.
django-annoying==0.8.0
Python == 2.7.6

Django 1.9: Cannot import name SingleRelatedObjectDescriptor

I'm trying to upgrade to 1.9 and 0.8.4 django-annoying references a class that has been renamed:

  File "/Users/john/.venv/mm19/lib/python2.7/site-packages/django/apps/config.py", line 202, in import_models
    self.models_module = import_module(models_module_name)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
    __import__(name)
  File "/Users/john/git/ballprice19/mysite/snakes/models.py", line 23, in <module>
    from annoying.fields import AutoOneToOneField
  File "/Users/john/.venv/mm19/lib/python2.7/site-packages/annoying/fields.py", line 4, in <module>
    from django.db.models.fields.related import SingleRelatedObjectDescriptor
ImportError: cannot import name SingleRelatedObjectDescriptor

Release notes say: SingleRelatedObjectDescriptor is ReverseOneToOneDescriptor

related to #44

Using AutoOneToOneField with proxy model

When using AutoOneToOneField with Proxy model, I've a hard time to get the related model. The similar setup with OneToOneField doesn't have problem. While I check the code I found a difference here:

class AutoOneToOneField(OneToOneField):
    def contribute_to_related_class(self, cls, related):
        setattr(
            cls,
            related.get_accessor_name(),
            AutoSingleRelatedObjectDescriptor(related)
        )

Studying Django's code:

class ForeignObject(RelatedField):
    def contribute_to_related_class(self, cls, related):
        if not self.remote_field.is_hidden() and not related.related_model._meta.swapped:
            setattr(cls._meta.concrete_model, related.get_accessor_name(), self.related_accessor_class(related))
            if self.remote_field.limit_choices_to:
                cls._meta.related_fkey_lookups.append(self.remote_field.limit_choices_to)

When calling setattr(...), should AutoOneToOneField also pass in cls._meta.concrete_model instead?

autostrip decorator doesn't work in ModelAdmin

If I add autostrip decorator on a ModelForm and call is_valid method on the form in my own view, white spaces are stripped correctly. But if I tell a ModelAdmin to use this decorated form as the form, white spaces won't be stripped when I edit the model and save inside Admin pages.

Django 1.9

InvalidTemplateLibrary at /admin/login/
Invalid template library specified. ImportError raised when trying to load 'annoying.templatetags.annoying': No module named 'smart_if'

Thanks.

Django5 Support?

May I respectfully ask when Django 5 support will be added?

It's not currently listed as supported, so as a result myself and others will simply avoid it out of an abundance of caution unless a release is cut that officially does so.

I still believe that there are some very valuable items in here, but I'm noticing open bugs for things like the AutoOneToOneField field, which is one of the biggest ones for me.

Django 1.11 middleware

Falls down,

https://docs.djangoproject.com/en/1.11/topics/http/middleware/#upgrading-middleware

import re

from django.conf import settings
from django.views.static import serve
from django.shortcuts import redirect

from .exceptions import Redirect


from django.utils.deprecation import MiddlewareMixin


class StaticServe(MiddlewareMixin):
    """
    Django middleware for serving static files instead of using urls.py
    """
    regex = re.compile(r'^%s(?P<path>.*)$' % settings.MEDIA_URL)

    def process_request(self, request):
        if settings.DEBUG:
            match = self.regex.search(request.path)
            if match:
                return serve(request, match.group(1), settings.MEDIA_ROOT)


class RedirectMiddleware(MiddlewareMixin):
    """
    You must add this middleware to MIDDLEWARE_CLASSES list,
    to make work Redirect exception. All arguments passed to
    Redirect will be passed to django built in redirect function.
    """
    def process_exception(self, request, exception):
        if not isinstance(exception, Redirect):
            return
        return redirect(*exception.args, **exception.kwargs)`

may be solution

Setting HTTP status code when using ajax_request

The ajax_request decorator lets you return a dictionary or list from your function, and it will convert it to JSON for you.

I would like to return a dictionary representing an error, and I would like to set the HTTP code to something other than 200, maybe 400 Bad Request. How can I do that if I am using ajax_request?

from annoying.decorators import ajax_request

@ajax_request
def foobar(request):
    # how do I set HTTP status code to 400?
    return {"error": "example"}

Possible to add support for types?

I have been enjoying using get_object_or_None all over my project in place of lazy incorrect .first() calls, and it's really great. However, it has the downside of losing the information about the object's type. Pyright tells me the returned type is Unknown | None, even though I know it has to be the corresponding type of the Model | QuerySet | BaseManager that I passed as klass.

image

add south rules for model fields

for AutoOneToOneField this should work:

# South rules
rules = [
    (
        (AutoOneToOneField,),
        [],
        {
            "to": ["rel.to", {}],
            "to_field": ["rel.field_name", {"default_attr": "rel.to._meta.pk.name"}],
            "related_name": ["rel.related_name", {"default": None}],
            "db_index": ["db_index", {"default": True}],
        },
    )
]
from south.modelsinspector import add_introspection_rules
add_introspection_rules(rules, ["^annoying\.fields\.AutoOneToOneField"])

Incompatibilities with Django 1.7

Django Annoying needs contrib middlewares which are deprecated in Django 1.7 so it is no longer working without them.

All the best.

AutoOneToOneField gives IntegrityError

class TestMe1(models.Model):
test = models.CharField(max_length=100, blank=True, default='')

class TestMe(models.Model):
base_class = AutoOneToOneField(TestMe1)

TestMe.objects.create()
IntegrityError: null value in column "base_class_id" violates not-null constraint
DETAIL: Failing row contains (1, null).

Here is the traceback:
https://dpaste.de/5XpiR/

Enchance exception middleware and support richer exception hierarchy

Redirect middleware is a very good idea, but it's usage is quite narrow. It would be good to use more generic approach, with richer exception hierarchy, which would allow to handle other response types.

Sample use case:

  • you use CBV
  • you check a condition in .get_context(), which is important to any furtner processing in the view,
  • condition is not met and all processing should be halted, client should receive some 4xx response
  • without such infrastructure, get_context should return dictionary, which should be processed by view, which should check the dict and return error response.
  • with such infrastructure you can raise proper exception and handle it the middleware whithout boilerplate code in the view.

Test don't run against Django 1.7+

As the title says, when trying to run the tests against Django 1.7.5 or Django 1.8.5 I get the following traceback:

Traceback (most recent call last):
  File "test.py", line 35, in <module>
    models.loading.cache.app_store[type(this + '.models', (), {'__file__':__file__})] = this
AttributeError: 'module' object has no attribute 'loading'

I'm not sure what the "official" supported versions of Django for this library are.

AutoOneToOneField breaks Django admin lookups

Imagine a lookup model_a__model_b__field_c added to a ModelAdmin.list_filters, which employs AutoOneToOneField as a relationship field between model_a and model_b.

Method lookup_allowed would return false once you try to use it. This is where it goes wrong: https://github.com/django/django/blame/4420761ea9457d386b2000cf9df5b2f6f88f8f91/django/contrib/admin/options.py#L382

            # It is allowed to filter on values that would be found from local
            # model anyways. For example, if you filter on employee__department__id,
            # then the id value would be found already from employee__department_id.
            if not prev_field or (prev_field.is_relation and
                                  field not in prev_field.get_path_info()[-1].target_fields):
                relation_parts.append(part)

While debugging I can see that contents of .target_fields is (<annoying.fields.AutoOneToOneField: model_b>,) at the moment of second iteration, that's what results in False for this whole condition here.

Thus the field is being erroneously excluded from relation_parts list within the method which later leads to clean_lookup becoming model_a__field_c instead of its correct form.

Even with these comments I don't fully understand the purpose of this code and what's expected from the field in this case. List of .target_fields should be empty? Is that universally correct or just within this code?

Could it be that the bug is within Django and not Annoying code? Any ideas how to solve it?

P.S. This might be very confusing. Let me know if any clarification is needed.

An AutoOneToOneField that works with Django 1.8

If anyone comes here looking for it here's the relevant bit:

class AutoSingleRelatedObjectDescriptor(SingleRelatedObjectDescriptor):
    """
    The descriptor that handles the object creation for an AutoOneToOneField.
    """
    def __get__(self, instance, instance_type=None):
        model = getattr(self.related, 'related_model', self.related.model)

        try:
            return (super(AutoSingleRelatedObjectDescriptor, self)
                    .__get__(instance, instance_type))
        except model.DoesNotExist:
            obj = model(**{self.related.field.name: instance})

            obj.save()

            # Don't return obj directly, otherwise it won't be added
            # to Django's cache, and the first 2 calls to obj.relobj
            # will return 2 different in-memory objects
            return (super(AutoSingleRelatedObjectDescriptor, self)
                    .__get__(instance, instance_type))

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.