I'm having an issue that I seriously can't wrap my head around.
I am using Django MPTT models and evrerything seems to be working fine (i.e. I can run the migrations and insert data in the database), but for some reason the
TreeForeignKey
table and the
TreeManyToManyField
table are not linking in the database.
Here are the models in question...
from mptt.models import MPTTModel, TreeForeignKey, TreeManyToManyField
class Category(MPTTModel):
name = models.CharField(
max_length=100,
verbose_name=_('category name'),
help_text=_('format: required, max=100'),
)
slug = models.SlugField(
max_length=150,
verbose_name=_('category safe URL'),
help_text=_('format: required, letters, numbers, underscore or hyphons'),
)
is_active = models.BooleanField(default=True)
parent = TreeForeignKey(
'self',
on_delete=models.PROTECT,
related_name='children',
null=True,
blank=True,
)
class MPTTMeta:
order_insertion_by = ['name']
class Meta:
verbose_name=_('product category')
verbose_name_plural=_('product categories')
def __str__(self):
return self.name
class Product(models.Model):
web_id = models.CharField(
unique=True,
max_length=50,
verbose_name=_('product website ID'),
)
slug = models.SlugField(
max_length=255,
verbose_name=_('product safe URL'),
help_text=_('format: required, letters, numbers, underscore or hyphons'),
)
name = models.CharField(max_length=150)
description = models.TextField(help_text='Required')
category = TreeManyToManyField(Category)
is_active = models.BooleanField(
default=False,
verbose_name=_('product visibility'),
)
created_at = models.DateTimeField(
editable=False,
auto_now_add=True,
help_text=_('format: Y-m-d H:M:S'),
)
updated_at = models.DateTimeField(auto_now=True, help_text=_('format: Y-m-d H:M:S'))
def __str__(self):
return self.name
I'm following the documentation verbatum, and really I have no idea why this is not working...
If anyone has any idea please let me know
Related
I want to sort Groups with their 'is_favorite' boolean field from model GroupUser. I have two models GroupUser where there is a foreign key to Group model, now when I query Group.objects.filter(is_active=True).order_by('groupuser__group_id__is_favorite')
I get groups multiple times. I tried to user distict() on final queryset still no luck. Pls suggest any other way or possible solution. TIA.
class Group(models.Model):
group_name = models.CharField(
max_length=250)
context_type = models.ForeignKey(
"contenttypes.ContentType",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="content_type")
context = models.IntegerField(
blank=True,
null=True)
privacy_type = models.ForeignKey(
"commans.PrivacyType",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="group_privacy_id")
is_active = models.BooleanField(
default=True,
help_text="Is Group Active")
class GroupUser(models.Model):
group = models.ForeignKey(
"Group",
on_delete=models.DO_NOTHING,
blank=True,
null=True,
related_name="groupuser_group_id")
user=models.ForeignKey(
"auth_module.User",
on_delete=models.DO_NOTHING,
blank=True,
null=True)
is_favorite = models.BooleanField(
default=False,
blank=True,
null=True)
```
We can use an annotation to count the number of favourites each Group has. Then we can use this annotation to order by
from django.db.models import Sum
Group.objects.filter(
is_active=True
).annotate(
total_favorites=Sum('groupuser_group_id__is_favorite')
).order_by(
'-total_favorites'
)
I want to make a filter on a nested Model with the Django reverse relation. Below is the sample models I have :
class ProcessVersion(TimeStampedModel):
tag = models.CharField(_('Tag Name'), max_length=48)
status = FSMField(
_('Status'), max_length=12, choices=VERSION_STATUS_CHOICES,
default=VERSION_STATUS_IN_EDITION)
class Step(models.Model):
version = models.ForeignKey(
ProcessVersion, verbose_name=_('Process Version'),
on_delete=models.CASCADE, related_name='steps', blank=True,
null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=32)
class Block(models.Model):
step = models.ForeignKey(
Step, verbose_name=_('Loan Process Step'), on_delete=models.CASCADE,
related_name='blocks', blank=True, null=True)
is_active = models.BooleanField(
_('Is active'), default=False)
title = models.CharField(_('Title'), max_length=128, blank=True)
The first scenario was accessing the Step through it's related name and it worked :
process_version = ProcessVersion.objects.get(id=process_version_id)
steps = process_version.steps.get(id=param_id)
meaning that I passed through ProcessVersion to get the Step.
Now, my question is what if I want to get the Block but passing through ProcessVersion with it's id , how can I query that ?
I am trying to create a custom Django Admin Site for new staff members that lets a staff member edit their User first_name/last_name + get presented a list of multiple choice questions with radio select for the answer choices. The questions need to be a predefined queryset (e.g. last 5 multiple choice questions by date_created), whether a M2M entries exists already or not.
models.py
class User(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
first_name = models.CharField(
max_length=100,
blank=True,
null=True,
default=None,
)
last_name = models.CharField(
max_length=100,
blank=True,
null=True,
default=None,
)
class Questions(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
question_text = models.CharField(
max_length=160,
blank=True,
null=True,
default=None,
)
date_created = models.DateTimeField(
auto_now_add=True
)
users = models.ManyToManyField(
Users,
through=Questions2Users,
through_fields=('questions', 'users')
)
class AnswerChoices(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
)
choices_text = models.CharField(
max_length=160,
blank=True,
null=True,
default=None,
)
questions = models.ForeignKey(
Questions,
related_name='questions',
on_delete=models.CASCADE,
)
class Questions2Users(models.Model):
questions = models.ForeignKey(
Questions,
on_delete=models.CASCADE
)
users = models.ForeignKey(
Users,
null=True,
blank=True,
on_delete=models.CASCADE,
)
answerchoices = models.ForeignKey(
AnswerChoices,
on_delete=models.CASCADE
)
admin.py
from django.contrib import admin
from .models import (
User,
Questions,
Answers,
Questions2Users,
)
class Questions2UsersInline(admin.TabularInline):
model = Questions2Users
class UserAdminSite(admin.ModelAdmin):
class Meta:
model = User
inlines = [
Questions2UsersInline
]
admin.site.register(User, UserAdminSite)
I have identified it as a user model admin page with an inline for the M2M model. How would I display the questions queryset all at once with question_text and choice_text?
I have the following models:
class Address(models.Model):
address1 = models.CharField(max_length=150, null=True)
address2 = models.CharField(max_length=150, null=True, blank=True)
city = models.CharField(max_length=50, null=True)
state_province = models.CharField(max_length=50, null=True)
zipcode = models.CharField(max_length=10, null=True)
country = models.CharField(max_length=3, default='USA', null=False)
created_at = models.DateTimeField(db_index=True, auto_now_add=True)
updated_at = models.DateTimeField(db_index=True, auto_now=True)
class Meta:
db_table = 'addresses'
and this one.....
class User(models.Model, AbstractBaseUser, PermissionsMixin):
email = models.EmailField(db_index=True, max_length=150, unique=True,
null=False)
first_name = models.CharField(max_length=45, null=False)
last_name = models.CharField(max_length=45, null=False)
mobile_phone = models.CharField(max_length=12, null=True)
profile_image = models.CharField(max_length=150, null=True)
is_staff = models.BooleanField(db_index=True, null=False, default=False)
is_active = models.BooleanField(
_('active'),
default=True,
db_index=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
addresses = models.ManyToManyField(Address),
USERNAME_FIELD = 'email'
objects = MyCustomUserManager()
def __str__(self):
return self.email
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
class Meta:
db_table = 'users'
My first mystery is that by migrating the models, there is no "addresses" field in the users table, nor a pivot table in the database to keep the multiple relationships. How are ManyToMany payloads kept??
Secondly, my goal is to have multiple addresses for Users. I want Users to have multiple "Addresses" (and not each address having one User) because other models can have addresses too. I don't want the Address model to have 12 different "owner" fields with with ForeignKeys.
So. I try this:
from myApp.models import User
from myApp.models import Address
user = User(email="test#test.com", first_name="john", last_name="doe", mobile_phone="444")
# the model permits partial address fields, don't worry about that.
address = Address(city="New York", zipcode="10014")
Now I try to add the address to the user.addresses and I'm getting an error.
user.addresses.add(address)
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-5-0337af6b1cd4> in <module>()
----> 1 user.addresses.add(address)
AttributeError: 'tuple' object has no attribute 'add'
Help?
You have a superfluous comma after the definition of the many-to-many field, which turns it into a tuple. When you've removed this, you'll find both that the migrations will create your intermediary table, and that user.addresses.add() will work.
I need some help at designing a model and widget for a custom-sorted M2M relationship. The typical application scenario would be books and authors. In particular, when the order of authors in a book does matter.
The current version of my Publication model is:
class Publication(models.Model):
"""
A scientific publication.
"""
class Meta:
verbose_name = _('Publication')
verbose_name_plural = _('Publications')
ordering = ['year',]
nickname = models.CharField(
max_length=16,
help_text=_(
'A mnemonic name that "idenfies" this publication.'\
' E.g., concept_drift. (lowcase letters and dashes only)'),
validators=[RegexValidator(regex=r'^[a-z]+(_[a-z]+)*$')])
title = models.CharField(
_('Title'),
max_length=1024)
year = models.CharField(
max_length=4,
choices=YEARS,
help_text=_('Year of publication'),
db_index=True)
month = models.PositiveSmallIntegerField(
choices=MONTHS,
db_index=True,
null=True,
blank=True)
authors = models.ManyToManyField(
Person,
related_name='publications',
blank=True,
null=True)
attachment = FileBrowseField(
_('Attachment'),
max_length=256,
format='File',
blank=True,
null=True)
notes = models.CharField(
_('Notes'),
max_length=512,
help_text=_('Notes, e.g., about the conference or the journal.'),
blank=True,
null=True)
bibtex = models.TextField(
verbose_name=_('BibTeX Entry'),
help_text=_('At this moment, the BibTeX is not parsed for content.'),
blank=True,
null=True)
abstract = models.TextField(
_('Abstract'),
blank=True,
null=True)
fulltext = FileBrowseField(
_('Fulltext'),
max_length=256,
format='Document',
blank=True,
null=True)
date_updated = models.DateField(
_('Last updated on'),
auto_now=True,
db_index=True)
citation_key = models.SlugField(
max_length=512,
editable=False,
db_index=True)
#models.permalink
def get_absolute_url(self):
return ('academic_publishing_publication', (), { 'object_id': self.id })
def __unicode__(self):
return u'%s %s' % (
self.title,
self.year)
and authors are of People class:
class Person(models.Model):
"""
A person in a research lab.
"""
class Meta:
verbose_name = _('Person')
verbose_name_plural = _('People')
ordering = [
'rank',
'last_name',
'first_name', ]
affiliation = models.ManyToManyField(
Organization,
blank=True,
null=True,
related_name='people')
public = models.BooleanField(
verbose_name=_('Public?'),
help_text=_('Toggle visibility on public pages.'),
default=False)
current = models.BooleanField(
help_text=_('Is he/she still in the group?'),
default=True)
rank = models.ForeignKey(
Rank,
verbose_name=_('Academic Rank'),
related_name='people',
blank=True,
null=True)
first_name = models.CharField(
_('First Name'),
max_length=64)
mid_name = models.CharField(
blank=True,
null=True,
max_length=64)
last_name = models.CharField(
_('Last Name'),
max_length=64)
e_mail = models.EmailField(
_('E-mail'),
blank=True,
null=True)
web_page = models.URLField(
_('Web page'),
blank=True,
null=True)
description = models.TextField(
_('Description'),
blank=True,
null=True)
picture = FileBrowseField(
_('Profile picture'),
max_length=200,
format='Image',
blank=True,
null=True)
#models.permalink
def get_absolute_url(self):
return ('academic_people_person_detail', (), {'object_id': self.pk})
def __unicode__(self):
return u'%s' % self.name
def _get_name(self):
return u'%s %s' % (self.first_name, self.last_name)
name = property(_get_name)
I have two possibilities for storing the order of authors for each publication:
1. Explicit: make a AuthorForPublication model
class AuthorForPublication(models.Model):
author = ForeignKey(Person)
order = SmallPositiveInteger()
publication = ForeignKey(Publication)
but then a question arise: is it feasible to make an easy to use admin widget into Publication?
2. Workaround: create an authors_order field in Publication that takes a list of pks with a widget that lets the user re-order the authors. But this sounds a bit tricky.
Other alternatives certainly exist and are suggestions are appreciated.
I'd go for the first option. The second seems like a lot of work for very little (if any) gain.
When I need to have some explicit ordering, I always use a 'weight' column in the database.