It's easy for templates: {{ field.id_for_label }}, but how to do same in view?
I need to get full id (with id_ and prefix). I can calculate it, but maybe is there a simpler way?
Update: I want to make a dictionary like {field_id: field_error_message} and send it back to browser as json response.
In view you can do the same - get the id_for_label property of the bound form field:
>>> from django import forms
>>> class MyForm(forms.Form):
... name = forms.CharField()
...
>>> form = MyForm(prefix='myform')
>>> form['name'].id_for_label
u'id_myform-name'
>>>
Related
In template I am trying to do something like this:
{{ request.user.profile.following.all.values_list }}
and I get
<QuerySet [(7, 2, 1)]>
, but I want to get
<QuerySet [2]>
like in Django values_list.
For example: Follow.objects.filter(follow_by=self.request.user.profile).values_list('follow_to', flat=True)
Can I pass argument like this in template?
Can I pass argument like this in template?
No. The Django template engine deliberately restricts this, since this is logic that belongs in the view. For example:
from django.contrib.auth.decorators import login_required
#login_required
def my_view(request):
following = request.user.profile.following.values_list('follow_to', flat=True)
return render(
request,
'some_template.html',
{'following': following}
)
You can then render this with:
{{ following }}
That being said, using .values_list(…) [Django-doc] is often an anti-pattern, since it erodes the model layer. It is thus something related to the primitive obsession antipattern [refactoring.guru].
I'm just wondering if there is a shortcut to do this code?
The code get's the video data and then mark_safe the embed code.
videos = Video.objects.all()
mark_safe_videos = []
for video in videos:
video.embed_code = mark_safe(video.embed_code)
mark_safe_videos.append(video)
I'm using Django 1.8
You can always just add a property to the model and avoid any additional code in the view:
from django.template.defaultfilters import mark_safe
class Video(models.Model):
. . .
#property
def safe_embed(self):
return mark_safe(self.embed_code)
I tend to favor the "fat model, skinny controller (view in Django)" methodology.
Additionally to Brandon's answer, which I would prefer, because it exposes that functionality throughout your whole app, you can also achieve it with a list comprehension in your view:
values_list for one field
videos = [mark_safe(v) for v in Videos.objects.values_list('embed_code', flat=True)]
values_list will return the requested fields as a list. Since only embed_code is relevant, using flat=True returns a one-dimensional list that we can use in the list comprehension to mark_safe their values into the videos variable.
Update: values_list for multiple fields
The same approach can be used for querying two or more fields.
# views.py
videos = [
(v[0], mark_safe(v[1]))
for v in Video.objects.values_list('title', 'embed_code')
]
And in the template:
{% for video in videos %}
Title: {{ video.0 }}<br/>
Embed code: {{ video.1 }}
{% endfor %}
I would do something like this:
def safe_embed_code(video):
video.embed_code = mark_safe(video.embed_code)
mark_safe_videos = [safe_embed_code(v) for v in Video.objects.all().iterator()]
Is it possible to populate a password field in wtforms in flask?
I've tried this:
capform = RECAPTCHA_Form()
capform.username.data = username
capform.password.data = password
The form is defined like:
class RECAPTCHA_Form(Form):
username = TextField('username', validators=[DataRequired()])
password = PasswordField('password', validators=[DataRequired()])
remember_me = BooleanField('Remember me.')
recaptcha = RecaptchaField()
The template looks like this:
<form method="POST" action="">
{{ form.hidden_tag() }}
{{ form.username(size=20) }}
{{ form.password(size=20) }}
{% for error in form.recaptcha.errors %}
<p>{{ error }}</p>
{% endfor %}
{{ form.recaptcha }}
<input type="submit" value="Go">
</form>
I have tried to change the PasswordField to a TextField, and then it works.
Is there some special limitation to populating PasswordFields in wtforms?
Update: After looking through the WTForms docs I found an even better solution. There is a widget arg.
from wtforms import StringField
from wtforms.widgets import PasswordInput
class MyForm(Form):
# ...
password = StringField('Password', widget=PasswordInput(hide_value=False))
As yuji-tomita-tomita pointed out, the PasswordInput class (source) has an hide_value argument, however the constructor of PasswordField (source) does not forward it to the PasswordInput. Here is a PasswordField class that initializes PasswordInput with hide_value=False:
from wtforms import widgets
from wtforms.fields.core import StringField
class PasswordField(StringField):
"""
Original source: https://github.com/wtforms/wtforms/blob/2.0.2/wtforms/fields/simple.py#L35-L42
A StringField, except renders an ``<input type="password">``.
Also, whatever value is accepted by this field is not rendered back
to the browser like normal fields.
"""
widget = widgets.PasswordInput(hide_value=False)
Something I've found with Flask, and Flask apps in general, is that the source is the documentation. Indeed, it looks like by default you cannot populate the field. You can pass an argument hide_value to prevent this behavior.
This is a good call, since if you can populate the field, you have access to the raw password... which could be dangerous.
class PasswordInput(Input):
"""
Render a password input.
For security purposes, this field will not reproduce the value on a form
submit by default. To have the value filled in, set `hide_value` to
`False`.
"""
input_type = 'password'
def __init__(self, hide_value=True):
self.hide_value = hide_value
def __call__(self, field, **kwargs):
if self.hide_value:
kwargs['value'] = ''
return super(
I believe there is an easier way to access the data of the password field, without usinghide_value. In your view, simply add in the request data as an argument to the form's constructor:
from flask import request
capform = RECAPTCHA_Form(request.form)
capform.username.data = username
capform.password.data = password
This should make the password input available for validation, and to be used in testing if desired.
I'm trying to use a javascript library in django that requires some attributes for HTML elements in camelCase. For example, I've a model with a CharField field like this:
expires = models.DateField("Expiration Date", db_index = False, blank = True, null = True, editable = True, help_text = "Something")
My ModelForm has the following line in the init method:
self.fields['expires'].widget.attrs['SomeAttribute'] = "SomeValue"
and after the render_to_response the outputed HTML is like this:
<input id="id_expires" type="text" name="expires" someattribute="SomeValue">
instead of:
<input id="id_expires" type="text" name="expires" SomeAttribute="SomeValue">
Am I missing something?
As Issac points out at the top, what you've should be correct. The Django internals responsible for rendering the above in django.forms.widgets
return mark_safe(u'<input%s />' % flatatt(final_attrs))
should give you the correct attr you're looking for. I did get to replicate your problem when I inspected the HTML rendered in Firebug. It seems that Firebug lowercases the attribute name but when I did a view source code, it did show as SomeAttribute versus someattribute in Firebug (if this is indeed what you're doing :))
I couldn't find anything in the django forms codebase that suggests that it's anything that's django's fault. How are you rendering the form? Please see my shell session for my details.
>>> from django import forms
>>> class F(forms.Form):
... a = forms.CharField()
...
>>> f = F()
>>> f.as_p()
u'<p><label for="id_a">A:</label> <input type="text" name="a" id="id_a" /></p>'
>>> f.fields['a'].widget.attrs
{}
>>> f.fields['a'].widget.attrs['dERP'] = 'ddf'
>>> f.as_p()
u'<p><label for="id_a">A:</label> <input id="id_a" type="text" name="a" dERP="ddf" /></p>'
>>>
I have a form in my forms.py that looks like this:
from django import forms
class ItemList(forms.Form):
item_list = forms.ChoiceField()
I need to populate the item_list with some data from the database. When generated in HTML item_list should be something like:
<select title="ItemList">
<option value="1">Select Item 1</option>
<option value="2">Select Item 2</option>
</select>
The options values in my select statement will change almost every time since a variable in the query will often change generating new results.
What do I need to put in the view.py and also in my template files to populate the ItemList with values from the database?
Take a look at this example in the Django documentation:
http://docs.djangoproject.com/en/dev/topics/forms/modelforms/#a-full-example
Basically, you can use the queryset keyword argument on a Field object, to grab rows from your database:
class BookForm(forms.Form):
authors = forms.ModelMultipleChoiceField(queryset=Author.objects.all())
Update
If you need a dynamic model choice field, you can hand over your item id in the constructor of the form and adjust the queryset accordingly:
class ItemForm(forms.Form):
# here we use a dummy `queryset`, because ModelChoiceField
# requires some queryset
item_field = forms.ModelChoiceField(queryset=Item.objects.none())
def __init__(self, item_id):
super(ItemForm, self).__init__()
self.fields['item_field'].queryset = Item.objects.filter(id=item_id)
P.S. I haven't tested this code and I'm not sure about your exact setup, but I hope the main idea comes across.
Resources:
http://www.mail-archive.com/django-users#googlegroups.com/msg48058.html
http://docs.djangoproject.com/en/dev/ref/forms/fields/#django.forms.ModelChoiceField
What you need to do is to find out which object do you actually want for e.g. if you want to find out a book named "Upvote-if-u-like!" then your urls.py should like
urlpatterns = [
path('textshare/<str:slug>',views.extract,name="textshare"),]
now when someone will search for mybook.com/textshare/upvote-if-u-like!/
it will take him/her to views.py which would look like
def extract(request,slug):
context={}
obj=bookForm.objects.get(title=slug)
form=bookModelForm(instance=obj)
context={'form':form}
return render(request,'bookfound.html',context)
where bookForm is in Models.py and bookModelForm is in forms.py
Happy Djangoing:)