Utilities for implementing a modified pre-order traversal tree in django.

Related tags

Djangodjango-mptt
Overview

django-mptt

Utilities for implementing Modified Preorder Tree Traversal with your Django Models and working with trees of Model instances.

Build Status

Project home: https://github.com/django-mptt/django-mptt/

Documentation: https://django-mptt.readthedocs.io/

Discussion group: https://groups.google.com/forum/#!forum/django-mptt-dev

What is Modified Preorder Tree Traversal?

MPTT is a technique for storing hierarchical data in a database. The aim is to make retrieval operations very efficient.

The trade-off for this efficiency is that performing inserts and moving items around the tree is more involved, as there's some extra work required to keep the tree structure in a good state at all times.

Here are a few articles about MPTT to whet your appetite and provide details about how the technique itself works:

What is django-mptt?

django-mptt is a reusable Django app which aims to make it easy for you to use MPTT with your own Django models.

It takes care of the details of managing a database table as a tree structure and provides tools for working with trees of model instances.

Requirements

  • Python 3.5+
  • A supported version of Django (currently 1.11+)

Feature overview

  • Simple registration of models - fields required for tree structure will be added automatically.
  • The tree structure is automatically updated when you create or delete model instances, or change an instance's parent.
  • Each level of the tree is automatically sorted by a field (or fields) of your choice.
  • New model methods are added to each registered model for:
    • changing position in the tree
    • retrieving ancestors, siblings, descendants
    • counting descendants
    • other tree-related operations
  • A TreeManager manager is added to all registered models. This provides methods to:
    • move nodes around a tree, or into a different tree
    • insert a node anywhere in a tree
    • rebuild the MPTT fields for the tree (useful when you do bulk updates outside of django)
  • Form fields for tree models.
  • Utility functions for tree models.
  • Template tags and filters for rendering trees.
  • Admin classes for visualizing and modifying trees in Django's administration interface.
