I have some form modelformset_factory with model contains ForeignKey, but I need display this ForeignKey(ModelChoiceField) like CharField.
I use like that:
class SingleNeedFormWithDescription(ModelForm):
helper = StandardFormHelper()
helper.template = 'template.html'
need = CharField()
class Meta:
model = NeedMembershipOrganization
fields = ['need', 'description']
I have id of need in my template, but I need need.title or need.__str__().
My model:
class NeedMembershipOrganization(Model):
need = ForeignKey('needs.Need')
organization = ForeignKey(Organization)
description = TextField(blank=True, null=True, verbose_name='description')
Thanks!
You can change the ModelChoiceField widget to a TextInput, but you might have to figure out some way to validate and parse the input.
class SingleNeedFormWithDescription(ModelForm):
need = forms.ModelChoiceField(
queryset=Need.objects.all(),
widget=forms.TextInput)
Related
I have a model called Listing that has a field called categories that stores all the different categories. There is also a form with a field called categories that should show a choice field to the user, where the choices should be the values stored in the Listing.categories model field. So I tried to loop through it but that is not possible as the choice field values are stored in a dict format.
So how do I get the values from the model field into the choice field?
models.py
class Category(models.Model):
name = models.CharField(max_length=50)
class Listing(models.Model):
...
category = models.ForeignKey(Category, on_delete=models.PROTECT, null=True)
forms.py:
from .models import Listing
for i in Listing.category:
category_choices = (
(i, Listing.category)
)
class NewListing(forms.Form):
...
category = forms.ChoiceField(choices=category_choices)
You can use a ModelChoiceField in order to pass a queryset and allow the user to choose between all models in this queryset.
You would then get something like:
category = forms.ModelChoiceField(queryset=Category.objects.all())
For me I have done it in this way:
Models (choice fields are in your models)
CATEGORYCHOICES=(
(1, 'New'),
(2, 'Refurbished'),
(3, 'Opened'),
(4, 'Used'),
)
class Listing(models.Model):
...
categories = models.IntegerField(choices=CATEGORYCHOICES,default=0)
Then in your forms.py you will need to use "form select"
class NewListing(ModelForm):
class Meta:
model = Listing
fields = ('field_name1','field_name2')
labels ={
'field_name1': '',
'field_name2': '',
}
widgets = {
'field_name1':forms.Select(attrs={'class':'form-control'}),
'field_name2': forms.Select(attrs={'class':'form-control'}),
}
Does it make sense?
You will obvioulsy need to process that data in your views.py. Let me know if you have a question, I am happy to share the code I have for this.
If Category is a model then your condition_choices should be redundant, why use a model if those options are hardcoded? Instead of just using forms.Form, you should use a model form forms.ModelForm. You can then pass your category choices through queryset:
class ListingForm(forms.ModelForm):
self.categories = Category.objects.all()
super(ListingForm, self).__init__(*args, **kwargs)
self.fields['categories'].queryset = self.categories
The class definition as shown here is executed before the models ar initialized. So, you have to do something dynamic to construct the form class or to patch its choices.
I've just tried this at the console and it seems to work. Define BaseForm with all the fields that you don't want to fiddle with a run-time:
class BaseForm( forms.Form):
something = forms.WhateverField( args)
...
omitting your dynamic choicefield. At runtime, say in the get_form_class method of a class-based view, build the form you want using 3-argument type.
I'm not too clear on what queryset returns the set of categories, so adapt this code
class SomethingView( FormView):
...
def get_form_class( self):
# interrogate the DB to get a list of categories, or categories and labels.
choices = list( enumerate(categories) ) # [ (0,'cat0'), (1,'cat1'), ...]
choicefield = forms.ChoiceField( choices=choices, ...)
return type('My_runtime_form',
(BaseForm, ),
{ 'category': choicefield }
)
If you had a DB table Categories containing a pair of values choice_value and choice_label then you could obtain choices as
choices = Category.objects.filter( ... # maybe via a ManyToMany relation
).values_list('choice_value', 'choice_label')
I'm trying to add the CountryField to a serializer for the Register process (using dj-rest-auth) and can't find the correct way to implement it.
All the answers I found just say to use what the documentation says, but that doesn't help for me, maybe Im just not doing it right.
This is what the documentation of django-countries says:
from django_countries.serializers import CountryFieldMixin
class CountrySerializer(CountryFieldMixin, serializers.ModelSerializer):
class Meta:
model = models.Person
fields = ('name', 'email', 'country')
I need to add the field here:
class CustomRegisterSerializer(RegisterSerializer, CountryFieldMixin):
birth_date = serializers.DateField()
country = CountryField()
gender = serializers.ChoiceField(choices=GENDER)
# class Meta:
# model = User
# fields = ('country')
# Define transaction.atomic to rollback the save operation in case of error
#transaction.atomic
def save(self, request):
user = super().save(request)
user.birth_date = self.data.get('birth_date')
user.country = self.data.get('country')
user.gender = self.data.get('gender')
user.save()
return user
User Model
class User(AbstractUser):
"""
Default custom user model
"""
name = models.CharField(max_length=30)
birth_date = models.DateField(null=True, blank=True)
country = CountryField(null=True, blank=True, blank_label='Select country')
gender = models.CharField(choices=GENDER, max_length=6, null=True, blank=True)
...
I tried different things besides this and nothing worked.
For the serializer, you import the CountryField of the django_countries.serializer_fields module, so:
from django_countries.serializer_fields import CountryField
class CustomRegisterSerializer(RegisterSerializer):
# …
country = CountryField()
# …
If you instead want to work with the Mixin (which will use such CountryField serializer field), you should specify the CountryFieldMixin before the RegisterSerializer, otherwise it will not override the .build_standard_field(…) method.
You thus inherit with:
class CustomRegisterSerializer(CountryFieldMixin, RegisterSerializer):
# …
In that case you should not specify the country serializer field manually, since that will render the mixin ineffective.
I would like to do the exact same thing as this has the only difference that the default text disappears when the user enters text
name = models.CharField(max_length=16, default="default value")
Exemple :
i'm using this method for my form
class Device(models.Model):
phone_regex = RegexValidator(regex=r'^[0-9]{10}$', message="Error: Format 0611223344")
name = models.CharField(max_length=16, default="default value")
[....cut code....]
class DeviceForm(ModelForm):
class Meta:
model = Device
fields = ['name']
Looks like you want a placeholder value on your field. Add the following code to your Form class.
name = forms.CharField(
label='Name',
widget=forms.TextInput(attrs={'placeholder': 'Type name here...'})
)
The way to do this is to use Django Forms' widget properties. Here, you can change the HTML that will be rendered client-side.
class YourForm(ModelForm):
class Meta:
model = YourModel
fields = ('your', 'fields')
widgets = {
'form_field': forms.TextInput(attrs={'placeholder': "Search Content..."}
}
The above code will render an input tag for the field form_field, and add an HTML attribute of placeholder with the value of Search Content...
I have two models with their respective forms. One has a Foreign Key link to the other and from, here I would like to set some fields default data.
class Lexicon(models.Model):
[...]
case_sensitive = models.BooleanField(default=True)
invariant = models.NullBooleanField(default=False)
diacritics = models.BooleanField(default=True)
[...]
class Meta:
verbose_name = "lexicon"
ordering = ["filename"]
def __str__(self):
return self.filename
class Lexeme(models.Model):
lexicon = models.ForeignKey(Lexicon, on_delete=models.CASCADE)
case_sensitive = models.BooleanField(default=True)
diacritics = models.BooleanField(default=True)
[...]
class Meta:
verbose_name = "lexeme"
I would like the Lexeme model fields "case_sensitive" and "diacritics" to default from Lexicon. I suppose the forms may be a better place to do this.
Any idea ?
As I understand, you only need to populate data from Lexicon to Lexeme model fields. You can override get_form_kwargs in your FormView as follows
def get_form_kwargs(self):
lex_obj = Lexeme.objects.get(pk=self.kwargs['pk'])
kwargs = super().get_form_kwargs()
kwargs['initial']['case_sensitive'] = lex_obj.lexicon.case_sensitive
kwargs['initial']['diacritics'] = lex_obj.lexicon.diacritics
return kwargs
Is that what you want? I have not tested but, I have used similar thing on my project. Let me know if works or not.
I finally found the way to go. It was just basic initial setting of field, no need to touch to forms.py, models.py nor the html template.
I passed data to my form like this:
lexeme_form = LexemeForm(initial={'case_sensitive': lexicon.case_sensitive, 'diacritics': lexicon.diacritics})
use Ajax at template to change the initial value of "case_sensitive" and "diacritics" when Lexicon changed, and abstract model can be used to reduce repeat lines :
class BaseLex(models.Model):
case_sensitive = models.BooleanField(default=True)
diacritics = models.BooleanField(default=True)
class Meta:
abstract = True
class Lexicon(BaseLex):
# without `case_sensitive` and `diacritics' fields
...
class Lexeme(BaseLex):
# without `case_sensitive` and `diacritics' fields
lexicon = models.ForeignKey(Lexicon, on_delete=models.CASCADE)
...
I am trying to limit the fields to in my table. The only way I see to do it is through the PersonTable object with the field property like this fields = [first_name, last_name]. I want to do it from a request form. I tried to override the get_queryset() method but it did not work only passed in less data but the columns were still there just blank. Is there a good way to do it with the generic view?
class Person(models.Model):
first_name =models.CharField(max_length=200)
last_name =models.CharField(max_length=200)
user = models.ForeignKey("auth.User") dob = models.DateField()
class PersonTable(tables.Table):
class Meta:
model = Person
fields = [first_name, last_name]
class PersonList(SingleTableView):
model = Person
table_class = PersonTable
If anyone runs into this same issue, there is an exclude instance variable on the table class so you can just override get_table and do something like this in your view:
class PersonList(SingleTableView):
model = Person
table_class = PersonTable
template_name = "person.html"
def get_table(self):
table = super(PersonList, self).get_table()
columns = self.request.GET.getlist('column')
tuple_to_exclude = tuple(set(table.columns.names()) - set(columns))
table.exclude = tuple_to_exclude
return table