Django TimeField Model without seconds - django

Greetings,
I am trying to implement a TimeField model which only consists of HH:MM (ie 16:46) format, I know it is possible to format a regular Python time object but I am lost about how to manage this with Django.
Cheers

Django widget can be used to achieve this easily.
from django import forms
class timeSlotForm(forms.Form):
from_time = forms.TimeField(widget=forms.TimeInput(format='%H:%M'))

DateTime fields will always store also seconds; however, you can easily tell the template to just show the hours and minute, with the time filter:
{{ value|time:"H:M" }}
where "value" is the variable containing the datetime field.
Of course, you can also resort to other tricks, like cutting out the seconds from the field while saving; it would require just a small change to the code in the view handling the form, to do something like this:
if form.is_valid():
instance = form.save(commit=False)
instance.nosecs = instance.nosecs.strptime(instance.nosecs.strftime("%H:%M"), "%H:%M")
instance.save()
(note: this is an ugly and untested code, just to give the idea!)
Finally, you should note that the admin will still display the seconds in the field.
It should not be a big concern, though, because admin should be only used by a kind of users that can be instructed not to use that part of the field.
In case you want to patch also the admin, you can still assign your own widget to the form, and thus having the admin using it. Of course, this would mean a significant additional effort.

So I think the proposed and accepted solution is not optimal because with:
datetime.widget = forms.SplitDateTimeWidget(time_format=('%H:%M'))
For a SplitDateTimeField in my case but for you only change it to TimeWidget.
Hope it helps other people too.

TimeField model
in Template
Is displayed
{{ value|time:"H:i" }}
Is not displayed
{{ value|time:"H:M" }}
Django 1.4.1

For a ModelForm, you can easily add a widget like this, to avoid the seconds being shown (just show hh:mm):
class MyCreateForm(forms.ModelForm):
class Meta:
model = MyModel
fields = ('time_in', 'time_out', )
widgets = {
'time_in': forms.TimeInput(format='%H:%M'),
'time_out': forms.TimeInput(format='%H:%M'),
}

You can at least modify the output in the __str__ method on the model by using datetime.time.isoformat(timespec='minutes'), like this:
def __str__(self):
return self.value.isoformat(timespec='minutes')
Now the value is showing as HH:MM in admin pages.

On Django 1.9 the following format should work:
{{ yourData.value|time:"H:i" }}
Django has a whole set of template tags and filters.
Django 1.9 documentation on this is:
https://docs.djangoproject.com/en/1.9/ref/templates/builtins/#time

Related

Django - form's ChoiceField not updating immediately

I have created a form in forms.py which uses select input based on objects from the database:
from controls.models import Valve
class CronjobForm(forms.Form):
query = Valve.objects.all()
VALVE_CHOICES = [
(valve.pk, valve.name) for valve in query
]
valves = forms.ChoiceField(required=True, widget=forms.Select, choices=VALVE_CHOICES)
At first, everything seemed to work just fine, the HTML's <select> with option got rendered.
The problem is, when I add a new Valve object to the database, using the Django Admin interface, it takes a while for the ChoiceField field to get updated - I can't see the new option on front-end immediately. I tried to reload the page, force reload, even print out the query to the terminal - the variable query got updated immediately, just the HTML did not.
It eventually gets updated after a while, minute or so, maybe thanks to the system checks or by repeating the runserver command.
So I'm wondering, what am I missing? Is there some way to force update the form? Does the form get cached and that's what causes the problem?
This is because the query is being evaluated when the class is defined, not when the form is instantiated.
Don't do this. Use a ModelChoiceField, which accepts a queryset.
class CronjobForm(forms.Form):
valves = forms.ModelChoiceField(required=True, widget=forms.Select, queryset=Valve.objects.all())
We can also pass a reference of the function which will return the array for choices, as mentioned in the choices' description of django docs.
I also faced the same issue, which was resolved like this.
def get_valve_choices():
return [
(valve.pk, valve.name) for valve in Valve.objects.all()
]
class CronjobForm(forms.Form):
valves = forms.ChoiceField(required=True, widget=forms.Select, choices=get_valve_choices)

Django DateTimeField

