Django model mixins and utilities.

Overview
Comments
  • Allow FieldTracker on Django user model (and other children of abstract base classes)

    Allow FieldTracker on Django user model (and other children of abstract base classes)

    Problem

    Here is a branch with failing tests that I think should work (and that I think worked in earlier versions?): https://github.com/jazzband/django-model-utils/compare/master...jcushman:abstract-test-failure

    This seems to be related to the stuff that @lucaswiman added in #317. @lucaswiman, I'm hoping based on that work you might have some clever idea for how to fix this. :)

    Here's the situation: you have an abstract base class that defines a static attribute like is_active = True, and a concrete model inheriting from that class that defines a field like is_active = models.BooleanField(default=True). The model then throws an error on save():

    from django.contrib.auth.models import AbstractUser
    
    class MyUser(AbstractUser):
        tracker = FieldTracker()
    
    MyUser().save()
    

    Result:

        def __get__(self, instance, owner):
            if instance is None:
                return self
            was_deferred = self.field_name in instance.get_deferred_fields()
    >       value = self.descriptor.__get__(instance, owner)
    E       AttributeError: 'bool' object has no attribute '__get__'
    
    model_utils/tracker.py:43: AttributeError
    

    It would be great for this to work, because tracking changes on the Django user model is handy.

    Debugging that error, I found the problem boils down to this:

    class AbstractUser(models.Model):
        is_active = True
    
        class Meta:
            abstract = True
    
    class MyUser(AbstractUser):
        is_active = models.BooleanField(default=True)
        tracker = FieldTracker()
    
    MyUser().save()
    

    The reason that fails is https://github.com/jazzband/django-model-utils/blob/master/model_utils/tracker.py#L218 :

    descriptor = getattr(sender, field_name)
    ...
    setattr(sender, field_name, wrapped_descriptor)
    

    ... which boils down to setting MyUser.is_active = DescriptorWrapper(MyUser.is_active). And that doesn't work because you expect MyUser.is_active to start with a value of DeferredAttribute('is_active'), but it actually returns True. For reasons I don't understand, when you override a static attribute on an abstract class, you get the base class's value back instead of the subclass's.

    I tried tweaking tracker.py with variations on descriptor = getattr(sender, field_name) if field_name in sender.__dict__ else DeferredAttribute(field_name), but that broke foreign key fields and feels pretty janky anyway.

    Any ideas on how to get this working?

    Thanks!

    Environment

    • Django Model Utils version: master
    • Django version: 2.1
    • Python version: 3.6
    • Other libraries used, if any:
    opened by jcushman 27
  • Small bug fix and feature addition.

    Small bug fix and feature addition.

    Please note that I have made a choice in the feature addition that people might like to have full downcasting even if the associated select_related isn't available (because of django <1.6 bugs). If you don't like it, feel free to take it out. However, the second part is indeed a bug, if you have multiple grandchildren from a single child, the instance is not the first grandchild checked, but it is a sibling to the grandchild checked, then the child class will be taken instead of continuing on to the other grandchildren.

    • Down-cast to final level even if we can't select the related data (in < 1.6)
    • Fix bug where child classes are accepted if grand-child doesn't match even if there are more grand-child classes to check.

    The second commit is a feature addition to allow casting of related fields (like foreign keys) in what I believe is a query efficient method. I have not yet written unit tests for it, but it does work in the testing I have done (in system testing).

    opened by CrazyCasta 17
  • Feature suggestion: Model mixin for checking for dirty fields

    Feature suggestion: Model mixin for checking for dirty fields

    I'm planning to implement tests and code for a model mixin that keeps track of the original values of the model. I often find this useful for performing tasks in save() methods or pre_save signals (like clearing cache on changes).

    A very simple implementation. Another implementation that supports m2m fields

    I don't think the implementation of this should create any extra DB queries... at least not by default. Feedback on implementation suggestion is welcome.

    Does this sound like a good addition to django-model-utils?

    opened by treyhunner 17
  • Remove Django itself from install_requires

    Remove Django itself from install_requires

    There's an unfortunate side effect of referencing Django itself in setup.py or requirements.txt

    It rather unexpectedly results in an upgrade to Django itself if I type: "pip install django-model-utils -U"

    And really - your app doesn't 'require' django as much as it's an add-on for Django so not much is lost by removing it. Is anyone likely to install django-model-utils and expect it to install Django for them?

    There's a discussion on the same issue here: https://github.com/charettes/django-admin-enhancer/issues/23

    opened by andybak 16
  • Drop unsupported Django versions

    Drop unsupported Django versions

    • Drops support for anything below Django 1.8 (current LTS release)
    • ~~Cleans up some pep8 E303 warnings. I can remove this commit - just went ahead because my editor lit up like a christmas tree.~~
    • ~~Resolves 183~~.
    • Supersedes / closes #162.
    • Supersedes / closes #204.
    opened by rpkilby 15
  • Add django 3.0 to the test matrix and drop six

    Add django 3.0 to the test matrix and drop six

    Problem

    Six won't be used in Django 3.0 so it will cause ImportError

    Solution

    Drop six and add django 3.0 to the test matrix to ensure it is supported

    Commandments

    • [x] Write PEP8 compliant code.
    • [x] Cover it with tests.
    • [x] Update CHANGES.rst file to describe the changes, and quote according issue with GH-<issue_number>.
    • [x] Pay attention to backward compatibility, or if it breaks it, explain why.
    • [x] Update documentation (if relevant).
    opened by mvbrn 14
  • preserve reverse_related_field caches when casting to a subclass

    preserve reverse_related_field caches when casting to a subclass

    I was going to write a test for this but the tests currently fail up to 4 assertions when I run them without making a change. Anyway, I'm new at this whole pull thing so be gentle.

    The issue is if i define a class with a related class:

    class Opportunity(models.Model):
        objects=InheritanceManager()
        pass
    
    class Contest(Opportunity):
        pass
    
    class Terms(models.Model):
        opportunity = models.OneToOneField(Opportunity, related_name='contest_terms')
    

    Calling:

    contests = Opportunity.objects.select_related('contest_terms').filter(id=1)
    t = contests[0].contest_terms
    assert(len(connection.queries)==1)
    

    works because it makes one DB hit and can access the contest_terms as it's been cached by select_related() changing the query in the first line to include select_subclasses:

    contests = Opportunity.objects.select_related('contest_terms').select_subclasses('contest').filter(id=1)
    

    fails because the related object cache is lost after subclassing so it makes the additional hit to the DB to get the terms.

    The fix I proposed will copy the object caches from the base class when _get_sub_obj_recurse finds the appropriate subclass. This will keep the results of select_related() in the returned model instance.

    opened by screamndigit 12
  • Json fields support

    Json fields support

    This improvement will be useful for those who uses the field to store small or medium json-data sets. It is unlikely that the field will store complex data with a high level of nesting (for such problems it's better to use NoSQL), so the overhead of using deepcopy will be negligible, especially given the fact that the protective function (prevent_side_effects) will be called only during initialization. For models without json-fields only one extra loop will be made through the fields during initialization.

    opened by silonov 12
  • Adding ppc64le architecture support on travis-ci

    Adding ppc64le architecture support on travis-ci

    Hi, I had added ppc64le(Linux on Power) architecture support on travis-ci and looks like its been successfully added. I believe it is ready for the final review and merge. Travis-CI build job: https://travis-ci.com/github/kishorkunal-raj/django-model-utils/builds/188852916

    Please have a look.

    Thanks!! Kishor Kunal Raj

    opened by kishorkunal-raj 11
  • Fix handling of deferred fields on django 1.10+

    Fix handling of deferred fields on django 1.10+

    Fixes #278. cc @utapyngo @djstein

    Problem

    Prior to Django 1.10, deferred attributes were handled by constructing a new model class with custom descriptors for the deferred attributes. After 1.10, deferred fields are tracked by whether the attribute is present in the instance __dict__.

    FieldTracker handled tracking on these fields by overwriting the descriptors on the model class. This means that in 1.10+, the instance model class is the model, so FieldTracker can introduce changes to the base class whenever deferred fields are used that persist on other queries. #278 This is reproduced in a test case.

    Solution

    I updated the finalize_class method to wrap field descriptors. This preserves the custom descriptor behavior, and means that deferring fields does not lead to permanent changes in base model classes. This is only done for django versions after 1.10: the previous behavior is preserved for 1.8 and 1.9.

    Since the relevant code branches behavior on unsupported versions of Django, I also removed all branching behavior for versions of django listed as unsupported in the CHANGELOG.

    Commandments

    • [ ] Write PEP8 compliant code.
    • [x] Cover it with tests. Reproduced in test cases, which fail prior to 54cc1507a79460497d40f6cba779f67a4b5f8041 and pass afterwards.
    • [x] Update CHANGES.rst file to describe the changes, and quote according issue with GH-<issue_number>.
    • [x] Pay attention to backward compatibility, or if it breaks it, explain why. The only backwards incompatible change is that the tracker._deferred_fields attribute is not set on django versions >=1.10. Since _deferred_fields is a private attribute, I wouldn't consider this a breaking change.
    • [x] Update documentation (if relevant). _I don't think it is relevant.

    Regarding PEP8, I ran flake8, and it generated a number of errors. I think my code didn't introduce new PEP8 violations, but I'm not sure. If you want, I can submit a separate PR fixing all the PEP8 violations, and rebase onto this branch.

    opened by lucaswiman 11
  • Implemented ability to lie about modified fields

    Implemented ability to lie about modified fields

    This would be a first stab at the changes I was describing in #109, to allow for manually setting the modified attributes of a TimeStampedModel (or, really, the fields backing that model)

    • Are there any other Django API methods that need demonstrating?
    • Changelog/docs would need updating.
    opened by kezabelle 11
  • Add type hints and the py.typed stub

    Add type hints and the py.typed stub

    Problem

    Model utils does not include type hints and py.typed. This prevents tools such as mypy to work properly with it.

    Solution

    Add model_utils/py.typed and a few typing hints.

    Commandments

    • [x] Write PEP8 compliant code.
    • [_] Cover it with tests.
    • [_] Update CHANGES.rst file to describe the changes, and quote according issue with GH-<issue_number>.
    • [x] Pay attention to backward compatibility, or if it breaks it, explain why.
    • [_] Update documentation (if relevant).
    opened by fabiommendes 0
  • Get sublcass queryset only

    Get sublcass queryset only

    I can't get queryset for a particular subclass only. I want to get only products relating that subclass only

    • Django Model Utils version: 4.3.1
    • Django version: 4.1
    • Python version: 3.9
    class Product(models.Model)
    ...
    objects  = InheritanceManager()
    
    
    class Phone(Product)
    ...
    
    class Laptop(Product)
    ...
    

    How do I get querysets for the subclass Phone without any other subclasses instances I have gone through the documentation and didn't find any

    I have built a custom filter that can do but it means I don't need the package and my concern is scalability of the custom implementation. I want to know if the package can help so I don't have to reinvent the wheel.

    opened by KekeliDev 2
  • Add support for Python 3.11

    Add support for Python 3.11

    Problem

    Python 3.11 was released on 2022-10-24 🚀

    image

    We should test it and declare support via the Trove classifier.

    Solution

    Add to tox.ini for local and CI testing, add to GitHub Actions for CI, and add the Trove classifier to declare support.

    Also bump GitHub Actions and add colour to CI logs for readability.

    Commandments

    • [x] Write PEP8 compliant code.
    • [x] Cover it with tests.
    • [x] Update CHANGES.rst file to describe the changes, and quote according issue with GH-<issue_number>.
    • [x] Pay attention to backward compatibility, or if it breaks it, explain why.
    • [x] Update documentation (if relevant).
    opened by hugovk 1
  • Adding async support to `InheritanceManager`/`InheritanceQuerySet`

    Adding async support to `InheritanceManager`/`InheritanceQuerySet`

    Problem

    Hey, since Django ORM is starting to support async more and more, I'm wondering if you guys thought about adding async support to InheritanceManager (and InheritanceQuerySet respectively)?

    Environment

    • Django Model Utils version: 4.2.0
    • Django version: 4.1
    • Python version: 3.10
    • Other libraries used, if any: not-relevant

    Code examples

    So far I was thinking of primitive solution to this problem and I've ended up with something like this, but I have not tested it yet (hopefully will get to testing it in few days). Do you think it should work, or is there some bigger problem about integrating async support to InheritanceManager?

    class ExtendedInheritanceQuerySet(InheritanceQuerySet):
        """InheritanceQuerySet from django-model-utils extended for async methods."""
    
        async def aselect_subclasses(self, *subclasses):
            return await sync_to_async(self.select_subclasses)(*subclasses)
    
        async def aget_subclass(self, *args, **kwargs):
            return await sync_to_async(self.get_subclass)(*args, **kwargs)
    
    
    class ExtendedInheritanceManager(InheritanceManager):
        """InheritanceManager from django-model-utils extended for async methods."""
    
        # todo also possible to create manager dynamically using `from_queryset` or `as_manager`
    
        _queryset_class = ExtendedInheritanceQuerySet
    
        async def aselect_subclasses(self, *subclasses):
            return await self.get_queryset().aselect_subclasses(*subclasses)
    
        async def aget_subclass(self, *args, **kwargs):
            return await self.get_queryset().aget_subclass(*args, **kwargs)
    
    opened by microHoffman 0
  • Inheritance improvments: Select subclasses of foreign relations + get subclass of model fields

    Inheritance improvments: Select subclasses of foreign relations + get subclass of model fields

    Problem

    I wanted to do single query SQL selects of foreign key relations that are using Django model inheritance and found the following two improvements helpful.

    Let me know what you think.

    Code examples

    Improvement to InheritanceQuerySet that is able to select inherited fields of foreign key relationship. Note that this works with multi-level inheritance by letting field_name be a tuple of list of names.

    ` class InheritanceQuerySet(ModelUtilsInheritanceQuerySet):

    def select_field_subclasses(self, field_name):
        # Get field name iterable
        if isinstance(field_name, str):
            field_names = (field_name,)
        else:
            field_names = field_name
    
        # Lookup model
        model = self.model
        for field_name in field_names:
            field = model._meta.get_field(field_name)
            model = field.related_model
    
        # Lookup subclasses
        subclasses = self._get_subclasses_recurse(model)
    
        # Construct query
        subclasses = ['%s__%s' % ('__'.join(field_names), subclass) for subclass in subclasses]
    
        return self.select_related(*subclasses)
    

    `

    Using proper select queries with the above method, subclasses of foreign key relations can be retrieved with the following Model Mixin without touching the database.

    ` class InheritanceMixin:

    def get_subclass(self):
        # Lookup subclasses
        helper = InheritanceQuerySetMixin() # hack to re-use private method of mixin
        subclasses = helper._get_subclasses_recurse(self.__class__)
        
        # Look for existing subclass
        for subclass in subclasses:
            try:
                return getattr(self, subclass)
            except getattr(self.__class__, subclass).RelatedObjectDoesNotExist:
                pass
    
        return self
    

    `

    opened by mortenthansen 0
Releases(4.2.0)
  • 4.2.0(Oct 11, 2021)

    • Add support for Django 3.2
    • Drop support for Django 3.0
    • Add support for Python 3.10
    • Added urlsafe token field.
    • Introduce context manager for FieldTracker state reset (GH-#491)
    • Fix performance regression of FieldTracker on FileField subclasses on Django 3.1+ (GH-#498)
    Source code(tar.gz)
    Source code(zip)
  • 4.1.1(Apr 8, 2021)

    • Applied isort to codebase (Refs GH-402)
    • Fix TypeError in save when model inherits from both TimeStampModel and StatusModel. (Fixes GH-465)
    Source code(tar.gz)
    Source code(zip)
  • 4.1.0(Apr 8, 2021)

    • Update InheritanceQuerySetMixin to avoid querying too much tables
    • TimeStampedModel now automatically adds 'modified' field as an update_fields parameter even if it is forgotten while using save()
    • FieldTracker now marks fields as not changed after refresh_from_db
    • FieldTracker now respects update_fields changed in overridden save() method
    • Replace ugettext_lazy with gettext_lazy to satisfy Django deprecation warning
    • Add available_objects manager to SoftDeletableModel and add deprecation warning to objects manager.
    • StatusModel now automatically adds 'status_changed' field during save as an update_fieldsparameter when 'status' is present in it to make sure it is not forgotten.
    • Update test requirements
    • Move tests to GitHub Actions: https://github.com/jazzband/django-model-utils/actions
    • Drop support for Django 2.1
    • Add support for Python 3.9
    • Add support for Django 3.1
    Source code(tar.gz)
    Source code(zip)
  • 4.0.0(Dec 11, 2019)

    4.0.0 (2019-12-11)

    • Remove hacks for previously supported Django versions. (Fixes GH-390)
    • Dropped support for Python 2.7. (Fixes GH-393)
    • Dropped usage of six
    • Drop support for Django 1.11
    • Add support for Python 3.8
    • Add support for Django 3.0
    Source code(tar.gz)
    Source code(zip)
  • 3.1.2(May 9, 2018)

Owner
Jazzband
Jazzband
Duckiter will Automatically dockerize your Django projects.

Duckiter Duckiter will Automatically dockerize your Django projects. Requirements : - python version : python version 3.6 or upper version - OS :

soroush safari 23 Sep 16, 2021
Django StatusPage - App to display statuspage for your services

Django StatusPage - App to display statuspage for your services

Gorlik 1 Oct 27, 2021
Silk is a live profiling and inspection tool for the Django framework.

Silk is a live profiling and inspection tool for the Django framework. Silk intercepts and stores HTTP requests and database queries before presenting them in a user interface for further inspection:

Jazzband 3.7k Jan 02, 2023
Django Phyton Web Apps template themes

Django Phyton Web Apps template themes Free download source code project for build a modern website using django phyton web apps. Documentation instal

Mesin Kasir 4 Dec 15, 2022
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 06, 2023
Flashback is an awesome, retro IRC based app built using Django

Flashback Flashback is an awesome, retro IRC based app built using Django (and the Django Rest Framework) for the backend as well as React for the fro

Unloading Gnat 1 Dec 22, 2021
Resolve form field arguments dynamically when a form is instantiated

django-forms-dynamic Resolve form field arguments dynamically when a form is instantiated, not when it's declared. Tested against Django 2.2, 3.2 and

DabApps 108 Jan 03, 2023
Django Serverless Cron - Run cron jobs easily in a serverless environment

Django Serverless Cron - Run cron jobs easily in a serverless environment

Paul Onteri 41 Dec 16, 2022
Simple XML-RPC and JSON-RPC server for modern Django

django-modern-rpc Build an XML-RPC and/or JSON-RPC server as part of your Django project. Major Django and Python versions are supported Main features

Antoine Lorence 82 Dec 04, 2022
A better and faster multiple selection widget with suggestions

django-searchable-select A better and faster multiple selection widget with suggestions for Django This project is looking for maintainers! Please ope

Andrew Dunai 105 Oct 22, 2022
Repo for All the Assignments I have to submit for Internship Application !😅

Challenges Repository for All the Assignments I have to submit for Internship Application ! 😅 As You know, When ever We apply for an Internship, They

keshav Sharma 1 Sep 08, 2022
This repository contains django library management system project.

Library Management System Django ** INSTALLATION** First of all install python on your system. Then run pip install -r requirements.txt to required se

whoisdinanath 1 Dec 26, 2022
An orgizational tool to keep track of tasks/projects and the time spent on them.

Django-Task-Manager Task Tracker using Python Django About The Project This project is an orgizational tool to keep track of tasks/projects and the ti

Nick Newton 1 Dec 21, 2021
File and Image Management Application for django

Django Filer django Filer is a file management application for django that makes handling of files and images a breeze. Contributing This is a an open

django CMS Association 1.6k Dec 28, 2022
Simple yet powerful and really extendable application for managing a blog within your Django Web site.

Django Blog Zinnia Simple yet powerful and really extendable application for managing a blog within your Django Web site. Zinnia has been made for pub

Julien Fache 2.1k Dec 24, 2022
django social media app with real time features

django-social-media django social media app with these features: signup, login and old registered users are saved by cookies posts, comments, replies,

8 Apr 30, 2022
A pluggable Django application for integrating PayPal Payments Standard or Payments Pro

Django PayPal Django PayPal is a pluggable application that integrates with PayPal Payments Standard and Payments Pro. See https://django-paypal.readt

Luke Plant 672 Dec 22, 2022
REST API con Python, Django y MySQL (GET, POST, PUT, DELETE)

django_api_mysql REST API con Python, Django y MySQL (GET, POST, PUT, DELETE) REST API con Python, Django y MySQL (GET, POST, PUT, DELETE)

Andrew 1 Dec 28, 2021
ProjectManagementWebsite - Project management website for CMSC495 built using the Django stack

ProjectManagementWebsite A minimal project management website for CMSC495 built

Justin 1 May 23, 2022
A Redis cache backend for django

Redis Django Cache Backend A Redis cache backend for Django Docs can be found at http://django-redis-cache.readthedocs.org/en/latest/. Changelog 3.0.0

Sean Bleier 1k Dec 15, 2022