Comments
  • Django 1.10 support: can't set attribute _default_manager at startup

    Django 1.10 support: can't set attribute _default_manager at startup

    While testing Django 1.10, mptt seems to mess with internal API of the framework, that has changed since 1.9. Here's the stacktrace I get at the loading of manage.py runserver:

    $ ./manage.py runserver
    Unhandled exception in thread started by <function wrapper at 0x7f32e681faa0>
    Traceback (most recent call last):
      File "My_VENV/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
        fn(*args, **kwargs)
      File "My_VENV/lib/python2.7/site-packages/django/core/management/commands/runserver.py", line 113, in inner_run
        autoreload.raise_last_exception()
      File "My_VENV/lib/python2.7/site-packages/django/utils/autoreload.py", line 249, in raise_last_exception
        six.reraise(*_exception)
      File "My_VENV/lib/python2.7/site-packages/django/utils/autoreload.py", line 226, in wrapper
        fn(*args, **kwargs)
      File "My_VENV/lib/python2.7/site-packages/django/__init__.py", line 27, in setup
        apps.populate(settings.INSTALLED_APPS)
      File "My_VENV/lib/python2.7/site-packages/django/apps/registry.py", line 108, in populate
        app_config.import_models(all_models)
      File "My_VENV/lib/python2.7/site-packages/django/apps/config.py", line 199, in import_models
        self.models_module = import_module(models_module_name)
      File "/usr/lib/python2.7/importlib/__init__.py", line 37, in import_module
        __import__(name)
      File "My_VENV/lib/python2.7/site-packages/mptt/models.py", line 379, in <module>
        class MPTTModel(six.with_metaclass(MPTTModelBase, models.Model)):
      File "My_VENV/lib/python2.7/site-packages/django/utils/six.py", line 808, in __new__
        return meta(name, bases, d)
      File "My_VENV/lib/python2.7/site-packages/mptt/models.py", line 262, in __new__
        cls = super_new(meta, class_name, bases, class_dict)
      File "My_VENV/lib/python2.7/site-packages/django/db/models/base.py", line 157, in __new__
        new_class.add_to_class(obj_name, obj)
      File "My_VENV/lib/python2.7/site-packages/django/db/models/base.py", line 316, in add_to_class
        value.contribute_to_class(cls, name)
      File "My_VENV/lib/python2.7/site-packages/mptt/managers.py", line 81, in contribute_to_class
        super(TreeManager, self).contribute_to_class(model, name)
      File "My_VENV/lib/python2.7/site-packages/django/db/models/manager.py", line 120, in contribute_to_class
        setattr(model, name, ManagerDescriptor(self))
    AttributeError: can't set attribute
    

    In contribute_to_class (the method in Django file), arguments are model=<class 'mptt.models.MPTTModel'> name=_default_manager. It looks like _default_manager is now read only.

    It might be linked to the following change (from the release notes):

    The new Meta.base_manager_name and Meta.default_manager_name options allow controlling the _base_manager and _default_manager, respectively.

    Defect 
    opened by mlorant 37
  • Tree gets corrupted when concurrently adding multiple root objects

    Tree gets corrupted when concurrently adding multiple root objects

    Reproduced with django-mptt 0.5.2

    Steps to reproduce:

    1. Concurrently add 5 root MPTTModel objects
    2. Check the tree ids of the newly created objects

    Expected: Each object has a separate tree_id

    Actual: All tree ids are the same

    The problem is in:

    def insert_node(self, node, target, position='last-child', save=False, allow_existing_pk=False):
        if self._base_manager:
            return self._base_manager.insert_node(node, target, position=position, save=save)
        if node.pk and not allow_existing_pk and _exists(self.filter(pk=node.pk)):
            raise ValueError(_('Cannot insert a node which has already been saved.'))
        if target is None:
            setattr(node, self.left_attr, 1)
            setattr(node, self.right_attr, 2)
            setattr(node, self.level_attr, 0)
            setattr(node, self.tree_id_attr, self._get_next_tree_id())
            setattr(node, self.parent_attr, None)
    

    All requests call insert_node before the new MPTTModel gets saved => all new objects will get the same tree id...

    I don't know how this can be fixed... Probably acquire read locks on the entire table when adding new objects? The problem with this is that it would be a performance overkill.

    opened by kux 27
  • Make `_get_queryset_relatives` generate more efficient SQL

    Make `_get_queryset_relatives` generate more efficient SQL

    Explanation:

    I'll use the following tree from this article in the explanation that follows:

    mptt tree

    Given the tree above, we know that in order to retrieve the descendants of the Meat node, we need to execute an SQL query that looks like this:

    SELECT * FROM tree WHERE lft BETWEEN 12 AND 17;
    

    And for the ancestors of the Pork node, we'd need to execute an SQL query that looks like this:

    SELECT * FROM tree WHERE lft < 15 AND rght > 16;
    

    But what if we wanted the all of the descendants of both the Fruit and Meat nodes? We could do the following:

    SELECT * FROM tree WHERE lft BETWEEN 2 AND 11 OR lft BETWEEN 12 AND 17;
    

    And if we wanted to retrieve all of the ancestors of the Red, Beef and Pork nodes, we could do this:

    SELECT * FROM tree WHERE lft < 3 AND rght > 6 OR lft < 13 AND rght > 14 OR lft < 15 AND rght > 16;
    

    Now take a look at that last query again. Couldn't it be simplified and still accomplish the same result? Sure it could:

    SELECT * FROM tree WHERE lft < 3 AND rght > 6 OR lft < 15 AND rght > 14;
    

    The difference is that we've put the nodes into groups and then identified the highest lft value and the lowest rght value per group. A group is defined as any collection of nodes that share a tree_id and a parent_id. Any ancestors of these groups of nodes will have a lft value less than the highest lft value and a rght value greater than the lowest rght value.

    ~~For the descendants of a group of nodes, it is just the opposite:~~ (See the edit below, addressing the problem with this method.) Any descendants of a group of nodes will have a lft value greater than the lowest lft value and a rght value less than the highest rght value. For example, if we wanted to retrieve the descendants of Red, Yellow, and Meat:

    SELECT * FROM tree WHERE lft > 3 AND rght < 10 OR lft > 12 AND rght < 17;
    

    (Edit: 30 Sept. 2014) However, this method returns more nodes than is required, as pointed out by craigds in the comments below. I'm currently working on a method to fix this.

    Why?

    Both get_queryset_descendants and get_queryset_ancestors use a Q object in order to accomplish their job: retrieving either the ancestors or descendants of a queryset (i.e., group) of nodes. This Q object can become quite large and in some cases it can raise an OperationalError if there are too many SQL variables involved. For example, sqlite only allows a single query to have <1000 SQL variables; well, if you wanted to get the ancestors of a queryset that contains 400 distinct nodes, you're looking at a query that contains 1200 variables. Now we could discuss the various techniques involved in shrinking that queryset, but with sufficiently large sets of data, sometimes there just isn't a way to do it.

    That's where the aggregate kwarg comes into play. This kwarg tells get_queryset_ancestors and get_queryset_descendants to group nodes first by their tree_id then by their parent_id. Then, for each "group", it finds the the appropriate lft and rght values to ensure that there is only one Q object per group of nodes. To reuse the example above, if you had a queryset with 400 distinct nodes but 200 of them shared the same tree_id and parent_id and the other 200 shared a different tree_id/parent_id combination, you would have two groups, with a total of 6 SQL variables (tree_id, lft, rght variables for each group.) Not only does this make for faster queries, but it has the potential to avoid the scenario I mentioned earlier where too many SQL variables raises an OperationalError.

    Examples:

    models.py

    from django.db import models
    from mptt.models import TreeForeignKey, MPTTModel
    
    class Directory(MPTTModel):
        parent = TreeForeignKey(
            'self',
            null = True,
            blank = True,
            related_name = 'children')
    
        path = models.CharField(
            max_length = 255)
    
        def __unicode__(self):
            return self.path
    
    
    class File(models.Model):
        parent = models.ForeignKey(
            Directory,
            null = True,
            blank = True,
            related_name = 'files')
    
        path = models.CharField(
            max_length = 255)
    
        def __unicode__(self):
            return self.path
    

    Our dataset is a directory structure that matches the example tree in the above graphic:

    mkdir -p Food/Fruit/Red/Cherry
    mkdir -p Food/Fruit/Yellow/Banana
    mkdir -p Food/Meat/{Beef,Pork}
    

    Then:

    import os
    from myapp.filesanddirectories.models import *
    
    for root, directories, files in os.walk('/Food'):
        parent_dir, created = Directory.objects.get_or_create(path = root)
        for directory in directories:
            path = os.path.join(root, directory)
            print path
            object, created = Directory.objects.get_or_create(path = path, parent = parent_dir)
            if created:
                print("CREATED: %s" % path)
    

    Running in the python interpreter (with debugging output):

    >>> from myapp.filesanddirectories.models import *
    >>> from django.db.models import Q
    >>> from django.db import transaction
    >>> dirs = Directory.objects.filter(Q(path = '/Food/Fruit') | Q(path = '/Food/Meat'))
    >>> dirs
    [<Directory: /Food/Fruit>, <Directory: /Food/Meat>]
    >>> 
    >>> ### get_queryset_descendants ###
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_descendants(dirs)
    Finished in 0.000601
    Q Object: (OR: (AND: (u'lft__gt', 2), (u'tree_id', 1), (u'rght__lt', 11)), (AND: (u'lft__gt', 12), (u'tree_id', 1), (u'rght__lt', 17)))
    [<Directory: /Food/Fruit/Red>, <Directory: /Food/Fruit/Red/Cherry>, <Directory: /Food/Fruit/Yellow>, <Directory: /Food/Fruit/Yellow/Banana>, <Directory: /Food/Meat/Pork>, <Directory: /Food/Meat/Beef>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_descendants(dirs, aggregate=True)
    Finished in 0.000036
    Q Object: (AND: (u'lft__gt', 2), (u'tree_id', 1), (u'rght__lt', 17))
    [<Directory: /Food/Fruit/Red>, <Directory: /Food/Fruit/Red/Cherry>, <Directory: /Food/Fruit/Yellow>, <Directory: /Food/Fruit/Yellow/Banana>, <Directory: /Food/Meat/Pork>, <Directory: /Food/Meat/Beef>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_descendants(dirs, include_self=True)
    Finished in 0.000043
    Q Object: (OR: (AND: (u'lft__gt', 1), (u'tree_id', 1), (u'rght__lt', 12)), (AND: (u'lft__gt', 11), (u'tree_id', 1), (u'rght__lt', 18)))
    [<Directory: /Food/Fruit>, <Directory: /Food/Fruit/Red>, <Directory: /Food/Fruit/Red/Cherry>, <Directory: /Food/Fruit/Yellow>, <Directory: /Food/Fruit/Yellow/Banana>, <Directory: /Food/Meat>, <Directory: /Food/Meat/Pork>, <Directory: /Food/Meat/Beef>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_descendants(dirs, include_self=True, aggregate=True)
    Finished in 0.000027
    Q Object: (AND: (u'lft__gt', 1), (u'tree_id', 1), (u'rght__lt', 18))
    [<Directory: /Food/Fruit>, <Directory: /Food/Fruit/Red>, <Directory: /Food/Fruit/Red/Cherry>, <Directory: /Food/Fruit/Yellow>, <Directory: /Food/Fruit/Yellow/Banana>, <Directory: /Food/Meat>, <Directory: /Food/Meat/Pork>, <Directory: /Food/Meat/Beef>]
    >>> 
    >>> 
    >>> ### get_queryset_ancestors ###
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_ancestors(dirs)
    Finished in 0.000042
    Q Object: (OR: (AND: (u'rght__gt', 11), (u'lft__lt', 2), (u'tree_id', 1)), (AND: (u'rght__gt', 17), (u'lft__lt', 12), (u'tree_id', 1)))
    [<Directory: /Food>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_ancestors(dirs, aggregate=True)
    Finished in 0.000027
    Q Object: (AND: (u'rght__gt', 11), (u'lft__lt', 12), (u'tree_id', 1))
    [<Directory: /Food>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_ancestors(dirs, include_self=True)
    Finished in 0.000045
    Q Object: (OR: (AND: (u'rght__gt', 10), (u'lft__lt', 3), (u'tree_id', 1)), (AND: (u'rght__gt', 16), (u'lft__lt', 13), (u'tree_id', 1)))
    [<Directory: /Food>, <Directory: /Food/Fruit>, <Directory: /Food/Meat>]
    >>> 
    >>> transaction.commit()
    >>> Directory.objects.get_queryset_ancestors(dirs, include_self=True, aggregate=True)
    Finished in 0.000091
    Q Object: (AND: (u'rght__gt', 10), (u'lft__lt', 13), (u'tree_id', 1))
    [<Directory: /Food>, <Directory: /Food/Fruit>, <Directory: /Food/Meat>]
    >>> 
    

    Summary

    Please tear this to shreds. Seriously. I haven't been able to find any bugs with this implementation but that doesn't mean that they aren't there. Tests pass though so ... yay. :-)

    opened by musashiXXX 20
  • Defer update of mptt fields (left/right/tree/level) until a batch of changes have been made

    Defer update of mptt fields (left/right/tree/level) until a batch of changes have been made

    Originally GC 46

    I'm using django-mptt to manage the hierarchy of an ecommerce site with a lot of products.

    We regularly sync large batches of products from another systems to the web database and these syncs can include a lot of changes to the category tree.

    What would be good is if there was a way to add/update/delete the tree without modifying the mptt fields then to do all the mptt changes once at the end.

    Would the easiest way to just use the default manager to add new nodes, then to rebuild the tree using the custom method? It would be nice if there was a standard way of doing this.

    Enhancement 
    opened by django-mptt 20
  • [has patch] add_related_count() can accept related querysets, not related model.

    [has patch] add_related_count() can accept related querysets, not related model.

    Originally GC 38

    This makes it much more usable. I'll show why.

    Old fashion:

    Model.tree.add_related_count(Model.objects.all(), AnotherModel, 'rel_col', 'cnt', cumulative=True) makes this query:

    SELECT (SELECT COUNT(*) FROM another_model WHERE ( rel_col_id IN ( SELECT m2.id FROM model m2 WHERE m2.mptt_tree_id = model.mptt_tree_id AND m2.mptt_left BETWEEN model.mptt_left AND model.mptt_right ) )) AS cnt, col1, colN FROM model

    Good, but we cant change add more difficult subquery. My patch allows to use related querysets instead of related model (which being determined automatically).

    Model.tree.add_related_count(Model.objects.all(), AnotherModel.objects.all (), 'rel_col', 'cnt', cumulative=True) makes exactly the same query. But this:

    Model.tree.add_related_count(Model.objects.all(), AnotherModel.objects.filter(field=1).filter(field=2), 'rel_col', 'cnt', cumulative=True) makes this:

    SELECT (SELECT COUNT(*) FROM another_model WHERE field = 1 AND field = 2 AND ( field = 2 AND field = rel_col_id IN ( SELECT m2.id FROM model m2 WHERE m2.mptt_tree_id = model.mptt_tree_id AND m2.mptt_left BETWEEN model.mptt_left AND model.mptt_right ) )) AS cnt, col1, colN FROM model

    In my case: I have categories, tasks and users. With my patch I'm able to fill task counts for specified user in all categories :). Even more! Using non-documented "having" ability in django orm queries, I can select all categories which have >0 tasks for specified user. E.g.:

    qs = AnotherModel.objects.filter(field=1).filter(field=2), 'rel_col', 'cnt', cumulative=True) qs.query.having.append('%s > %s' % (connection.ops.quote_name('cnt'), 0))

    Which will have a result:

    SELECT (SELECT COUNT(*) FROM another_model WHERE field = 1 AND field = 2 AND ( field = 2 AND field = rel_col_id IN ( SELECT m2.id FROM model m2 WHERE m2.mptt_tree_id = model.mptt_tree_id AND m2.mptt_left BETWEEN model.mptt_left AND model.mptt_right ) )) AS cnt, col1, colN FROM model HAVING cnt > 0

    All of these examples are for cumulative queries. But also apply to non- cumulative queries as well. Woohooo! :)

    Enhancement 
    opened by django-mptt 20
  • Admin tree management

    Admin tree management

    Originally GC 33

    Attached is a patch that will allow a tree to be managed in the admin interface using the jQuery NestedSortableWidget (http://code.google.com/p/nestedsortables/wiki/NestedSortableWidgetDocumentation). I have shamelessly lifted some code from the Tusk CMS, credit goes to them for the idea (http://code.google.com/p/tusk-cms/). It's a little messy and hacky at the moment, but it should work.

    Some sample usage in admin.py:

    from django.contrib import admin from mptt.admin import MpttModelAdmin

    class CategoryAdmin(MpttModelAdmin): list_display = ('title',)

    admin.site.register(Category, CategoryAdmin)

    The files in mptt_media.tar.gz need to be put in your MEDIA_URL directory.

    opened by django-mptt 20
  • Make MPTTModel.tree the default manager

    Make MPTTModel.tree the default manager

    As far as I can tell there's no reason why the TreeManager is not the default manager. This confuses me and probably everyone else.

    For 0.5, I think .objects should refer to the same manager as .tree . It can be overridden if a subclass wants a different default manager.

    Enhancement 
    opened by craigds 18
  • Release a version compatible with Django 1.9

    Release a version compatible with Django 1.9

    The current master seems to work fine on 1.9 but the last released version does not. Seeing that Django 1.9 has been officially released, it would be nice to have a compatible release of django-mptt.

    opened by patrys 17
  • Django 1.8 support

    Django 1.8 support

    I am alpha testing Django 1.8

    Meta API is formalised in 1.8 and as a result, method get_fields_with_model is deprecated.

    That method is used here https://github.com/django-mptt/django-mptt/blob/6a41fd4384f44ff1d66c6cded4dcd37a8767b9a4/mptt/managers.py#L76

    Because of this, project which is on 1.7 is not able to to run on 1.8. Please refer to migration docs https://docs.djangoproject.com/en/1.8/ref/models/meta/#migrating-old-meta-api

    opened by chhantyal 17
  • Unique constraint failure when moving nodes

    Unique constraint failure when moving nodes

    Hi !

    I have a MPTT tree with an unique constraint on the parent and a "code" field. With such a setup, I get an IntegrityError when I reparent a child if there's already a child with the code, even if I change the code so that they don't conflict !

    This means I need to change the code, save, then reparent, and save again. This also means I'll get headaches if the new code is conflicting in the initial parent.

    I'm surprised to find a bug with a setup that seems extremely common (wanting an unique property per parent). Did I miss something ?

    Anyway, thanks a lot for the tool !

    Here's the model I tested with :

    class TestModel( MPTTModel ):
        class Meta:
            unique_together = (('parent','code',),)
        parent = TreeForeignKey('self', null=True)
        code = models.CharField(max_length=10)
    

    And here's the steps to reproduce

    from MyApp.models import TestModel
    a = TestModel.objects.create(code='a',parent=None)
    b = TestModel.objects.create(code='b',parent=None)
    a1 = TestModel.objects.create(code='1',parent=a)
    b1 = TestModel.objects.create(code='1',parent=b)
    
    b1.code = '2'
    b1.parent = a
    b1.save() # THIS THROWS IntegrityError: UNIQUE constraint failed
    
    opened by olivierdalang 16
  • Removing mppt.register and putting metaclass is not funny ;/

    Removing mppt.register and putting metaclass is not funny ;/

    There is a lot of projects (including my code) using own metaclasses and now I could not use mppt whit my models. mptt.register was the best way to integrate models with mptt.

    For example: Now there is no way to use mppt and django-transmeta. Sux!

    I'm back to 0.3 version.

    Defect 
    opened by ghost 16
  • Update mptt_change_list.html to include {% change_list_object_tools %}

    Update mptt_change_list.html to include {% change_list_object_tools %}

    It seems that the admin template admin/mptt-change-list.html currently does not have the {% change_list_object_tools %} tag present, which causes the Add button to not be rendered. This change ensures that the Add button is rendered even when the django admin has some kind of skin added to it (eg. jazzmin).

    https://stackoverflow.com/questions/68722249/django-jazzmin-add-button-disappeared-after-adding-mptt-admin/69230357#69230357

    opened by paramkpr 1
  • Problem occured when integrating with django-parler

    Problem occured when integrating with django-parler

    The alternative answer was givin here, but you can improve that in the new version:

    https://stackoverflow.com/questions/68722249/django-jazzmin-add-button-disappeared-after-adding-mptt-admin/

    opened by uktamjon-komilov 0
  • How do I use order_by?

    How do I use order_by?

    Good afternoon. I want to sort the tree, but I understand that from some level the elements start to be displayed in the wrong level

    obj = Model.objects.filter(level__lte=10).annotate(
        children_count=Count('children'),
        descendants_count=Floor((F('rght') - F('lft') - 1) / 2),
        comments_count=Count('comments'),
    ).order_by('tree_id', 'level', 'children_count', '-slug')
    

    Tell me, can you somehow solve the sorting problem?

    opened by maksam07 8
  • TypeError: unsupported operand type(s) for +=: 'set' and 'tuple

    TypeError: unsupported operand type(s) for +=: 'set' and 'tuple

    When upgrading from Django-mptt 0.8.6 to 0.11.0 or later version, Django migrations fail with unsupported type error: TypeError: unsupported operand type(s) for +=: 'set' and 'tuple' The error is traced to: https://github.com/django-mptt/django-mptt/blob/7a6a54c6d2572a45ea63bd639c25507108fff3e6/mptt/models.py#L377

    The code is expecting a tuple so when a set is passed, it throws this error. Is it possible to make the code more robust to handle both sets and tuples?

    We came across this error when upgrading from Django 1.11 to 2.2.24 which required mptt upgrade from 0.86 to 0.11 due to template loader errors. This error did not occur before upgrading.

    Failing migrations stack trace:

    (20211018-eregs-env) macadmins-mbp-5:fec-eregs pkasireddy$ python manage.py migrate
    System check identified some issues:
    
    WARNINGS:
    regcore.Diff: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.
    	HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
    regcore.Layer: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.
    	HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
    regcore.NoticeCFRPart: (models.W042) Auto-created primary key used when not defining a primary key type, by default 'django.db.models.AutoField'.
    	HINT: Configure the DEFAULT_AUTO_FIELD setting or the AppConfig.default_auto_field attribute to point to a subclass of AutoField, e.g. 'django.db.models.BigAutoField'.
    Operations to perform:
     Apply all migrations: auth, contenttypes, regcore, regulations, sessions
    Running migrations:
     Applying contenttypes.0001_initial... OK
     Applying contenttypes.0002_remove_content_type_name... OK
     Applying auth.0001_initial... OK
     Applying auth.0002_alter_permission_name_max_length... OK
     Applying auth.0003_alter_user_email_max_length... OK
     Applying auth.0004_alter_user_username_opts... OK
     Applying auth.0005_alter_user_last_login_null... OK
     Applying auth.0006_require_contenttypes_0002... OK
     Applying auth.0007_alter_validators_add_error_messages... OK
     Applying auth.0008_alter_user_username_max_length... OK
     Applying auth.0009_alter_user_last_name_max_length... OK
     Applying auth.0010_alter_group_name_max_length... OK
     Applying auth.0011_update_proxy_permissions... OK
     Applying auth.0012_alter_user_first_name_max_length... OK
     Applying regcore.0001_initial... OK
     Applying regcore.0002_mptt_add_fields... OK
     Applying regcore.0003_mptt_copy_children...Traceback (most recent call last):
     File "manage.py", line 10, in <module>
      execute_from_command_line(sys.argv)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/__init__.py", line 419, in execute_from_command_line
      utility.execute()
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/__init__.py", line 413, in execute
      self.fetch_command(subcommand).run_from_argv(self.argv)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/base.py", line 354, in run_from_argv
      self.execute(*args, **cmd_options)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/base.py", line 398, in execute
      output = self.handle(*args, **options)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/base.py", line 89, in wrapped
      res = handle_func(*args, **kwargs)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/core/management/commands/migrate.py", line 246, in handle
      fake_initial=fake_initial,
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/db/migrations/executor.py", line 117, in migrate
      state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/db/migrations/executor.py", line 147, in _migrate_all_forwards
      state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/db/migrations/executor.py", line 227, in apply_migration
      state = migration.apply(state, schema_editor)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/db/migrations/migration.py", line 126, in apply
      operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/django/db/migrations/operations/special.py", line 190, in database_forwards
      self.code(from_state.apps, schema_editor)
     File "/Users/pkasireddy/.pyenv/versions/3.7.10/envs/20211018-eregs-env/src/regcore/regcore/migrations/0003_mptt_copy_children.py", line 17, in rebuild
      mptt.register(Regulation)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/mptt/__init__.py", line 13, in register
      return MPTTModelBase.register(*args, **kwargs)
     File "/Users/pkasireddy/.pyenv/versions/20211018-eregs-env/lib/python3.7/site-packages/mptt/models.py", line 352, in register
      cls._meta.index_together += (index_together,)
    TypeError: unsupported operand type(s) for +=: 'set' and 'tuple
    
    
    
    
    opened by johnnyporkchops 7
  • Ancestors and descendants through proxy model returns as parent model objects instead proxy model objects.

    Ancestors and descendants through proxy model returns as parent model objects instead proxy model objects.

    class Car(MPTTModel):
        pass
    
    class BMW(Car):
        class Meta:
            proxy = True
    
        def bmw_method(self):        
            pass
    
    class Audi(Car):
        class Meta:
            proxy = True
    
        def audi_method(self):        
            pass
    
    bmw = BMW.objects.get(pk=1)
    bmw_descendants = bmw.get_descendants()
    

    bmw_descendants queryset of Car model objects, I think it should return BMW model objects.

    • custom manager with default name objects on each proxy model not working.
    • default_manager_name with custom manager with custom name on each proxy model not working.
    opened by maxovsy 2
Releases(0.9.0)
Django app for building dashboards using raw SQL queries

django-sql-dashboard Django app for building dashboards using raw SQL queries Brings a useful subset of Datasette to Django. Currently only works with

Simon Willison 383 Jan 06, 2023
Inject an ID into every log message from a Django request. ASGI compatible, integrates with Sentry, and works with Celery

Django GUID Now with ASGI support! Django GUID attaches a unique correlation ID/request ID to all your log outputs for every request. In other words,

snok 300 Dec 29, 2022
Docker django app

Hmmmmm... What I should write here? Maybe "Hello World". Hello World Build Docker compose: sudo docker-compose build Run Docker compose: sudo docker-

Andrew 0 Nov 10, 2022
Returns unicode slugs

Python Slugify A Python slugify application that handles unicode. Overview Best attempt to create slugs from unicode strings while keeping it DRY. Not

Val Neekman (AvidCoder) 1.3k Dec 23, 2022
Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards and optional settings files.

Organize Django settings into multiple files and directories. Easily override and modify settings. Use wildcards in settings file paths and mark setti

Nikita Sobolev 940 Jan 03, 2023
Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

tzangms 557 Oct 19, 2022
No effort, no worry, maximum performance.

Django Cachalot Caches your Django ORM queries and automatically invalidates them. Documentation: http://django-cachalot.readthedocs.io Table of Conte

NoriPyt 980 Jan 06, 2023
Run Django tests with testcontainers.

django-rdtwt (Run Django Tests With Testcontainers) This targets users who wish to forget setting up a database for tests. There's no manually startin

2 Jan 09, 2022
Django And React Notes App

Django & React Notes App Cloning the repository -- Clone the repository using the command below : git clone https://github.com/divanov11/Django-React

Dennis Ivy 136 Dec 27, 2022
Packs a bunch of smaller CSS files together from 1 folder.

Packs a bunch of smaller CSS files together from 1 folder.

1 Dec 09, 2021
Money fields for Django forms and models.

django-money A little Django app that uses py-moneyed to add support for Money fields in your models and forms. Django versions supported: 1.11, 2.1,

1.4k Jan 06, 2023
A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for quickly creating new images from the one assigned to the field.

django-versatileimagefield A drop-in replacement for django's ImageField that provides a flexible, intuitive and easily-extensible interface for creat

Jonathan Ellenberger 490 Dec 13, 2022
Django datatables with htmx.

Django datatables with htmx.

Regis Santos 7 Oct 23, 2022
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
RedisTimeSeries python client

redistimeseries-py Deprecation notice As of redis-py 4.0.0 this library is deprecated. It's features have been merged into redis-py. Please either ins

98 Dec 08, 2022
:couple: Multi-user accounts for Django projects

django-organizations Summary Groups and multi-user account management Author Ben Lopatin (http://benlopatin.com / https://wellfire.co) Status Separate

Ben Lopatin 1.1k Jan 01, 2023
A reusable Django app that configures your project for deployment

django-simple-deploy This app gives you a management command that configures your project for an initial deployment. It targets Heroku at the moment,

Eric Matthes 205 Dec 26, 2022
A starter template for building a backend with Django and django-rest-framework using docker with PostgreSQL as the primary DB.

Django-Rest-Template! This is a basic starter template for a backend project with Django as the server and PostgreSQL as the database. About the templ

Akshat Sharma 11 Dec 06, 2022
django CMS Association 1.6k Jan 06, 2023
Sistema de tratamento e análise de grandes volumes de dados através de técnicas de Data Science

Sistema de tratamento e análise de grandes volumes de dados através de técnicas de data science Todos os scripts, gráficos e relatórios de todas as at

Arthur Quintanilha Neto 1 Sep 05, 2022