Django 1.8 set exist default value of Update form - django

I wrote template
<div class="container">
<form action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
</div>
And, my View is below
class UserProfileUpdateView(UpdateView):
model = UserProfile
form_class = UserProfileUpdateForm
template_name_suffix = '_update_form'
And this is my UserProfile model below.
It uses User key
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
website = models.URLField(blank=True, verbose_name=u'Webサイト')
picture = models.ImageField(
upload_to='uploads/profile_images/%Y/%m/%d', blank=True,
null=True, verbose_name=u'Image'
)
age = models.IntegerField(verbose_name=u'Age')
country = models.CharField(max_length=30, verbose_name=u'country')
profile = models.CharField(max_length=300, verbose_name=u'profile')
address = models.CharField(max_length=300, verbose_name=u'address')
GENDER_CHOICES = (
(u'M', u'Male'),
(u'F', u'Female'),
)
gender = models.CharField(max_length=2, choices=GENDER_CHOICES, verbose_name=u'Gender')
CATEGORY_CHOICES = (
(u'U', u'u'),
(u'R', u'r'),
)
category = models.CharField(max_length=2, choices=CATEGORY_CHOICES, verbose_name=u'category')
last_accessed = models.DateTimeField()
My Form is
class UserProfileUpdateForm(forms.ModelForm):
slug_field = 'user_slug'
class Meta:
model = UserProfile
fields = (
'address', 'profile', 'gender', 'category',
'age',
'website', 'picture',
)
But, my form can't fill default value which already set before.
Could you tell me why doesn't set?

You should look at this: Django: using ModelForm to edit existing database entry
The key is:
form = MyModelForm(instance=MyModel.objects.get(pk=some_id))

Related

How to have a button in Django template to add more form variable? Then how to process the multiple forms in views?