I have a field in my model
published_on = models.DateTimeField()
on a Django template page and I want to show only the date instead of date along with time. Any idea how to truncate the time form date in the django model form?
Thanks in advance.
Use the date filter in your template, for instance:
{{ form.published_on|date:"D d M Y" }}
Or just:
{{ form.published_on|date }}
You can customize the output the way you want, or use the locale default. See this link for details.
You could try to use SplitDateTimeWidget to represent the field in two widgets (https://docs.djangoproject.com/en/dev/ref/forms/widgets/#splitdatetimewidget). Then, for example, the time field could be hidden with CSS. This method is particularly useful if you need to preserve the actual time value, and just allow user to change the date.

DJANGO - How to generate a form for a model not known in advance because of the contentType instance

I have the following model and it's form:
class Project(models.Model)
class ProjectForm(forms.ModelForm)
class Meta:
Model = Project
So it's easy to create a form by instantiating:
form = ProjectForm()
But in my case, I have several models aside from "Projects", and I don't know in advance for which of these models I will need to create the form.
So I would like to create the form from the ContentType instance of the Project model.
In other words, I'm looking for something that looks like:
myproject = Project()
form = createform(myproject.ContentType)
Presumably you have a certain limited selection of models that might be used. The simplest way is just to create form classes for each of them, then choose the one you need from a dictionary:
MODEL_FORMS = {
MyModel: MyModelForm,
MyOtherModel: MyOtherModelForm
}
my_form_class = MODEL_FORMS[my_project.content_type]
my_form = my_form_class()
Unfortunately, this was the best I could find - but a combination of get_model and form_for_model should do the trick. You'll need to use get_model to load up the model type you want to work on, and then form_for_model to get a form for that model.
Edit: Daniel's solution is a much better one if you know what models you're dealing with.
Thank you to both of you, this helps a lot !
I will go with Daniel's solution as I have a limited number of models.
I think maybe I will need to add model_class() to "my_project.content_type.model_class()" in order to get the model class (to be checked) ?
Just for the record, I had managed to make something work with model formset factories :
from django.forms.models import modelformset_factory
ProjectFormSet = modelformset_factory(my_project.content_type.model_class())
my_form = ProjectFormSet()
but this form would of course not get all the customisations made in my model forms... so that was not a good solution.

Django Forms and Buttons

I have been working on forms only recently and I am still puzzeld by them.
What I want are standard Forms:
Next Button
Submit Data to Db
Timestamp
Clickable Images with Regions defined where when I click I get to the next page
And
I would like to combine these.
E.g. have a next button + Record the Timestamp.
or
E.g. Click into an Image + Next + Timestamp
If anybody could give me some examples for code that can achieve that or a good online resource on where to get info on that, that would be awesome.
Thanks for the time!!
I'm a little unclear about what you're trying to accomplish, but if you're trying to move data from an HTML form to the database, I'd suggest looking at how to use ModelForms. In a nutshell, you create a model class, like this:
class MyModel(models.Model):
field1 = models.CharField(max_length=50)
Then you create a ModelForm class that references that model:
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
You can render an instance of MyModelForm in a view function. Inside of a POST request in that view, you bind the POST data to the form, validate it, and call save() on it to commit it to the database:
if request.method == 'POST':
form = MyModelForm(request.POST)
if form.is_valid():
model_instance = form.save()
This really isn't a question, I'm not exactly sure what you're trying to accomplish.
If you want to use Django forms, start here, or here.
I assume the stuff you mention about a timestamp should probably be an auto_now field in a model. Take a look at this.
The stuff you mention about buttons and click-able images is really just HTML and has nothing to do with Django. I would try Google for that.

Hidden field in Django Model

A while back I made a Model class. I made several ModelForms for it and it worked beautifully.
I recently had to add another optional (blank=True, null=True) field to it so we can store some relationship data between Users. It's essentially a referral system.
The problem is adding this new field has meant the referral field shows up where I haven't changed the ModelForms to exclude it. Normally this would just mean an extra 10 minutes going through and excluding them but in this case, due to project management politics out of my control, I only have control over the Models for this application.
Can I either:
Set the field to auto-exclude?
Set it so it renders as a hidden (acceptable if not perfect)?
If you have access to the template you could render it as a hidden field with the following code:
{{ form.field_name.as_hidden }}
instead of the standard:
{{ form.field_name }}
from the docs on Using a subset of fields on the form:
Set editable=False on the model field. As a result, any form created from the model via ModelForm will not include that field.
You could define a custom model field subclass and override the formfield() method to return a field with a HiddenInput widget. See the documentation for custom fields.
Though you mentioned that you cannot use exclusion in your case, I think others who come across this answer (like myself, based on the title) may find it helpful.
It is possible to selectively hide fields using exclude in ModelAdmin, here is a snippet from something I'm working on:
class ItemsAdmin(admin.ModelAdmin):
form = ItemsForm
actions = None
list_display = ('item_id', 'item_type', 'item_title', 'item_size', 'item_color',)
search_fields = ('item_id', 'item_title',)
inlines = [ImageInline,]
readonly_fields = ('disable_add_date','disable_remove_date',)
exclude = ('add_date', 'remove_date',)
###.............