I am working on a project where users can upload a post, edit a post and tag other users. I was able to implement upload post, edit and tag users (I implemented tag users with jquery ui). When i want to edit a post i have already tagged users on, i do not get the names of the users on select option field, instead it shows empty. How do i save/show users already tagged users from manytomany field in select option field in template. I will attach images to my question for clarity.
These are the users i tagged on my post, showing in manytomany field:
This image below is what i want, when i want to edit my post, let all tagged users of that post be shown in select option field:
Views.py:
def update_post_view(request, id):
#update post
post = get_object_or_404(Post, id=id)
edit_form = PostForm(request.POST, instance=post)
if request.method == "POST":
if edit_form.is_valid():
edit_form.save()
return redirect('site:comments', id=id)
else:
edit_form = PostForm(instance=post)
#Tag username dropdown in form
tag_list_users = User.objects.all()
context = {
'edit_form': edit_form,
'post':post,
'tag_list_users': tag_list_users,
}
return render(request, 'update_post.html', context)
Template:
<label for="id_tag_someone">Tag someone:</label><br>
<select name="tag_someone" id="id_tag_someone" multiple="" class="chosen w-100">
{% for user in tag_list_users %}
<option value="{{user.pk}}">{{user}}</option>
{% endfor %}
</select>
jQuery:
$('.chosen').chosen();
I was able to get this working by adding code to my views and template:
Views.py
#tagged_users is a related_name to tag someone in Model
tagged_user = User.objects.filter(tagged_users=post)
Template
<label for="id_tag_someone">Tag someone:</label><br>
<select name="tag_someone" id="id_tag_someone" multiple="" class="chosen w-100">
{% for user in tagged_users %}
<option value="{{user.pk}}">{{user}}</option>
{% endfor %}
{% for user in tag_list_users %}
<option value="{{user.pk}}">{{user}}</option>
{% endfor %}
</select>
Related
I currently have fully functional commenting form in my blog post view that I want to display in the ListView. Sort of like linkedin has under every list item, if you have noticed, i think facebook has the same thing.
Is there a shortcut to achieve this?
I supposed you can combine a ListView with a FormMixin (https://docs.djangoproject.com/fr/4.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.ModelFormMixin)
In each item of list, you create your form html and checking if form exist and if form instance corresponds to current list view for displaying errors and data in case of invalid form sent.
class MyPostList(FormMixin, ListView);
model = Post
form = CommentAddForm
template...
class CommentAddForm(ModelForm):
class Meta:
model = Comment
fields = ('post_id', 'txt'...)
{% for post in post_list %}
{{post}}
<form>
{% if form.data.post_id == post.pk %}{{form.errors}}{% endif %}
<input type="hidden" name="post_id" value="{{post.pk}}" />
</form>
{% endfor %}
I am trying to update my foem, and I have Country value in dropdown and I want to get this value in request, so that i can update my form using this value in request, Please check my code and let me know where I am mistaking.
Here is my test.html file...
<select name='country'>
<option>Select One</option>
{% for countries in country %}
<option value="{{country.id}}" {% if countries.id == datas.country_id %}selected{% endif
%}>{{countries.country}}</option>
{% endfor %}
</select>
here is my views.py file...
datas = MyModelName.objects.get(pk=id)
if request.method == "POST"
datas.country = request.POST.get('country')
datas.save()
it's not selecting the country, it's giving me error, Please guide me how i can solve this issue.
you better use ModelForm to edit data in your models, it allows you to check all entered values in more clean way
create ModelForm to edit your data
class MyModelNameEditForm(forms.ModelForm):
class Meta:
model = MyModelName
then in your views.py you can do this:
datas = MyModelName.objects.get(pk=id)
if request.POST:
edit_form = MyModelNameEditForm(request.POST, instance=datas)
if edit_form.is_valid():
edit_form.check()
else:
edit_form = MyModelNameEditForm(instance=datas)
# don't forget to send your form as a parameter to your template
return render(request, "path_to_template/test.html", {'edit_form': edit_form})
then in your test.html you can replace:
<select name='country'>
<option>Select One</option>
{% for countries in country %}
<option value="{{country.id}}" {% if countries.id == datas.country_id %}selected{% endif
%}>{{countries.country}}</option>
{% endfor %}
</select>
with one line
{{ edit_form.country }}
you can read more about ModelForm in official docs https://docs.djangoproject.com/en/3.1/topics/forms/modelforms/#modelform
I have struggled with this problem for a while so I appreciate any help, however vague.
Django 2.0.1: The "required" setting that Django uses for validating whether a field is valid works fine if I input:
{{ client_primary_sector }} in to the applicable html file with the "required" setting chosen via the data model (blank=False) or via forms.py (attrs={"required": "required"}). However, the "required" setting fails when I use for loops to produce radio buttons.
See below for a working and broken example.
models.py:.
class SurveyInstance(models.Model):
client_primary_sector = models.CharField(choices=PRIMARY_SECTOR, null=True, default='no_selection', blank=False, max_length=100)
Please note from above the `default='no_selection', which is not in the PRIMARY_SECTOR choices and isn't rendered as an option to the user. This forces the user to select before data is saved (I have confirmed it works).
forms.py
class ClientProfileForm(ModelForm):
class Meta:
model = SurveyInstance
fields = ('client_primary_sector',)
widgets = {'client_primary_sector': forms.RadioSelect(choices=PRIMARY_SECTOR, attrs={"required": "required"}),
}
views.py
def client_profile_edit(request, pk):
# get the record details from the database using the primary key
survey_inst = get_object_or_404(SurveyInstance, pk=pk)
# if details submitted by user
if request.method == "POST":
# get information from the posted form
form = ClientProfileForm(request.POST, instance=survey_inst)
if form.is_valid():
survey_inst = form.save()
# redirect to Next view:
return redirect('questionnaire:business-process-management', pk=survey_inst.pk)
else:
# Retrieve existing data
form = ClientProfileForm(instance=survey_inst)
return render(request, 'questionnaire/client_profile.html', {'form': form})
client_profile.html
<!-- this works: -->
<!-- <div class="radio_3_cols">
{{ form.client_primary_sector }}
</div> -->
<!-- this doesn't: -->
{% for choice in form.client_primary_sector %}
<div class="radio radio-primary radio-inline">
{{ choice.tag }}
<label for='{{ form.client_primary_sector .auto_id }}_{{ forloop.counter0 }}'>{{ choice.choice_label }}</label>
</div>
{% endfor %}
You may wonder why I don't just use the working solution... I would like to be able to use the for loop logic for other situations and so require a solution.
Answered my own question. From the documentation for 2.0:
https://docs.djangoproject.com/en/2.0/ref/forms/widgets/#radioselect
The correct syntax is:
{% for radio in form.client_profile %}
<label for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
<span class="radio">{{ radio.tag }}</span>
</label>
{% endfor %}
Not whatever I found before. Confirmed as working. Hoorah!
I have a Django site built on a model formset (forms.py). The model formset is picked up by my view (views.py). The view is rendered in my template (alerts.html). The user sees a list of alerts with entity and logic populated. They must enter a comment on one or more forms in the formset and then click the submit button to post the one or more forms to the DB. When the submit button is clicked currently, the page refreshes and a successful POST (200) displays in runserver, but the data is not saved to the DB. formset.errors shows that comment is required for each field, not just the form that was changed.
I tried adding if formset.has_changed(): prior to calling formset.save(), but the problem persisted.
How should I alter my project to allow the model formset to be saved appropriately?
EDIT: I migrated blank=True for comment. Now when the submit button is clicked, the data is saved. However, the comment text (and the rest of the form) remains in the table in the template. When submit is clicked again, the comment text remains and entity and logic are replaced by blanks.
forms.py
class AlertForm(ModelForm):
class Meta:
model = Alert
fields = [
'comment'
]
AlertFormSet = modelformset_factory(Alert, extra=0, form=AlertForm)
views.py
def alerts(request):
newAlerts = Alert.objects.filter(comment='')
formset = AlertFormSet(request.POST or None, queryset=newAlerts)
context = {'formset':formset}
if request.method == 'POST':
formset = formset
if formset.is_valid():
formset.save()
else:
formset = formset
print(formset.errors)
return render(request, 'alerts/alerts.html', context)
alerts.html
<form method='POST' action=''>
{{ formset.management_form }}
{% csrf_token %}
<input name="submit" value="Submit" id="submit-id-submit" type="submit">
{% for form in formset %}
{% for hidden_field in form.hidden_fields %}
{{ hidden_field }}
{% endfor %}
{% endfor %}
<table>
<thead>
<tr>
<th>Entity</th>
<th>Logic</th>
<th>Comment</th>
</tr>
</thead>
<tbody>
{% for form in formset %}
<tr>
<td>{{ form.instance.entity }}</td>
<td>{{ form.instance.logic }}</td>
<td>{{ form.comment }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
The formset is invalid because you are not submitting the values for the entity or logic fields. You would see this if you printed formset.errors in your view or included the form errors in the template.
Since you don't want entity or logic to be editable, you should not include these in the formset's fields:
class AlertForm(ModelForm):
class Meta:
model = Alert
fields = [
'comment',
]
Since you are defining fields in the form, you shouldn't need to include exclude when you call modelformset_factory.
AlertFormSet = modelformset_factory(Alert, extra=0, form=AlertForm)
Try looping over the data in the formset like this
if request.method == 'POST':
formset = formset
if formset.is_valid():
for form in formset:
cleaned_data = form.cleaned_data
entity = cleaned_data.get('entity')
logic = cleaned_data.get('logic')
comment = cleaned_data.get('comment')
# create a new Alert object here
alert = Alert(entity=entity, logic=logic, comment=comment)
alert.save()
I'm new to Django and was needing some help on a view error i am getting.
I wrote a view that will display a data table of "Groups" if the request method is GET, or display a form to edit a particular "Group" if the request method is POST (item to edit is passed with POST data).
Also, if POST on an existing item, i'd like the form to be pre-populated with the data i already have in the table for that item. I've pretty much got it all down, except when i goto save an edited form, i keep getting this error:
"Cannot set values on a ManyToManyField which specifies an intermediary model"
Any help would be greatly appreciated. Also, I'm new to all this web dev stuff, so if i'm doing something completely silly or am missing a concept, please feel free to flame me accordingly. ;-)
Model
class Alias(models.Model):
def __unicode__(self):
return unicode(self.alias)
alias = models.CharField(max_length=32)
class Octet(models.Model):
def __unicode__(self):
return unicode(self.num)
num = models.IntegerField(max_length=3)
class Group(models.Model):
def __unicode__(self):
return unicode(self.name)
name = models.CharField(max_length=32) #name of the group
id = models.AutoField(primary_key=True) #primary key
octets = models.ManyToManyField(Octet, through='OctetAssignment', blank=True) #not required
aliases = models.ManyToManyField(Alias, through='AliasAssignment', blank=True) #not required
class OctetAssignment(models.Model):
octet = models.ForeignKey(Octet) #octet
group = models.ForeignKey(Group) #group that octet is assigned to
class AliasAssignment(models.Model):
alias = models.ForeignKey(Alias)
group = models.ForeignKey(Group)
View
def index(request):
if request.method == 'GET':
groups = Group.objects.all().order_by('name')
return render_to_response('groups.html',
{ 'groups': groups, },
context_instance = RequestContext(request),
)
elif request.method == "POST":
g = Group.objects.get(id=request.POST['id'])
form = GroupEditForm(instance=g)
return render_to_response('groups.html',
{ 'form': form, },
context_instance = RequestContext(request),
)
def save(request):
if request.method == "POST":
form = GroupEditForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/tradedesk/groups/') # Redirect after POST
To make it complete, here is the form template code i'm using that renders the table and edit page.
Template
<h1>Group Information</h1>
{% if groups %}
<table border=1>
{% for group in groups %}
<tr>
<td>{{group.name}}</td>
<td>{% for octet in group.octets.all %} {{octet}} {% endfor %}</td>
<td>{% for alias in group.aliases.all %} {{alias}} {% endfor %}</td>
<td>{{group.analyst}}</td>
</tr>
{% endfor %}
</table>
<br></br>
<form method="post" action="/groups/">{% csrf_token %}
<select name="id" >
{% for group in groups %}
<option value="{{group.id}}">{{group.name}}</option>
{% endfor %}
</select>
<input type="submit" value="Edit">
</form>
{% endif %}
{% if form %}
<form method="post" action="/groups/save/">{% csrf_token %}
{{form}}
<br></br>
<input type="submit" value="Save">
<form>
{% endif %}
</div>
Try to remove the intermediary models OctetAssignment and AliasAssignment. They should be used only when you want to add custom fields to them. Otherwise Django creates them and uses them transparently by itself.