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.
Related
I have a ModelChoiceField in a form that uses a TextInput widget. I want to be able to select a value from the database or add new entries to the database with this input. If the value is not already in the database, I get an error on the form that says "Select a valid choice. That choice is not one of the available choices."
Model
class FeedCategory(models.Model):
category = models.CharField(max_length=255, unique=True)
class RssFeed(models.Model):
category = models.ForeignKey(FeedCategory, null=True, on_delete=models.SET_NULL)
name = models.CharField(max_length=255)
feed = models.URLField()
Form
class RssForm(forms.Form):
name = forms.CharField()
feed = forms.URLField()
category = forms.ModelChoiceField(queryset=FeedCategory.objects.all(), to_field_name='category', widget=forms.TextInput())
def clean(self):
cleaned_data = super().clean()
????
Views
class RssCreateView(FormView):
template_name = 'dashboard/rss_feed_form.html'
form_class = RssForm
success_url = '/dashboard/'
def form_valid(self, form):
name = form.cleaned_data['name']
feed = form.cleaned_data['feed']
category = form.cleaned_data['category']
rss_obj = RssFeed(category=category, name=name, feed=feed)
rss_obj.save()
return super().form_valid(form)
Template
<form method="post">
{%csrf_token%}
{{form|crispy}}
<button type="submit">Save</button>
</form>
It might help you what I am using:
category = models.ForeignKey("General.entity",verbose_name='Category', db_column="CategoryEntityRef", null=False, blank=False)
so, what I am doing with this is creating a field that points to an existing category that exists in another table. It will display it as a dropdown box. However using this method will allow me to have the option to add another Category:
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>
I try to set my field in form readonly and put any default value.
This is a part of my form:
category = forms.CharField(widget=forms.TextInput(attrs={'readonly':
'readonly'}),
initial=Category.objects.get(name='Zdrowie i uroda'))
class Meta:
model = Site
fields = ('url', 'name', 'description', 'keywords', 'group', 'category',
'subcategory', 'category1', 'subcategory1')
I get an error: Cannot assign "'Zdrowie i uroda'": "Site.category" must be a "Category" instance.
This is my site model:
class Site(models.Model):
category = models.ForeignKey('Category')
subcategory = ChainedForeignKey(
'SubCategory',
chained_field='category',
chained_model_field='category',
show_all=False,
auto_choose=True)
name = models.CharField(max_length=70)
description = models.TextField()
# importuje zmienione TextFields widgets.py
keywords = MyTextField()
date = models.DateTimeField(default=datetime.now, editable=False)
url = models.URLField()
is_active = models.BooleanField(default=False)
category1 = models.ForeignKey('Category', related_name='category', blank=True, null=True, default=None)
subcategory1 = ChainedForeignKey(
'SubCategory',
chained_field='category1',
chained_model_field='category',
related_name='subcategory',
show_all=False,
auto_choose=True, blank=True, null=True, default=None)
group = models.CharField(max_length=10, choices=(('podstawowy', 'podstawowy'),
('premium', 'premium')), default='podstawowy')
def get_absolute_url(self):
return reverse('site', args=[str(self.category.slug),
str(self.subcategory.slug), str(self.id)])
def get_thumb(self):
host = urlparse(self.url).hostname
if host.startswith('www.'):
host = host[4:]
thumb = 'http://free4.pagepeeker.com/v2/thumbs.php?size=s&url=' + host
return thumb
class Meta:
verbose_name_plural = "Strony"
def __str__(self):
return self.name
I can't deal with it. Any clues?
Finally I excluded category, subcategory fields from my model.form and added it to html source manually:
{{ form_extended|bootstrap }}
<label for="example-text-input" class="col-2 col-form-label">Category</label>
<input class="form-control form-control-lg" type="text" name="category" disabled required value="{{ form_extended.initial.category.name }} " />
<label for="example-text-input" class="col-2 col-form-label">Subcategory</label>
<input class="form-control form-control-lg" type="text" name="subcategory" disabled required value="{{ form_extended.initial.subcategory.name }} " />
I don't think it is a right way but I can't put some data to form initial values. Should I create my form manually from scratch? My way isn't good because I use jQuery to extend form. Now category, subcategory fields are las but they shouldn't (when user choose "premium" group from choice fields, after subcategory field there should appear "category1", "subcategory1" fields...
As always - I am sorry for my terrible English. Every post is like exam to me.
Options without further delving into Django forms:
Change Model Field
This might not be an option, but you could try setting:
class Site(models.Model):
category = models.ForeignKey('Category', editable=False)
Remove the explicit declaration of the category form field from your form and simply set the initial category when initializing the form or override __init__ to set it.
Change Form Field
Django would normally render a ForeignKeyField as drop down. Do you explicitly want a text input instead? In that case you have to handle data validation and the data mapping yourself.
A way of working around that would be to remove the explicit declaration of the form field and simply handle this field separatly in your HTML template:
<input type="text" name="category" value="{{ form.initial.category.name }}" />
"Do you explicitly want a text input instead?" - No.
In that case, you want a ModelChoiceField instead of a CharField.
category = forms.ModelChoiceField(
queryset=Category.objects,
empty_label=None,
disabled=True, # Django 1.9+
initial=Category.objects.get(name='Zdrowie i uroda'))
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
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))