Add ID field to ModelForm - django

I need to add ID field to my form, and I'm getting so mad
Currently I have :
class ProductVideoForm(forms.ModelForm):
class Meta:
model = ProductVideo
translatable_fields = get_translatable_fields(ProductVideoTranslation)
fields = [
"product",
"id", #added!!!!
"type",
"placeholder",
] + translatable_fields
widgets = {
"placeholder": ImageInput(),
}
trans_fields_per_lang = get_trans_fields_per_lang(translatable_fields)
I added ID to fields, and the template is:
{{ video_formset.management_form }}
Why Is ID not displayed ??
actually, I just need display it, not updated.

Yea ok, but by default django will not display editable=False fields in forms.
What you are looking for is disabled param.
https://docs.djangoproject.com/en/4.1/ref/forms/fields/#disabled

Related

django form field displayed out of order

I have this form and model for a group:
class GroupForm(forms.ModelForm):
class Meta:
model = Group
fields = ('leader', 'description', 'size', 'max_size', 'motto')
widgets = {
'size': forms.CheckboxInput(attrs={'id': 'size'}),
'max_size': forms.TextInput(attrs={'type': 'hidden', 'id': 'maxSize'}),
}
The creator of the group has an option to check yes for size and on doing so, I used javascript to change the type of max_size to show.
In my create_group.html template:
<script>
let size = document.getElementById('size')
let maxSize = document.getElementById('maxSize')
let checked = false
size.onclick = () => {
checked = !checked
if (checked === true) {
maxSize.type = 'show'
} else {
maxSize.type = 'hidden'
}
}
</script>
Now, this works fine, the only problem is that the fields are displayed out of order.
When the page loads, max_size is false and its field is not displayed. Which is good. However, when the user checks that group has a size, and, subsequently, the max_size has a display of show, the field shows up after the motto field and not in its correct order according to fields = ('leader', 'description', 'size', 'max_size', 'motto').
Furthermore, the max_size field is included inside the motto element itself and not as its own field:
vs. the other fields which are all in their own <p></p>.
I'm guessing that {{form.as_p}} etc. render all the visible fields first, then the hidden ones.
You can explicitly render the fields in the order you want in your template. Rather than hardcoding the order in your template, maybe this (I've never tried this):
FIELD_ORDER = ( ('leader', 'description', 'size', 'max_size', 'motto')
class GroupForm(forms.ModelForm):
class Meta:
model = Group
fields = FIELD_ORDER
Pass to your template a list of fields explicitly in the order you want:
fields_in_order = [ form[x] for x in FIELD_ORDER ]
In the template
{% for field in fields_in_order %}
{{field}}
{% endfor %}
Or, you can make the hiding of this field something done by JS
If anyone else comes across this issue, it's also possible to just use js and css. Right now, I'm using javascript to see if size is checked and if it is then maxSize.style.display = 'block' vs maxSize.style.display = 'none' if size isn't checked.
Then I had the issue of django's form label still being visible. To fix that I saw an answer on dev.to which you can see for yourself.
My issue now is that I don't know how to add a label that is only visible when the form field is visible.

Filter queryset in django select2 widget

Is it possible to filter queryset in Django Select2 forms?
I got a form that sends a direct message to the user and I want to have the possibility to filter users.
s2forms.ModelSelect2Widget, as I see, selects all instances of User model
Now I need t to implement a flag to the User model (allow_direct_messages), and if the user allows sending direct messages, so I need to filter them accordingly.
class DirectMessageCreateForm(forms.ModelForm):
class Meta:
model = DirectMessage
fields = ("author", "recipient", "content")
labels = {
"author": "",
}
widgets = {
"recipient": UsersWidget,
"content": forms.Textarea(attrs={
'class': 'block p-3 w-full text-md bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500'
' focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 '
'dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500',
'placeholder': "Type your message here..."
}),
"author": forms.TextInput,
}
class UsersWidget(s2forms.ModelSelect2Widget):
search_fields = [
"name__icontains",
"email__icontains",
]
Maybe someone knows how to make a custom queryset inside ModelSelect2Widget form?
Thanks in advance
I found solution
Hope it will help somebody
Don`t be afraid to set a queryset attribute inside your class:
class UsersWidget(s2forms.ModelSelect2Widget):
*queryset = User.objects.exclude(profile__allow_direct_messages=False)*
search_fields = [
"name__icontains",
"email__icontains",
]
This should work!

How to add a searchable text field to select an item in drop down list?

I have a filter form as you can see https://jsfiddle.net/aba2s/qcsynt7f/6/. I would like to add a searchable field(in the red area) so users can filter the campaign naming tool object instead of scrolling. Any help is appreciated.
My filter class
class UserInsertionOrderFilter(django_filters.FilterSet):
start_date = django_filters.DateFilter(widget=DateInput)
end_date = django_filters.DateFilter(widget=DateInput)
class Meta:
model = UserInsertionOrder
fields = [
'campaign_naming_tool',
'start_date',
'end_date'
]
You can use select2.
And add script below to your template.
<script>
$(document).ready(function() {
$("#id_campaign_naming_tool").select2();
})
</script>

How do I create new models not affecting the nested serializer

I already have a general idea of how it should be done. The only issue that I face now is how to actually send the data. I don't want to create new Projects I just want to add them to the notifications. How do I pass the data, the actual JSON?
class NotificationsScheduleSerializer(ModelSerializer):
projects = ProjectSerializer(many=True) # Thats the Many2Many Field
user = HiddenField(default=CurrentUserDefault())
class Meta:
model = NotificationsSchedule
fields = [
"pk",
"projects",
"period",
"week_day",
"created_at",
"time",
"report_type",
"user",
]
def create(self, validated_data):
breakpoint() # I don't ever get "projects" in validated_data just Empty OrderedDict
projects_data = validated_data.pop("projects", [])
notification = NotificationsSchedule.objects.create(**validated_data)
return notification
class ProjectSerializer(ModelSerializer):
class Meta:
model = Project
fields = ["pk", "name"]
I want to be able to pass something like this.
{
"projects": [290, 289],
"period": "daily",
"week_day": 2,
"time": "16:02:00",
"report_type": "word_report"
}
But it expects dict instead.
"non_field_errors": [
"Invalid data. Expected a dictionary, but got int."
]
You have to set read_only,
projects = ProjectSerializer(many=True, read_only=True)
And when creating Notifications ,
notification = NotificationsSchedule.objects.create(**validated_data)
notification.projects.add(*self.initial_data.get("projects"))
notification.save()

Why table shows no data using a custom table template in django-tables2?

I am using django-tables to create a table from my model to display it on a page.
I have created the folowing tables.py file:
class OpenBetsTable(tables.Table):
class Meta:
model = Bet
fields = ("date", "time", "competition", "home",
"visitor", "bookie", "bet", "stake", "odds")
attrs = {"class": "table table-striped table-sm table-bordered"}
empty_text = "Nothing to display"
I have a class-based view that contains the following:
queryset = user_bets.filter(status__name="New").order_by("-timestamp")
table = OpenBetsTable(queryset)
RequestConfig(self.request, paginate={'per_page': 10}).configure(table)
context["table"] = table
In the page's template I have added {% load django_tables2 %} and {% render_table table %} to render the table.
Everything works correctly until this point.
I want to use a custom template for the table so I added template_name in OpenBetsTable, using one of the templates provided with django-tables2:
class OpenBetsTable(tables.Table):
class Meta:
model = Bet
template_name = "django_tables2/table.html"
fields = ("date", "time", "competition", "home",
"visitor", "bookie", "bet", "stake", "odds")
attrs = {"class": "table table-striped table-sm table-bordered"}
empty_text = "Nothing to display"
Everything still works correctly.
As a sidenote, there are a few ways to use a custom table template as shown in Is it possible to custom django-tables2 template for a specific page in this case?.
Because I wanted to use my own custom table template, I created a html file called bets_table.html. I just copied the content from django-tables2 default table template.
The new table is below:
class OpenBetsTable(tables.Table):
class Meta:
model = Bet
template_name = "bets/bets_table.html"
fields = ("date", "time", "competition", "home",
"visitor", "bookie", "bet", "stake", "odds")
attrs = {"class": "table table-striped table-sm table-bordered"}
empty_text = "Nothing to display"
Using the table above, the table is rendered, the headers are displayed correctly but no data is shown, it displays the empty_text string from the table class. Another thing that is interesting is that the pagination controls display the number of available pages correctly.
I have looked in django debug toolbar and found out that in comparison the table with the custom table template has a few missing SQL queries. I am not sure why is that.