I have 2 questions:
How to code a button to be able to add 1 or more duplicate form variable in template? I want to have a product_create page with a Product that may have multiple Color and Thickness.
Then how to save the Product with multiple Color and Thickness in views.py to database? Do I need for loop?
My 4 related models in models.py:
class Product(models.Model):
product_id = models.CharField(max_length=6)
video = models.URLField(max_length=250, null=True, blank=True)
class ColorParent(models.Model):
name = models.CharField(max_length=50)
class ProductColor(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
color = models.ForeignKey(ColorParent, on_delete=models.CASCADE)
class ProductThickness(models.Model, MeasurementUnits):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
dimension = models.PositiveIntegerField(verbose_name='Thickness in International SI unit',
null=True, blank=True)
dimension_unit = models.CharField(max_length=20,
choices=MeasurementUnits.si_base_units,
default=MeasurementUnits.millimetre, null=True, blank=True)
alias = models.CharField(verbose_name='Thickness in Imperial unit',
max_length=10, null=True, blank=True)
alias_unit = models.CharField(max_length=20,
choices=MeasurementUnits.imperial_base_units,
default=MeasurementUnits.inch, null=True, blank=True)
My forms.py:
class ProductForm(ModelForm):
class Meta:
model = Product
fields = ['product_id', 'video']
class ColorParentForm(ModelForm):
class Meta:
model = ColorParent
fields = ['name']
class ProductColorForm(ModelForm):
class Meta:
model = ProductColor
fields = ['color']
class ProductThicknessForm(ModelForm):
class Meta:
model = ProductThickness
fields = ['dimension', 'dimension_unit',
'alias', 'alias_unit']
My views.py:
def product_create_view(request):
product_form = ProductForm(request.POST, prefix='product_form')
color_form = ProductColorForm(request.POST, prefix='color_form')
thickness_form = ProductThicknessForm(request.POST, prefix='thickness_form')
if product_form.is_valid() and color_form.is_valid() and thickness_form.is_valid():
product = product_form.save() # save parent modelform first.
color = color_form.save(commit=False) # do not commit immediately for child modelform.
thickness = thickness_form.save(commit=False)
color.product = product # pair the color with created product first.
color.save() # proceed to save.
thickness.product = product
thickness.save()
context = {
'product_form': product_form,
'color_form': color_form,
'thickness_form': thickness_form,
}
return render(request, 'product_visualizers/product_create.html', context)
My current product_create.html template:
<form action="." method="post" enctype="multipart/form-data"> {% csrf_token %}
<p>Product ID {{product_form.product_id }}</p>
<p>Color Parent {{color_form.color}}</p> # Button target to add more {{color_form.color}}
<p>Video URL {{product_form.video}}</p>
<h3>Technical Specifications</h3>
<h4>Thickness Options</h4>
<p> # Button target to add more {{thickness_form.*}}
Dimension: {{thickness_form.dimension}} {{thickness_form.dimension_unit}}
Alias: {{thickness_form.alias}} {{thickness_form.alias_unit}}
</p>
<p><input type="submit" value="Save" /></p>
</form>

Every field in Django modelform shows "Select a valid choice. That choice is not one of the available choices."

I've already read many other threads complaining about this error message but I still can't figure this out. I try removing the fields that give the error, and the error message just moves to another field the next time I try to submit. They are CharField, Foreign Key, and other types.
forms.py
class TemporaryresponseForm(forms.ModelForm):
gender_custom = forms.CharField(
required=False,
label="",
)
ethnicity = forms.ModelChoiceField(
queryset=Ethnicity.objects.all(),
widget=forms.RadioSelect(),
empty_label=None,
required=True,
label="Which of the following best describes your ethnicity?"
)
...
class Meta:
model = Temporaryresponse
fields = [...'gender_custom', 'ethnicity',...]
views.py
def tr(request):
if request.method == "POST":
form = TemporaryresponseForm(request.POST)
if form.is_valid():
tempresponse = form.save(commit=False)
tempresponse.ip = "123456"
tempresponse.save()
return redirect('politicalpollingapp/index.html')
else:
form = TemporaryresponseForm()
return render(request, 'politicalexperimentpollapp/tr.html', {'form': form})
def nr(request, pk):
return render(request, 'politicalexperimentpollapp/nr.html', {'tempresponse': tempresponse})
tr.html template
{% extends 'politicalexperimentpollapp/base.html' %}
{% block extrahead %}
{% load crispy_forms_tags %}
{{ form.media }}
{% endblock extrahead%}
...
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<div><br></div>
<div class="text-center"><button type="submit" class="save btn btn-primary">CONTINUE</button></div>
</form>
..
models.py
class Ethnicity(models.Model):
ethnicity = models.CharField(max_length=200)
def __str__(self):
return '%s' % (self.ethnicity)
...
class Temporaryresponse(models.Model):
birth_year = models.PositiveIntegerField()
voting_registration = models.ForeignKey(Voting_registration, models.SET_NULL, null=True)
party_identification = models.ForeignKey(Party_identification, models.SET_NULL, null=True)
gender = models.ForeignKey(Gender, models.SET_NULL, null=True)
gender_custom = models.CharField(max_length=200, blank=True)
ethnicity = models.ForeignKey(Ethnicity, models.SET_NULL, null=True)
race = models.ManyToManyField(Race)
zip_code = models.IntegerField()
ip = models.CharField(max_length=200, blank=True)
policy_areas_of_importance = models.ManyToManyField(Policy_category, blank=True)
likelihood_of_voting = models.PositiveIntegerField(models.SET_NULL, null=True, blank=True)
Oddly no error shows up in my Chrome console - it's only because I am showing errors on the actual page. I'm not sure if that's normal. Thanks in advance for any help, I'm ripping my hair out at this point.
I discovered that I was using the wrong language for the "race" form field. I had used ModelChoiceField but it should be ModelMultipleChoiceField as follows:
race = forms.ModelMultipleChoiceField(queryset=Race.objects.all(), widget=forms.CheckboxSelectMultiple, label="5. Which of the following best describes your race? Please select all that apply.")

Get user OneToOneField fields in ModelForms

I've extended the django user with a OneToOneField so I can store address and such.
SiteUser is the model which extends User using a OneToOneField. How can I get fields of both User and SiteUser in a single ModelForm?
Here is the relevant code so far:
class ProfileForm(ModelForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class AddressForm(ModelForm):
pass
View in question:
def edit_profile(request):
username = request.user
user = User.objects.get(username__exact=username)
profileform_class = ProfileForm
if request.method == 'POST':
profileform = profileform_class(data=request.POST, instance=user)
if profileform.is_valid():
profileform.save()
return redirect('profile')
else:
profileform = profileform_class(instance=user)
return render(request, 'edit_profile.html', {
'user': user,
'profileform': profileform,
})
And the two models:
class Product(models.Model):
order = models.IntegerField(default=0)
name = models.CharField(max_length=255)
description = models.TextField()
image = models.ImageField(upload_to='product-images', default='default.jpg')
price = models.FloatField()
slug = models.SlugField(unique=True)
class SiteUser(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=255)
post_number = models.CharField(max_length=255, default='')
post_location = models.CharField(max_length=255, default='')
HTML Page I want the forms on:
{% extends 'base.html' %}
{% block title %}
Rediger {{ product.name }} - {{ block.super }}
{% endblock title %}
{% block content %}
<h1>Rediger "{{ user }}"</h1>
<form role="form" action="" method="post">
{% csrf_token %}
{{ profileform.as_p }}
{{ addressform.as_p }}
<button type="submit">Submit</button>
</form>
{% endblock content %}
One option is to use inline formsets. Using this, you won't be needing a second ModelForm.
Inline formsets is a small abstraction layer on top of model formsets. These simplify the case of working with related objects via a foreign key.
You can find good examples here.
Alternatively, if you want to avoid inline formsets and use both ProfileForm and AddressForm under a single <form> tag as you have done in your template, you can do it like this.
Forms:
class ProfileForm(ModelForm):
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class AddressForm(ModelForm):
class Meta:
model = SiteUser
exclude = ['user']
Views:
def edit_profile(request):
username = request.user
user = User.objects.get(username__exact=username)
profileform_class = ProfileForm
addressform_class = AddressForm
if request.method == 'POST':
profileform = profileform_class(data=request.POST, instance=user)
addressform = addressform_class(data=request.POST, instance=user.siteuser)
if all((profileform.is_valid(), addressform.is_valid())):
user = profileform.save()
address = addressform.save(commit=False)
address.user = user
address.save()
return redirect('profile')
else:
profileform = profileform_class(instance=user)
addressform = addressform_class(instance=user.siteuser)
return render(request, 'edit_profile.html', {
'user': user,
'profileform': profileform,
'addressform': addressform,
})
I don't know much about forms, but I think you should use the "initial" parameter when instantiating the AddressForm, as exemplified here: https://docs.djangoproject.com/es/1.9/topics/forms/modelforms/#providing-initial-values
So you create your AddressForm class with SiteUser as model, and when you instantiate it in the view, you make it like this:
AddressForm(initial={'user': request.user})
If "username" is not the primary key of the User model, you can get the primary key like this:
User.objects.get(username=request.user).pk
and then give it in the "initial" parameter.
model:
class Company(models.Model):
name = models.CharField(max_length=150)
description = models.CharField(max_length=150)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Bike(models.Model):
to_company = models.OneToOneField(Company, on_delete=models.CASCADE, related_name="bike_company")
name_bike = models.CharField(max_length=150)
model = models.CharField(max_length=150)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
form.py
class CompanyForm(ModelForm):
class Meta:
model = Company
fields = ("name", "description" )
class BikeForm(ModelForm):
name_bike = forms.CharField(required=True)
model = forms.CharField(required=True)
class Meta(CompanyForm.Meta):
model = Company
#transaction.atomic
def save(self):
company = super().save(commit=False)
company.name = self.cleaned_data.get("name")
company.description = self.cleaned_data.get("description")
company.save()
bike = Bike.objects.create(to_company=company)
bike.name_bike = self.cleaned_data.get("name_bike")
bike.model = self.cleaned_data.get("model")
bike.save()
return company
the relationship is kept in this line:
Bike.objects.create(to_company=company)
here is an example of a different type of user model
models user and type
https://gist.github.com/josuedjh3/259b4b3b03ab195637fe2db3c701edd6
FormModel the User and UserCreationForm
https://gist.github.com/josuedjh3/0c26d989552a82d5b252c5bd3fed1054

Django - how to exclude repeating objects

models.py
class Location(models.Model):
name = models.CharField(max_length=100, verbose_name=u"Локация", default=u'')
country = models.CharField(max_length=100, verbose_name=u"Страна", default=u'')
class Country(models.Model):
name = models.CharField(max_length=50, verbose_name=u"Страна")
class Photo(models.Model):
location = models.ForeignKey(Location, null=True, verbose_name=u'Фото')
photo = models.ImageField(upload_to='photos', null=True)
forms.py
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = ['name', 'country']
photos = MultiFileField(min_num=1, max_num=10)
def save(self, commit=True):
instance = super(LocationForm, self).save(commit)
for each in self.cleaned_data['photos']:
Photo.objects.create(photo=each, location=instance)
return instance
views.py
class AddLocationPageView(CreateView):
model = Location
form_class = LocationForm
template_name = 'add_location.html'
class BrowseLocationsPageView(ListView):
model = Country
context_object_name = 'countries'
template_name = "browse_locations.html"
add_location.html
<form action="" method="POST">{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-default" type="submit">Add</button>
</form>
browse_locations.html
{% for country in countries %}
{{ country }}
{% endfor %}
I need to get in browse_locations.html the list of countries without repeating.
For exapmple, I am creating location object with country 'USA'. Then I am creating second one with country 'USA'. And in my view I can see the list where there are two 'USA', but I need only one.
Thanks!!!
If you are using postgres, then you can use the distinct queryset filter with a field name.
class BrowseLocationsPageView(ListView):
def get_queryset(self):
return self.model.objects.distinct('name')
This solves the "issue" but there is a bigger problem at hand. Wherever you are creating the countries, you are creating new countries instead of looking if there is an existing country with the same name - get_or_create may be useful here.
Location should probably have a foreign key to a country too...
You have country as a CharField in the Location Model. Hence the repitition.
Change the country field as a ForeignKey in the Location model

Django1.6 UpdateView, how to display field without update it

models.py
class Application(models.Model):
desc = models.CharField(max_length=40, unique=True, null=False)
name = models.CharField(max_length=40, null=False)
user = models.ForeignKey(User)
views.py
class ApplicationUpdate(UpdateView):
model = Application
template_name = "apps/update.html"
fields = ['name', 'desc']
context_object_name = "app"
success_url = reverse_lazy('app-list')
templates
<div class='update-item'>
{{form.name.error}}
{{form.name.label_tag}}
{{form.name}}
</div>
<div class='update-item'>
{{form.desc.value}}
</div>
Here I want to display desc field in template, but only POST name field when update it. Any solution for it?
Try one of these:
Set readonly attributes on fields that you don't want to be changed.
Instead of {{form.desc.value}} you can display instance field value - {{ form.instance.desc }}, next remove desc field from include attribute.