Ordering mptt tree using a field - python

This is the original category model:
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class MPTTMeta:
order_insertion_by = ['name']
Then I needed to order the category, so I altered it like the following:
class Category(MPTTModel):
name = models.CharField(max_length=50, unique=True)
order = models.SmallIntegerField() <<<<<<<<<
parent = TreeForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self):
return self.name
class MPTTMeta:
order_insertion_by = ['order'] <<<<<<<<<
And I changed the Django admin declaration from:
admin.site.register(Category, MPTTModelAdmin)
To:
class CategoryAdmin(MPTTModelAdmin):
list_display = ('name', 'order')
list_editable = ('order',)
admin.site.register(Category, CategoryAdmin)
Then everything fall apart after making a few edits from the admin control panel. I can't describe exactly what happened but it seems the lft, rght, level and parent_id where messed up by these changes.
Am I using order_insertion_by in the wrong context? Is it for something else? I tried to search the docs but didn't get a useful answer.

I faced this problem. The problem is not in the package django-mptt, and in the framework Django, more precisely in the admin. Perhaps this is due to several administrators working simultaneously. While only one solution - to abandon the list_editable in admin class or write a script with the same field order for Ajax.
In order to restore the tree, use rebuld method: Category.tree.rebuild()

Related

Django form: reference fields from foreign key

I'm making a task tracker webapp (the full source code is also available) and I have a database structure where each task has a title, a description, and some number of instances, that can each be marked incomplete/incomplete:
class Task(models.Model):
title = OneLineTextField()
description = models.TextField(blank=True)
class TaskInstance(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE)
is_complete = models.BooleanField()
The task and the instances can be shared separately, although access to the instance should imply read access to the task. This is intended for classroom situations, where the teacher creates a task and assigns it to their students.
class TaskPermission(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE, related_name='permissions')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='task_permissions_granted')
shared_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, related_name='task_permissions_granting')
can_edit = models.BooleanField(default=False)
class Meta:
unique_together = 'task', 'user', 'shared_by',
class TaskInstancePermission(models.Model):
task_instance = models.ForeignKey(TaskInstance, on_delete=models.CASCADE, related_name='permissions')
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='task_instance_permissions_granted')
shared_by = models.ForeignKey(User, on_delete=models.PROTECT, null=True, related_name='task_instance_permissions_granting')
can_edit = models.BooleanField(default=False)
class Meta:
unique_together = 'task_instance', 'user', 'shared_by',
My question is how to create a form for TaskInstances with fields for its is_complete, as well as its Task's title and description. Would something like this work? Or would I need to implement my own save and clean methods?
class TaskForm(ModelForm):
class Meta:
model = TaskInstance
fields = ('is_complete', 'task__title', 'task__description')
I think inlineformset_factory is what I'm looking for!
Actually, it does not seem to be useful: it is for multiple forms of the same type, not different types...

Django Forms query

