Dynamic form choice/option field in django - python

I have made this web app https://notes12345.herokuapp.com
The code of this app is here: https://github.com/theparadoxer02/Notes
What is want is to make the search form in such a way that when user select the year the choices for branches get generated dynamically , means only that branch options should come that of selected year, when when one is done selecting the branch , then the options for subjects should come that are related to selected year,branch above.
So in this way I want to generate form .
What should I learn? where should i modify file in views.py or models.py ? I am stuck with that .
Here is my model file:
year_choices = (
( 1 , 'First' ),
( 2 , 'Second'),
( 3 , 'Third' ),
( 4 , 'Fourth')
)
branch_choices = (
( 'IT','IT' ),
( 'EE','EE' ),
( 'CSE','CSE'),
( 'EC','EC' ),
( 'ME','ME' ),
( 'CE','CE' ),
)
subject_choices = (
( 'DS' , 'Data Structure' ),
( 'OS' , 'Operating sytem' ),
( 'EC' , 'Ecomomics' ),
( 'Thermo' , 'Thermo' ),
)
def generate_picture_name(instance, filename):
url = "images/{0}_{1}_{2}.jpg".format(
instance.subjects.branch, instance.subjects.year, instance.unit_no)
return url
class Subject(models.Model):
name = models.CharField(max_length=20)
no_of_units = models.IntegerField()
year=models.IntegerField(choices=year_choices)
branch=models.CharField(choices=branch_choices,max_length=15)
def __str__(self):
return self.name
class Note(models.Model):
#unit_choices = ((1,'1'),(2,'2'),(3,'3'),(4,'4'),(5,'5'),(6,'6'),(7,'7'),(8,'8'),(9,'9'),(10,'10'))
#branch = models.CharField(max_length=55,choices=branch_choices)
#year = models.IntegerField(choices = year_choices)
#subject_name = models.CharField(choices=subject_choices,max_length=10)
subjects = models.ForeignKey(Subject,on_delete=models.CASCADE)
unit_no = models.IntegerField()
picture = models.ImageField(upload_to = generate_picture_name)
def __str__(self):
return str(self.id)

You can easily do this using intercooler.js specifically by its dependent Select feature as mention in docs.

