MultiSelect in django no alloiwng multiple choices - python

I have an option for the user to select times, (half hours of the day), they can select as many as they like, and there are no constraints so (00:00, 01:00, 01:30) would be ok. But I can't get that to work as a field, I always get (is not in the available choices, as the specific combination will not be in their unless I enumerate all, but even with that I've struggled. Current files:
forms.py
from django import forms
from .models import InputData
class InputForm(forms.ModelForm):
class Meta:
model = InputData
fields = ('periods')
widgets = {
'periods': forms.MultipleSelect(attrs={'class': 'form-control','size': 48}),
models.py
times_list = ['00:00', '00:30','01:00','01:30','02:00']
periods_choices = list(choices(times_list,times_list))
class InputData(models.Model):
periods = models.CharField("Available periods:",
max_length=96,
choices=periods_choices,
blank=False,
default='all')
I've tried enumerating all the possibilities with itertools.combinations but I can't get the output to work as a set off choices.

Related

Django - Can I add a calculated field that only exists for a particular sub-set or occurences of my model?

Imagine that you have a model with some date-time fields that can be categorized depending on the date. You make an annotation for the model with different cases that assign a different 'status' depending on the calculation for the date-time fields:
#Models.py
class Status(models.TextChoices):
status_1 = 'status_1'
status_2 = 'status_2'
status_3 = 'status_3'
special_status = 'special_status'
class MyModel(models.Model):
important_date_1 = models.DateField(null=True)
important_date_2 = models.DateField(null=True)
calculated_status = models.CharField(max_length=32, choices=Status.choices, default=None, null=True, blank=False,)
objects = MyModelCustomManager()
And the manager with which to do the calculation as annotations:
# managers.py
class MyModelCustomManager(models.Manager):
def get_queryset(self):
queryset = super().get_queryset().annotate(**{
'status': Case(
When(**{'important_date_1' is foo, 'then':
Value(Status.status_1)}),
When(**{'important_date_2' is fii, 'then':
Value(Status.status_2)}),
When(**{'important_date_1' is foo AND 'importante_date_2' is whatever, 'then':
Value(Status.status_3)}),
# And so on and so on
)
}
)
return queryset
Now, here's where it gets tricky. Only one of these sub-sets of occurrences on the model requires an ADDITIONAL CALCULATED FIELD that literally only exists for it, that looks something like this:
special_calculated_field = F('important_date_1') - F('importante_date_2') #Only for special_status
So, basically I want to make a calculated field with the condition that the model instance must belong to this specific status. I don't want to make it an annotation, because other instances of the model would always have this value set to Null or empty if it were a field or annotation and I feel like it would be a waste of a row in the database.
Is there way, for example to do this kind of query:
>>> my_model_instance = MyModel.objects.filter(status='special_status')
>>> my_model_instance.special_calculated_field
Thanks a lot in advance if anyone can chime in with some help.

How to fetch data from another app Django

I'm creating a quiz project using Django with MongoEngine. Multiple Choice Questions and quiz are two separated apps. I want to fetch multiple choice in quiz based on m_id (unique number for each multiple choice). I'm a beginner and need a little help. How can i achieve thisMCQS Model
from django_mongoengine import Document, EmbeddedDocument, fields
class multichoice(Document):
m_id = fields.IntField(min_value=1, verbose_name='MCQ Id')
m_title = fields.StringField(primary_key=True, max_length=255, verbose_name='Title')
m_question = fields.StringField(verbose_name='Question')
m_alternatives = fields.ListField(fields.StringField(),verbose_name='Alternatives')
def __str__(self):
return self.m_title
Quiz Model
from django_mongoengine import Document, EmbeddedDocument, fields
from mcqs.models import *
class quiz(Document):
q_id = fields.IntField(min_value=1, verbose_name='Quiz ID')
q_title = fields.StringField(primary_key=True, max_length=255, verbose_name='Title')
q_s_description = fields.StringField(max_length=255, verbose_name='Description')
q_questions = fields.ListField(fields.IntField(), verbose_name='Question Numbers', blank=True)
def __str__(self):
return self.q_title
MCQ Views
def view_multichoice(request, m_id):
get_md = multichoice.objects(m_question_number = m_id)
return render(request, 'mcqs/mcq.html', {'get_md':get_md})
Quiz Views
def view_quiz(request, q_id):
get_q = quiz.objects(q_id = q_id)
return render(request, 'quiz/quiz.html', {'get_q':get_q})
Current Result
Expected Result
EDIT 1
Quiz Views
from django.shortcuts import render
from django.http import HttpResponse
from .models import *
from mcqs.models import *
def view_quiz(request, q_id):
quiz_object = quiz.objects(q_id=q_id)[0]
multichoice_objects = [multichoice.objects(m_id=id) for id in quiz_object.q_questions]
get_q = [objects[0].m_question for objects in multichoice_objects if objects]
return render(request, 'quiz/quiz.html', {'get_q':get_q})
Quiz Template
{{ get_q }}
You are returning the question documents as it is. What you should be doing is, fetch the multichoice documents corresponding to the question ids, and then get the question field from each of those documents.
Change the second line in quiz views to this:
# Get the question document corresponding to given id
# objects method returns a list. Get the first one out of it.
# Here, I've assumed there's exactly 1 quiz document per ID. Handle the edge cases
quiz_object = quiz.objects(q_id = q_id)[0]
# Get the multiple choice documents corresponding to the ids in q_questions list
# Remember that objects method returns a list. Hence this is a list of lists
multichoice_objects = [multichoice.objects(m_id=id) for id in quiz_object.q_questions]
# Get the actual questions from the multichoice documents
get_q = [objects[0].m_question for objects in multichoice_objects if objects]
Ideally, you should be making multichoice as an EmbeddedDocument and the q_questions field in quiz model as EmbeddedDocumentListField. But the drawback here will be, you can't query EmbeddedDocuments independently. So you wont be able to do multichoice.objects(m_question_number=m_id).
You can read more about EmbeddedDocuments here

Wagtail admin ,CheckboxSelectMultiple not saving data

#register_snippet
class Numbers(models.Model):
number = models.IntegerField()
class State(models.Model):
state = models.CharField(max_length=100)
number = ParentalManyToManyField(Numbers)
class HomeStateNumber(State):
page = ParentalKey('home.HomePage', related_name='helpline')
api_fields = ['state', 'number']
panels = [
FieldPanel('state'),
FieldPanel('number',widget=forms.CheckboxSelectMultiple),
]
class HomePage(Page):
content_panels = [
FieldPanel('title'),
ImageChooserPanel('cover_page'),
InlinePanel('ticker', label="ticker"),
InlinePanel('helpline', label="helpline"),
]
I want to add one than more number in a state , wagtail shows correct order in admin , when you select number from multiple and save the page, data is not saved. It remains None (queryset)
Is there any other way to do this ?
I think i am doing wrong somewhere
Please help
Models using ParentalManyToManyField need to inherit from modelcluster.models.ClusterableModel.
from modelcluster.models import ClusterableModel
class State(ClusterableModel):
state = models.CharField(max_length=100)
number = ParentalManyToManyField(Numbers)
Also, make sure you have django-modelcluster version 4.0 (or above) installed - older versions had a bug preventing m2m relations in inline objects from working.

How can I count the number of instances per a queryset? Django

I'm writing an action to set one field equal to the number of instances attached to it via a foreign key (see below)
Models.py
class competition(models):
competition_name = models.CharField(max_length = 50)
class people(models):
competition = models.ForeignKey(competition)
fullname = models.CharField(max_length = 100)
Admin.py
def people_in_competition:
for X in queryset:
X.number_of_people = X.count(X.set_all) #(I want the number of people in this competition in this part)
X.save()
Of course this gives me an error as I cant seem to use _set_all in admin.py, does it only work in templates? What would be the best way to figure that number out?
Use the backward relation:
X.number_of_people = X.people_set.all().count()

Sorting for custom fields in models in django admin

I want to have sorting functionality for custom model field in django admin.
The code is similar to
class MyModel(models.Model):
first_name = models.CharField()
last_name = models.CharField()
def most_recent_mailing_date(self):
""" Return the most recent mailing date """
mailingHistories = self.mailinghistory_set.all()
if len(mailingHistories) != 0:
today = datetime.date.today()
mostRecentHistory = None
diff = -1
for mailingHistory in mailingHistories:
if mailingHistory.mailing_date < today and (diff == -1 or (today - mailingHistory.mailing_date) < diff):
mostRecentHistory = mailingHistory
diff = today - mostRecentHistory.mailing_date
if mostRecentHistory is None:
return "No Mailing History"
else:
return mostRecentHistory.mailing_date
else:
return "No Mailing History"
most_recent_mailing_date.admin_order_field = 'self.most_recent_mailing_date'
The field I want to order is most_recent_mailing_date.
It is a custom field.
Is it possible?
Thanks in advance!
I don't think that's possible. From the docs:
You have four possible values that can be used in list_display:
....
A string representing an attribute on the model. This behaves almost
the same as the callable, but self in this context is the model
instance. Here’s a full model example:
from django.db import models from django.contrib import admin
class Person(models.Model):
name = models.CharField(max_length=50)
birthday = models.DateField()
def decade_born_in(self):
return self.birthday.strftime('%Y')[:3] + "0's"
decade_born_in.short_description = 'Birth decade'
class PersonAdmin(admin.ModelAdmin):
list_display = ('name', 'decade_born_in')
Thus, your field is the fourth option. However:
A few special cases to note about list_display:
...
Usually, elements of list_display that aren’t actual database fields
can’t be used in sorting (because Django does all the sorting at the
database level).
...(goes on to describe exception that doesn't apply here).
Thus, you can only sort on actual database fields.
You can't use Django's order_by since it is applied at the database level. The database does not know anything about your python methods and properties.
However, You can do the ordering in Python
objects = MyModel.objects.all()
sorted(objects, key=lambda k: k.most_recent_mailing_date())
If you want reverse ordering,
objects = MyModel.objects.all()
sorted(objects, key=lambda k: k.most_recent_mailing_date(), reverse=True)
Advice
I think you should be consistent on your return type. If there are no mailing history, you can return some old date instead of returning a string.
I think you should consider using the #property decorator on your most_recent_mailing_date() so you can simply refer to it as instance.most_recent_mailing_date. This will make it somehow consistent on how you refer to your actual model fields.

Categories

Resources