I have created a app using the following Model
models.py
class Vendor(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Model(models.Model):
name = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.name
class Request(models.Model):
job_reference = models.CharField(max_length=100, unique=True, blank=False)
def __str__(self):
return self.job_reference
class Device(models.Model):
Vendor = models.ForeignKey('Vendor')
Model = models.ForeignKey('Model')
device_id = models.CharField(max_length=255, unique=True, blank=True)
is_encrypted = models.BooleanField()
is_medical = models.BooleanField()
request_job_reference = models.ForeignKey('Request')
submitted = models.DateTimeField(default=timezone.now)
When i go to the admin page I can add new devices which displayed each of the fields and the "Vendor" and "Model" allows me to either select an existing entry or has a plus icon to add a new entry (which is great)
Django_Admin_form
When i create a form for my app
forms.py
from django import forms
from . models import Device
class AddDevice(forms.ModelForm):
class Meta:
model = Device
fields = ('Vendor', 'Model', 'device_id', 'is_encrypted', 'is_medical', 'submitted')
The form on my webpage display ok however there is no option to insert a new entry to "Vendor" or "Model".
Webpage Form
I have looked on other posts on here as users have had the same issue and it's been suggested to use "ModelChoiceField" but unfortunately it still doesn't make any sense to me. Either i'm completely missing something or I have setup my models in a way which is making things harder for myself.
Can anyone explain how I can go about doing this?

Using a class as a part of another class in django models

Assume I am writing an app to change configurations in a machine. I have 3 created tables as below. Machine configuration shows the current state of configurations for our machine. Users can create their tickets and request for changes of the configurations. RequestDetails will be the table to keep the proposed cofigurations plus some extra info such as the name of the requestor, date etc.
These classes are just a simple examples, in the real model I would have nearly 600+ fields=configuration presented in class MachineConfiguration. I should have EXACTLY THE SAME fields in RequestDetails class too. I was wondering there is a way NOT TO REPEAT MYSELF when defining class RequestDetails when it comes to all the fields that exist in MachineConfiguration model?
I want to write it in a way that if I changed anything in MachineConfiguration table, the same change would apply to RequestDetails table too.
Thanks in advance for the help.
class RequestTicket(models.Model):
subject=models.CharField(max_length=50, null=False, blank=False)
description=models.TextField(null=False, blank=True)
class MachineConfiguration(models.Model):
field_1 = models.CharField(null=False,blank=True)
field_2 = models.CharField(null=False, blank=True)
field_3 = models.CharField(null=False, blank=True)
class RequestDetails(models.Model):
tracking_number=models.ForeignKey('RequestTicket')
field_A=models.DateField(null=True, blank=False)
field_B=models.TextField(null=True, blank=False)
field_1 = models.CharField(null=False, blank=True)
field_2 = models.CharField(null=False, blank=True)
field_3 = models.CharField(null=False, blank=True)
Yes you can create the base class and inherit that class in another class like,
class BaseModel(models.Model):
field1 = models.CharField()
field2 = models.CharField()
class Meta:
abstract = True
And inherit this class in another model to get those same field,
# Now if you change any field in BaseModel, it will reflect in both the models
class MachineConfiguration(BaseModel):
pass
class RequestDetails(BaseModel):
field3 = models.CharField()

How can I create Django ModelForm for an abstract Model?

I have an abstract model that all my other models inherit from, it looks like this.
class SupremeModel(models.Model):
creator = models.ForeignKey(User, related_name="%(class)s_creator")
created = models.DateTimeField(null=True, blank=True)
deleted = models.BooleanField(default=False)
modified = models.DateTimeField(null=True,blank=True)
class Meta:
abstract = True
I then have a bunch of other models that inherit from this model, with something along these lines...
class ExampleModel(SupremeModel):
name = models.TextField(null=False, blank=False)
description = models.TextField(null=False, blank=False)
class AnotherModel(SupremeModel):
title = models.TextField(null=False, blank=False)
location = models.TextField(null=False, blank=False)
I want to create a Django model form for nearly all of my custom models that look similar to ExampleModel, but I always want the fields in SupremeModel to be excluded in the form...
How can I create a ModelForm that can be used to inherit the exclude parameters that will hide creator,created,deleted, and modified but show all of the other fields (in this case name and description or title and location).
you may try this
class ExcludedModelForm(ModelForm):
class Meta:
exclude = ['creator', 'created', 'deleted', 'modified']
class ExampleModelForm(ExcludedModelForm):
class Meta(ExcludedModelForm.Meta):
model = ExampleModel

How can I use the automatically created implicit through model class in Django in a ForeignKey field?

In Django I have the following models.
In the Supervisor model I have a many-to-many field without an explicitly defined through table. In the ForeignKey field of the Topic model I would like to refer to the automatically created intermediate model (created by the many-to-many field in the Supervisor model), but I don't know what is the name of the intermediate model (therefore I wrote '???' there, instead of the name).
Django documentation tells that "If you don’t specify an explicit through model, there is still an implicit through model class you can use to directly access the table created to hold the association."
How can I use the automatically created implicit through model class in Django in a ForeignKey field?
import re
from django.db import models
class TopicGroup(models.Model):
title = models.CharField(max_length=500, unique='True')
def __unicode__(self):
return re.sub(r'^(.{75}).*$', '\g<1>...', self.title)
class Meta:
ordering = ['title']
class Supervisor(models.Model):
name = models.CharField(max_length=100)
neptun_code = models.CharField(max_length=6)
max_student = models.IntegerField()
topicgroups = models.ManyToManyField(TopicGroup, blank=True, null=True)
def __unicode__(self):
return u'%s (%s)' % (self.name, self.neptun_code)
class Meta:
ordering = ['name']
unique_together = ('name', 'neptun_code')
class Topic(models.Model):
title = models.CharField(max_length=500, unique='True')
foreign_lang_requirements = models.CharField(max_length=500, blank=True)
note = models.CharField(max_length=500, blank=True)
supervisor_topicgroup = models.ForeignKey(???, blank=True, null=True)
def __unicode__(self):
return u'%s --- %s' % (self.supervisor_topicgroup, re.sub(r'^(.{75}).*$', '\g<1>...', self.title))
class Meta:
ordering = ['supervisor_topicgroup', 'title']
It's just called through - so in your case, Supervisor.topicgroups.through.
Although I think that if you're going to be referring to it explicitly in your Topic model, you might as well declare it directly as a model.

Categories

Resources