Django Forms - set field values in view - django

I have a model which represents a work order. One of the fields is a DateField and represents the date the work order was created (aptly named: dateWOCreated). When the user creates a new work order, I want this dateWOCreated field to be automatically populated with todays date and then displayed in the template. I have a few other fields that I want to set without user's intervention but should show these values to the user in the template.
I don't want to simply exclude these fields from the modelForm class because there may be a need for the user to be able to edit these values down the road.
Any help?
Thanks

When you define your model, you can set a default for each field. The default object can be a callable. For your dateWOCreated field we can use the callable date.today.
# models.py
from datetime import date
class WorkOrder(models.Model):
...
dateWOCreated = models.DateField(default=date.today)
To display dates in the format MM/DD/YYYY, you need to override the widget in your model form.
from django import forms
class WorkOrderModelForm(forms.ModelForm):
class Meta:
model = WorkOrder
widgets = {
'dateWOCreated': forms.DateInput(format="%m/%d/%Y")),
}
In forms and model forms, the analog for the default argument is initial. For other fields, you may need to dynamically calculate the initial field value in the view. I've put an example below. See the Django Docs for Dynamic Initial Values for more info.
# views.py
class WorkOrderModelForm(forms.ModelForm):
class Meta:
model = WorkOrder
def my_view(request, *args, **kwargs):
other_field_inital = 'foo' # FIXME calculate the initial value here
form = MyModelForm(initial={'other_field': 'other_field_initial'})
...

Related

Django ForeignKey, hide from user select options in dropdown menu

I have standard Django models with ForeignKey.
Django docs:
"ForeignKey is represented by django.forms.ModelChoiceField, which is a ChoiceField whose choices are a model QuerySet."
and
"If the model field has choices set, then the form field’s widget will be set to Select, with choices coming from the model field’s choices."
Now I have dropdown menu with choices.
I don't want dropdown menu where user can see options. I want CharField(textfield or similar) where user type, but still
that must be one of the options from the database for that field. He must type a valid entry.
I tried:
class TransakcijeForm(forms.ModelForm):
model = models.Transakcije
fields = .....
labels = .....
widgets ={'subscriber':forms.TextInput()}
but I receive the message:
"Select a valid choice. That choice is not one of the available choices."
(entry is correct and it works with dropdown menu)
This is my first question here and I'm sorry if I miss the form.
The reason you are getting that error is because your form is still treating the subscriber field as a ModelChoiceField because you are only overriding what widget is rendered to html. You need to change the actual field type of your field. You can define your form like this:
from django.core.exceptions import ValidationError
class TransakcijeForm(forms.ModelForm):
subscriber = forms.CharField()
class Meta:
model = models.Transakcije
fields = ....
labels = ....
def clean_subscriber(self):
subscriber_id = self.cleaned_data['subscriber']
try:
# adjust this line to appropriately get the model object that you need
subscriber = SubscriberModel.objects.get(id=subscriber_id)
return subscriber
except:
raise ValidationError('Subscriber does not exist')
The line subscriber = forms.CharField() will change the form to treat the field as a CharField rather than a ModelChoiceField. Doing this will cause the form to return the subscriber field value as a string, so you will need to get the appropriate model object based on the value of the field. That is what the clean_subscriber(self) function is for. It needs to be named like clean_<field name>(). That function will take the string that is returned by the form, try and find the correct model object and return it if an object is found. If it finds no matching objects it will raise a ValidationError so the form doesn't submit with a bad value.

How can I access parent model fields in a form using the child model?

