I have a model Prova:
class Prova(models.Model):
id = models.AutoField(primary_key=True)
codice= models.TextField(blank=True, null=True)
foto = models.ImageField(upload_to='stati/uploads/', blank=True)
and this is the form:
class ProvaForm(forms.ModelForm):
class Meta:
model = models.Prova
fields = ('codice','foto',)
widgets = {
'codice': forms.Textarea(attrs={'rows':1, 'cols':15,
'autofocus':'autofocus',
}),
'foto': forms.ClearableFileInput(attrs={'type': 'camera'}),
}
the customization of the codice field is working, but not the foto.
I want to change the type of html input from 'file' to specific image from 'camera'.
Tried also ImageField and
'foto': forms.FileInput(attrs={'capture': 'camera'}),
What am I missing to get it like the pure html:
<input type="file" capture="camera" accept="image/*">
camera is not valid HTML for the value of the type attribute of an input element.
If you do change it to <input type="camera" name="a-name-here" value="some-value">, then Chrome and FF will render it as a text input, while your ProvaForm expects a file (an ImageField), resulting in a failed validation. Of course you can override the validation part, by writting you own one, but what's the point of using an ImageField from the start if instead this field is going to be rendered as a text?
Check here for the possible values of the type attribute of an input element.
Related
I have an app in which two models are related with foreign keys.
class Trans(models.Model):
pk = UUIDField(auto=True, primary_key=True, serialize=True, hyphenate=True)
en = models.TextField('English')
class Article(models.Model):
pk = UUIDField(auto=True, primary_key=True, serialize=True, hyphenate=True)
title = models.OneToOneField(Trans)
description = models.OneToOneField(Trans)
Now if I want to add values in Article model via admin interface and for title and description there will be a '+' sign above the field to add values , on click Trans model form popup will shown where I can add values and then that instance will be attach into Article title field (Usual process).
But I do not want to add values like this , I want to show a simple text field to admin there for both title and description and on save those values saved into Trans model and their instance in Article model . In simple words I do not want to show '+' sign to admin but a simple text field.
Is this possible in Django admin if yes then any suggestions ?
I'm getting this error with TinyMCE in django:
TypeError: init() got an unexpected keyword argument 'widget'
I have followed the instructions as I found them, and don't know why the error is there. Here is the model:
class Article(models.Model):
"""Represents a wiki article"""
title = models.CharField(max_length=100)
slug = models.SlugField(max_length=50, unique=True)
text = models.TextField(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))# (help_text="Formatted using ReST")
author = models.ForeignKey(User)
is_published = models.BooleanField(default=False, verbose_name="Publish?")
created_on = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
published = PublishedArticlesManager()
The comment "#formatted in ReST" is because the original TextField was using restructuredText. I was able to actually get tinyMCE from CDN and place a very simpel script in the head of the appropriate template. It loaded the wysiwyg editor, but then rendered the saved page with HTML tags visible.
So I added to form declaration as:
from django import forms
from models import Article, Edit, FileUploadHandler
from tinymce import models as tinymce_models
class ArticleForm(forms.ModelForm):
class Meta:
text = forms.Charfield(widget=TinyMCE(attrs={'cols': 80, 'rows': 30}))#(help_text="Formatted using ReST")
model = Article
exclude = ['author', 'slug']
class EditForm(forms.ModelForm):
class Meta:
model = Edit
fields = ['summary']
class UploadImageForm(forms.ModelForm):
class Meta:
model = FileUploadHandler
image = forms.ImageField()
fields = ['title']
The editor is there, but upon save its rendering the article with html tags visible. Why is that?
widget is an attribute for form fields, not model fields. You need to move that setting to your form declaration (or formfield_overrides if you're trying to use it in the admin).
To display the marked up content without escaping the HTML tags in a later view, one way is to use the |safe built in filter.
I have this model:
class Gallery(models.Model):
HeadImage = models.ImageField(upload_to="gallery")
With this form:
class GalleryForm(ModelForm):
class Meta:
model = Gallery
And this view:
gform = GalleryForm(request.POST, request.FILES, instance=galleryInstance)
In template a filled form is shown. For the HeadImage field it shows a link to an image related to the HeadImage field, and a fileinput with a change label:
{{ gform.HeadImage }}
Now instead of a link to the picture, I want to put the image into an img tag. I do this in the template as follows:
<img src={{ gform.HeadImage.value }}/>
What should I do so that the link doesn't show in the form?
To prevent it from showing, use any of these three options:
Set editable=False on the model field;
Use the fields attribute of the ModelForm's inner Meta class.
Use the exclude attribute of the ModelForm's inner Meta class.
Which one to use depends on how often you want the field to show (never, or in select cases). See the Django docs for more information on this.
I have a model and a form like this:
class Content(models.Model):
title = models.CharField(_("title"), max_length=16)
category = models.ForeignKey(Category, verbose_name = _('category'))
class ContentForm(forms.ModelForm):
class Meta:
model=Content
fields = ('title', 'category', )
I would like to have the name of the field in the form to be f_category (of course the name of the field in the model is to stay category). Is it possible to do that, without having to construct the whole form manually (which is difficult because the field is a ForeignKey and has to be a select field with a list of options)?
To clarify: by name I mean the name as in the HTML form code: <input type="select" name="f_category" />
Your comment reveals what you actually need to do - this is why you should always describe your actual problem, not your proposed solution. Naturally, there is a proper way to deal with two identical forms on the same page in Django - use the prefix parameter when instantiating the field.
form1 = MyForm(prefix='form1')
form2 = MyForm(prefix='form2')
Now when you output form1 and form2, all the fields will automatically get the relevant prefix, so they are properly separated.
I'm not sure what you mean by "the name of the field in the form". Do you mean the label? Or the id? Or something else? Configuring the label is pretty easy:
class ContentForm(forms.ModelForm):
category = forms.ModelChoice(queryset=Category.objects.all(), label='f_category')
class Meta:
model=Content
fields = ('title', 'category', )
My form:
class PlanForm(forms.ModelForm):
owner = forms.ModelChoiceField(label="",
queryset=Profile.objects.all(),
widget=forms.HiddenInput())
etc...
class Meta:
model = Plan
Owner, in the model, is a ForeignKey to a Profile.
When I set this form, I set the value of "owner" to be a Profile object.
But when this comes out on the form, it seems to contain the name of the Profile like this:
<input type="hidden" name="owner" value="phil" id="id_owner" />
When the form is submitted and gets back to my views.py I try to handle it like this:
form = PlanForm(request.POST)
...
if form.is_valid():
plan = form.save()
return HttpResponseRedirect('/plans/%s'%plan.id) # Redirect after POST
However, what I get is a type-conversion error as it fails to turn the string "phil" (the user's name that was saved into the "owner" field) into an Int to turn it into the ForeignKey.
So what is going on here. Should a ModelForm represent a foreign key as a number and transparently handle it? Or do I need to extract the id myself into the owner field of the form? And if so, how and when do I map it back BEFORE I try to validate the form?
I suspect that the __unicode__ method for the Profile model instance, or the repr thereof is set to return a value other than self.id. For example, I just set this up:
# models.py
class Profile(models.Model):
name = models.CharField('profile name', max_length=10)
def __unicode__(self):
return u'%d' % self.id
class Plan(models.Model):
name = models.CharField('plan name', max_length=10)
profile = models.ForeignKey(Profile, related_name='profiles')
def __unicode__(self):
return self.name
# forms.py
class PlanForm(forms.ModelForm):
profile = forms.ModelChoiceField(queryset=Profile.objects.all(),
widget=forms.HiddenInput())
class Meta:
model = Plan
# views.py
def add_plan(request):
if request.method == 'POST':
return HttpResponse(request.POST['profile'])
profile = Profile.objects.all()[0]
form = PlanForm(initial={'profile':profile})
return render_to_response('add_plan.html',
{
'form':form,
},
context_instance=RequestContext(request))
With that, I see PlanForm.profile rendered thus in the template:
<input type="hidden" name="profile" value="1" id="id_profile" />
Hmm...
This might actually be a security hole.
Suppose a malicious attacker crafted a POST (say, by using XmlHttpRequest from FireBug) and set the profile term to some wacky value, like, your profile ID. Probably not what you wanted?
If possible, you may want to get the profile from the request object itself, rather than what's being submitted from the POST values.
form = PlanForm(request.POST)
if form.is_valid():
plan = form.save(commit=False)
plan.owner = request.user.get_profile()
plan.save()
form.save_m2m() # if neccesary
When you assign a Profile object to the form, Django stringifies it and uses the output as the value in the form. What you would expect though, is for Django to use the ID of the object instead.
Luckily, the workaround is simple: Just give the form primary key values of the Profile objects instead:
form = PlanForm(initial={'profile': profile.pk})
On the other end, when you're working with bound forms, however, they work much more sensibly:
form = PlanForm(request.POST)
if form.is_valid():
print form.cleaned_data['profile'] # the appropriate Profile object
There's usually no need to put related object into form field. There's a better way and this is specifying parent id in form URL.
Let's assume you need to render a form for new Plan object and then create one when form is bubmitted. Here's how your urlconf would look like:
(r"/profile/(?P<profile_id>\d+)/plan/new", view.new_plan), # uses profile_id to define proper form action
(r"/profile/(?P<profile_id>\d+)/plan/create", view.create_plan) # uses profile_id as a Plan field
And if you're changing existing object, all you need is plan_id, you can deduce any related record from it.
Since ModelChoiceField inherits from ChoiceFIeld, you should use the MultipleHiddenInput widget for this:
class PlanForm(forms.ModelForm):
owner = forms.ModelChoiceField(
queryset=Profile.objects.all(),
widget=forms.MultipleHiddenInput())
class Meta:
model = Plan