You have two options:
Either do everything server-side.
In that case split the search form in two django views.
First view, display a form with the year only. Submit the form to the second view (using <form action="url_for_second_view">
Second view, read the selected year, and respond with a form for the other options.
Or use javascript on the client to dynamically set the available options when the year changes.

Related

On admin django choose one element in a list and have same result in the inline

If we consider that "client" is a dropdown list, would it be possible to reflect the choice made in StatusAdmin in my StatusTextInline class in order to have only one client associated please?
Or to check if the two clients are the same before saving?
class StatusTextInline(admin.TabularInline):
model = StatusText
extra = 0
list_display = (
"id",
"client",
"label"
)
#admin.register(Status)
class StatusAdmin(admin.ModelAdmin):
list_display = (
"id",
"client"
)
inlines = [
StatusTextInline,
]
Knowing that client is a list, if I choose client 1 in StatusAdmin, then I will automatically have client 1 in my StatusTextInline.

Django admin how to show a progress bar in percentage

In the Django built-in admin site, how can I show a progress bar in the Change List pages and Change Form page as a field?
For example:
Create method percentage_paid in your model to calculate the result and render an HTML element.
# models.py
class SomeModel(models.Model):
....
def percentage_paid(self):
if self.paid_amount and self.final_price:
percentage = round((self.paid_amount / self.final_price * 100), 2)
else:
percentage = 0
return format_html(
'''
<progress value="{0}" max="100"></progress>
<span style="font-weight:bold">{0}%</span>
''',
percentage
)
Add this method field 'percentage_paid' to readonly_filds
Meanwhile, add it to list_display if you want to show in Change List Page and or fields if want it in Change Form Page. I add it to fieldsets to customize my Change Form.
# admin.py
class CaseAdmin(CommonInfoAdmin):
fieldsets = CommonInfoAdmin.fieldsets + (
('Sales Summary', {
'fields': (
....
('final_price', 'paid_amount', 'balance', 'percentage_paid'),
....
)
}),
)
readonly_fields = [
....
'percentage_paid',
]
list_display = (
....
'percentage_paid'
)
The results:
Change List
Change Form

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 add a document on a StreamField in Wagtail CMS?

I've a question about Wagtail CMS.
Recently I'm trying to import programmatically some documents in a StreamField of an instance of a Wagtail Page model. I've done some researches but without results.
Currently I'm using:
Wagtail 1.13
Django 1.11.6
Python 2.7
Here the model of the page in which I need to import the documents as attachments (see the homonym field):
class EventPage(TranslatablePage, Page):
# Database fields
uuid = models.UUIDField(verbose_name='UUID', default=uuid.uuid4)
start_date = models.DateField(verbose_name='Start date')
end_date = models.DateField(verbose_name='End date')
location = models.CharField(verbose_name='Place', max_length=255, null=True, blank=True)
body = RichTextField(verbose_name='Body')
attachments = StreamField(blocks.StreamBlock([
('document', DocumentChooserBlock(label='Document', icon='doc-full-inverse')),
]), verbose_name='Attachments', null=True, blank=True)
subscribe = models.BooleanField(verbose_name='Subscribe option', default=False)
# Editor panels configuration
content_panels = [
FieldPanel('title', classname='title'),
MultiFieldPanel([
FieldRowPanel([
FieldPanel('start_date'),
FieldPanel('end_date'),
]),
], heading='Period'),
FieldPanel('location'),
FieldPanel('body'),
StreamFieldPanel('attachments'),
]
promote_panels = Page.promote_panels + [
MultiFieldPanel([
FieldPanel('subscribe'),
], heading='Custom Settings'),
]
settings_panels = TranslatablePage.settings_panels + [
MultiFieldPanel([
FieldPanel('uuid'),
], heading='Meta')
]
parent_page_types = ["home.FolderPage"]
subpage_types = []
On shell, I tried to apply the solution explained on this page but without success.
event = EventPage.objects.get(pk=20)
doc = Document.objects.get(pk=3)
event.attachments = [
('document',
[
StreamValue.StreamChild(
id = None,
block = DocumentChooserBlock(),
value = doc
)
]
)
]
Python give me this error: AttributeError: 'list' object has no attribute 'pk'.
event.attachments = [('document', doc)] should work, I believe. (On the other question you link to, StreamChild was necessary because AccordionRepeaterBlock was a StreamBlock nested in a StreamBlock; that's not the case for your definition.)
To add a document to the existing StreamField content, build a new list and assign that to event.attachments:
new_attachments = [(block.block_type, block.value) for block in blocks]
new_attachments.append(('document', doc))
event.attachments = new_attachments
(Currently you can't append directly to a StreamField value, but this may well be supported in a future Wagtail release...)

Filter on annotated column in django

I have two models:
class Project(models.Model):
...
class StateChange(models.Model):
created_at = models.DateTimeField(default=now, db_index=True)
project = models.ForeignKey("project.Project")
state = models.IntegerField(choices=PROJECT_STATE_TYPES, db_index=True)
...
The models are linked and I need a list of projects which is filtered by the related StateChange if there's one.
I build my queryset like this:
state_checked = Case(
When(statechange__state=PROJECT_STATE_CHECKED, then=F('statechange__created_at'))
)
state_construction_ordered = Case(
When(statechange__state=PROJECT_STATE_CONSTRUCTION_ORDERED, then=F('statechange__created_at'))
)
qs = Projekt.objects.visible_for_me(self.request.user) \
.annotate(date_reached_state_checked=state_checked) \
.annotate(date_reached_state_construction_ordered=state_construction_ordered)\
.exclude(Q(date_reached_state_checked__isnull=True) & Q(statechange__state=PROJECT_STATE_CHECKED) |
Q(date_reached_state_construction_ordered__isnull=True) & Q(statechange__state=PROJECT_STATE_CONSTRUCTION_ORDERED))
The Project may have no matching StateChange, or one or both.
I need the list to show one Project-line in all cases. My queryset only works for zero or one matching StateChange. It excludes the Projects where both StateChanges are present and I see why it does it when I look at the generated query.
If I do not exclude anything, it shows 1 line for each case.
Can anyone give me a hint about how to make django create the JOINs I need?
We did it by using .extra():
return Projekt.objects.all().extra(
select={
"date_reached_state_checked": "SELECT created_at FROM tracking_statechange WHERE tracking_statechange.projekt_id = projekt_projekt.id AND tracking_statechange.state = 20",
"date_reached_state_construction_ordered": "SELECT created_at FROM tracking_statechange WHERE tracking_statechange.projekt_id = projekt_projekt.id AND tracking_statewechsel.state = 50"
})

Categories

Resources