For context, I'm trying to create a form that allows users to upload info about their own custom Pokemon. Basically, they are creatures that you can catch, name, and level up. To draw a comparison, it is a similar concept to dogs; there are labradors, German Shepherds, huskies, etc. that would be variations of a base Dog model, but then each individual would have a name and other defining characteristics.
I've created Pokemon and CustomPokemon models and imported the latter into my forms.py file. I'm trying to access some parent fields but am unable to:
from django import forms
from .models import CustomPokemon
class PokemonForm(forms.ModelForm):
class Meta:
model = CustomPokemon
fields = ['pokemon.poke_name', 'name', 'level']
The poke_name field is inherited from the parent Pokemon model while the other two fields belong to the CustomPokemon model. I'm getting this FieldError:
Unknown field(s) (pokemon.poke_name) specified for CustomPokemon.
The issue isn't resolved by using poke_name, so I'm curious how I can access the parent model's fields so they can be displayed in the form.
First option
If you just want a dropdown displaying the field poke_name, what you could do is to define a __str__ method inside Pokemon model like this:
class Pokemon(model.Model):
...
def __str__(self):
return self.poke_name
Then, you can define the form as follows:
class PokemonForm(forms.ModelForm):
class Meta:
model = CustomPokemon
fields = ['pokemon', 'name', 'level']
And you will get a dropdown displaying all the poke_name of your database, where you can choose your foreign key. It would be better if poke_name is a unique field so that the foreign key can be clearly identified.
Second option
If you need more freedom, you could manually define a custom field as follows:
class PokemonForm(forms.ModelForm):
poke_name = forms.CharField()
class Meta:
model = CustomPokemon
fields = ['name', 'level']
Then, when validating the form, you should take care of whether the entry exists and/or create it:
if form.is_valid():
form.instance.pokemon = Pokemon.objects.get_or_create(cname=form.cleaned_data['poke_name'])
form.save()

Django restrict options of ManyToMany field in ModelForm based on model instance

I want to show only options already stored in models' ManyToManyField.
I have model Order which I want to have a Model based form like this:
class OrderForm(ModelForm):
class Meta:
model = Order
fields = ['amount', 'color']
Now I do not want to display all colors as choices, but instead only color instances saved in ManyToManyField of another model. The other model is Design:
class Design(models.Model):
color = models.ManyToManyField('maker.Color')
# ...
Is this at all possible while using ModelForm?
Attempt
I have tried doing it by having a ModelForm of Design and setting instance:
class ColorForm(ModelForm):
class Meta:
model = Design
fields = ['color']
And then in view:
color_form = ColorForm(instance=design)
But I don't exactly understand what setting instance does, and I think instance is not what I am looking for as it still lists all colors.
The instance setting has nothing to do with limiting the choices. In essence, it simply populates the form's values with the ones from a specific record. You usually provide an instance in an edit operation, whereas you skip it in an add operation.
The representation of a models.ManyToManyField in the ModelForm is a forms.ChoiceField for which you can simply override its queryset property, and specify the queryset you desire.
Therefore, in your view:
form = OrderForm()
form.fields['color'].queryset = Design.object.all() # for example

Edit related object using ModelFormSet

I was using a model formset to generate a table of forms for a list of objects.
Forms:
class UserTypeModelForm(ModelForm):
account_type = ChoiceField(label='User type',
choices=ACCOUNT_OPTIONS, required=False)
class Meta:
model = get_user_model()
fields = ('account_type',)
UserTypeModelFormSet = modelformset_factory(get_user_model(),
form=UserTypeModelForm,
extra=0)
View:
formset = UserTypeModelFormSet(queryset=users, prefix='formset')
Now my client wants to be able to modify a related field: user.employee_profile.visible.
I tryed to add a field to the form, and then passing "initial" and "queryset" to the formset, but It looks like it just takes one.
How would you guys do this?
Thanks
with model formsets, the initial values only apply to extra forms, those that aren’t bound to an existing object instance.
Django docs
The queryset provides the selected/entered values for the bound fields, the initial for the extra fields (in your case 0).
But you can override the initial value in e.g. your views when you created a field called employee in this case:
for form in forms:
# Don't override a selected value.
if not form.fields['employee'].initial:
form.fields['employee'].initial = my_init

How can I create a form for that is populated with the current data in the database in django?

I am new to Django and I am using 1.7. I am looking for an example, on how to create a form that is populated with the current values which are stored. This way the user can see the forms current values and just modify the the ones they want. Then click save.
Assuming you're talking about values stored on a model, you can prepopulate a ModelForm using instance:
#######forms.py#############
class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['title']
#######views.py################
#create a normal ModelForm without any pre-populated values
blank_form = ArticleForm()
#create a ModelForm pre-populated with a specific object. first, get that object
article = Article.objects.get(pk=1)
form = ArticleForm(instance=article)
Taken from https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/