Creating multiple objects using the same form - django

Hi I have just read through, http://collingrady.wordpress.com/2008/02/18/editing-multiple-objects-in-django-with-newforms/, and am trying to apply it to my own django app.
I have created a view which lets me use a single form to create and store 2 objects that are related to each other
I am getting a post error but can't seem to find what is causing it.
After clicking add a blank white page is shown along with the error message below, which is in red in the terminal.
'[28/May/2014 02:57:25] "POST /members HTTP/1.1" 405 0'
Models
class MemberRole(models.Model,get_fields):
name = models.CharField(max_length = 20)
def __unicode__(self):
return self.name
class Member(models.Model,get_fields):
first_name = models.CharField(max_length = 20)
role = models.ForeignKey(MemberRole, null = True, blank = True)
Forms
class MemberForm(forms.ModelForm):
class Meta:
model = Member
exclude = ('role',)
class MemberRoleForm(forms.ModelForm):
class Meta:
model = MemberRole
View fucntion
def add_member(request):
model_url = 'member-list'
if request.method == "POST":
rform = MemberRoleForm(request.POST, instance=MemberRole())
mform = MemberForm(request.POST, instance=Member())
if rform.is_valid() and mform.is_valid():
new_role = rform.save()
new_member = mform.save()
return HttpResponseRedirect('member-list')
else:
rform = MemberRoleForm(instance=MemberRole())
mform = MemberForm(instance=Member())
return render_to_response('create_model.html', {'role_form': rform, 'member_form': mform, 'model_url': model_url,},context_instance=RequestContext(request))
snippet of create_model.html
<form action="{% url model_url %}" method="POST">
{% csrf_token %}
{% if model_url == 'member-list' %}
{% for field in member_form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
{% for field in role_form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endfor %}
{% endif %}
<input id="save_contact" type="submit" value="Add"/>
</form>

I've solved it, it was due to some errors in url naming
View
model_url = 'member-add'
return HttpResponseRedirect('members')
URLS
url(r'^members', ModelListView.as_view(model = Member,page_name = 'Members',edit_link = 'updatemember/'), name='member-list'),
url(r'^addmember', 'inventory.views.add_member', name = 'member-add'),

Related

I created a view that add stops to route and they are not appearing by parameter order from models

I created view where i add stops to route, its working fine, but stops are not appearing in order when i add them, and i have no idea why. Please tell me where i'm making a mistake
Here's my code:
Models:
class Port(models.Model):
name = models.CharField(max_length=128)
description = models.TextField(default='')
lattitude = models.DecimalField(max_digits=9, decimal_places=6)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
amenities = models.ManyToManyField(Amenity, blank=True)
def __str__(self):
return f'{self.name}'
class Route(models.Model):
name = models.CharField(max_length=128, default='')
user = models.ForeignKey(User, on_delete=models.CASCADE)
stop_list = models.ManyToManyField(Port, through='RoutePort')
def __str__(self):
return f'{self.name}'
class RoutePort(models.Model):
port = models.ForeignKey(Port, on_delete=models.CASCADE)
route = models.ForeignKey(Route, on_delete=models.CASCADE)
order = models.PositiveIntegerField()
class Meta:
ordering = ['order']
the order i intend them to appear is set by 'order' parameter from class routeport
form:
class AddRoutePort(forms.ModelForm):
class Meta:
model = RoutePort
fields = ['port', 'order']
form is short and i dont know if i didnt forget something there
View, get is working correctly, post works almost ok. New ports are correctly added to new route from list, but they appear in order of being added, not the one i wanted them to.
class RouteCorrectView(View):
def get(self, request, pk):
route = Route.objects.get(pk=pk)
form = AddRoutePort()
return render(request, 'route_correct.html', {'route':route, 'form':form})
def post(self, request, pk):
route = Route.objects.get(pk=pk)
form = AddRoutePort(request.POST)
if form.is_valid():
to_port = form.save(commit=False)
to_port.route = route
order = to_port.order
ordering = RoutePort.objects.filter(order__gte=order, route=route)
for port in ordering:
port.order += 1
port.save()
to_port.save()
return redirect('route_correct', pk)
return render(request, 'route_correct.html', {'route':route, 'form':form})
and HTML - i can't draw set order here, so i think theres a mistake somwhere previously. Line {{ stops.order }} does nothing.
{% extends 'base.html' %}
{% block content %}
<div class="card">
<ul>Nazwa</ul>
<p>{{ route.name }}</p>
<ul>Twórca</ul>
<p> {{ route.user }}</p>
<ul>Szlak</ul>
<td> {% for stops in route.stop_list.all %}
{{ stops }} {{ stops.order }}
<td>
<form action="{% url 'delete_stop' stops.id %}" method="get"> {% csrf_token %}
<input type="submit">usuń</form>
<form action="{% url 'port_detail' stops.id %}" method="get"> {% csrf_token %}
<input type="submit">o porcie</form><br>
</td>
{% empty %}
Szlak jest jeszcze pusty
{% endfor %}</td>
</div>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit">
</form>
</div>
{% endblock %}
So i found the solution. First of all i'm an idiot, second of all - html was problem
<td> {% for stops in route.stop_list.all %}
{{ stops }} {{ stops.order }}
<td>
Above part refer to stop list, not routeport model with "order" in it. It should look like that:
<td> {% for stops in route.routeport_set.all %}
{{ stops.port }} {{ stops.order }}
<td>
where i refer to routeport with order in it.

Data not save on database

In my website when someone register he give some values like 1st name,last name,email, password etc. Which save in auth_User database. I want to make a new model Profile which is child of User model. and its have some new fields.
models.py
class Profile(User):
image = models.ImageField(null=True,blank=True, upload_to="profile/")
bio = models.TextField(max_length=255,null=True)
address = models.CharField(max_length=255,null=True,blank=True,)
mobile_no = models.CharField(max_length=10,null=True,blank=True,)
website_url = models.CharField(max_length=255,null=True,blank=True,)
facebook_url = models.CharField(max_length=255,null=True,blank=True,)
twitter_url = models.CharField(max_length=255,null=True,blank=True,)
linkdin_url = models.CharField(max_length=255,null=True,blank=True,)
forms.py
class UserEditForm(UserChangeForm):
email = forms.EmailField(widget=forms.EmailInput(attrs={"class":"form-control"}) )
first_name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={"class":"form-control"}))
last_name = forms.CharField(max_length=100,widget=forms.TextInput(attrs={"class":"form-control"}))
class Meta:
model = Profile
fields = ('first_name','last_name','username','email','password','image','address','mobile_no','bio','website_url','facebook_url','twitter_url','linkdin_url')
widgets = {
"username" : forms.TextInput(attrs={"class":"form-control","placeholder":"write title of your posts"}),
"website_url" : forms.TextInput(attrs={"class":"form-control","placeholder":"write title of your posts"}),
"facebook_url" : forms.TextInput(attrs={"class":"form-control","placeholder":"write title of your posts"}),
"twitter_url" : forms.TextInput(attrs={"class":"form-control","placeholder":"write title of your posts"}),
"linkdin_url" : forms.TextInput(attrs={"class":"form-control","placeholder":"write title of your posts"}),
# # "title_tag" : forms.TextInput(attrs={"class":"form-control"}),
# # "author" : forms.HiddenInput(),
# # "image" : forms.Select(attrs={"class":"custom-file"}),
# "catagory" : forms.Select(choices=choices,attrs={"class":"form-control"}),
"bio" : forms.Textarea(attrs={"class":"form-control"}),
}
urls.py
path('edit_profile/',UserEditView.as_view(),name="editProfile"),
views.py
class UserEditView(UpdateView):
form_class = UserEditForm
template_name = 'edit_profile.html'
success_url = reverse_lazy('editProfile')
def get_object(self):
return self.request.user
edit_profile.html
{% extends 'base.html' %}
{% block title %} Edit Profile... {% endblock title %}
{% block content %}
<style>
label[for=id_password],.helptext,#id_password {
display: none;
}
</style>
{% if user.is_authenticated %}
<h1>Edit Profile... </h1>
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p}}
<button type="submit" class="btn btn-secondary">Update Profile</button>
</form>
{% else %}
<h3> You are not loged in</h3>
{% endif %}
{% endblock content %}
But from template when I want to add some value on these new fields, it does not save in app_Profile table of my database. but I can do this from admin panel
I also try to make signup page using profile table. but still not work
<form method="POST" enctype="multipart/form-data" action=".">
{% csrf_token %}
{{ form.as_p}}
<button type="submit" value="Save" class="btn btn-secondary">Update Profile</button>
Try this.

Why the attribute of an instance model does not change

I create a financial manager and I need the user to change the account activity (indicate an active account or not), but when I send the form for change, then the model attribute does not change and always remains TRUE
I also tried to do this through a copy of the Account, but it was also not a result of the outcome
Account.objects.get(user=self.request.user, id=id).is_active = False
models.py
class Account(models.Model):
type_of_currency = models.CharField(max_length=20)
user = models.ForeignKey(get_user_model(), blank=True,
related_name='user_account',
on_delete=models.CASCADE)
count = models.DecimalField(max_digits=12, decimal_places=2, blank=True)
created = models.DateTimeField(default=datetime.datetime.now)
is_active = models.BooleanField()
def __str__(self):
return f'{self.type_of_currency} - {self.count}'
views.py
class AccountDetailView(DetailView, UpdateView):
model = Account
form_class = AccountCreateForm
template_name = 'account_detail.html'
def post(self, request, *args, **kwargs):
id = self.request.POST['accountid']
self.request.user.user_account.get(id=6).is_active = False
print(self.request.user.user_account.get(
id=id).is_active) # always True why?
return redirect('/counts/' + id)
template
{% extends 'base.html' %}
{% block content %}
<div class="col-sm-5">
<h1>account: {{ account.id }}</h1>
<p><strong>Author:</strong> {{ account.user }}</p> <!-- author detail link not yet defined -->
<p><strong>Type:</strong> {{ account.type_of_currency }}</p>
<p><strong>count:</strong> {{ account.count }}</p>
<p><strong>IsCreated:</strong> {{ account.created }}</p>
<p><strong>IsActive:</strong>{{ account.is_active }}</p>
<a class="btn btn-outline-primary"
href="{% url 'account-list' %}">Back</a>
{% if account.is_active %}
<form method="post">
{% csrf_token %}
<input type="hidden" value="{{ account.id }}" name="accountid">
<button type="submit" class="btn btn-outline-danger">Deactivate</button>
</form>
{% else %}
<form method="post">
{% csrf_token %}
<button type="submit" class="btn btn-outline-success">Activate</button>
</form>
{% endif %}
</div>
{% endblock %}
In the post method DetailViews, I expect that after the button is pressed, user activity will change, but the result is always True
You're never commiting change to DB.
Also, I wouldn't use the following syntax: self.request.user.user_account.get(id=6).is_active = False
You can try: self.request.user.user_acocount.filter(id=6).update(is_active=False)
But, if you're dead set on using .get():
user_acc = self.request.user.user_account.get(id=6)
user_acc.is_active = False
user_acc.save()

Django: ModelFormSet saving first entry only

Update:
The issue seemed to be in the coding for Django-formset. I was processing it as an inline formset and not a model formset. The answer below was also correct. Thanks!
I am working with a model formset for an intermediate model. I am using django-formset js to add additional formset fields on the template. Most everything works OK except that when I go to save the formset only the first entry is being saved to the DB. The first entry is saved and assigned correctly but any after than just disappear. It is not throwing any errors so I am not sure what is going wrong. Thanks!
The Model
class StaffAssignment(models.Model):
study = models.ForeignKey(Study, related_name='study_set', null=True, on_delete=models.CASCADE)
staff = models.ForeignKey('account.UserProfile', related_name='assigned_to_set', null=True, on_delete=models.CASCADE)
role = models.CharField(max_length=100, null=True)
assigned_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-role',)
def __str__(self):
return '{} is assigned to {}'.format(self.staff, self.study)
The Form:
class AddStaff(forms.ModelForm):
model = StaffAssignment
fields = ('staff',)
def __init__(self, *args, **kwargs):
super(AddStaff, self).__init__(*args, **kwargs)
for field in self.fields:
self.fields[field].widget.attrs.update({'class': 'form-control'})
The View:
def add_staff(request, study_slug):
study = get_object_or_404(Study, slug=study_slug)
staff_formset = modelformset_factory(StaffAssignment, form=AddStaff, fields=('staff',), can_delete=True)
if request.method == 'POST':
staffList = staff_formset(request.POST, request.FILES)
if staffList.is_valid():
for assignment in staffList:
assigned = assignment.save(commit=False)
assigned.study = study
assigned.role = assigned.staff.job_title
assigned.save()
return HttpResponseRedirect(reverse('studies:studydashboard'))
else:
HttpResponse('Something is messed up')
else:
staffList = staff_formset(queryset=StaffAssignment.objects.none())
return render(request, 'studies/addstaff.html', {'staffList': staffList, 'study': study})
The Template:
<form action="{% url 'studies:addstaff' study.slug %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="box-body">
{% for list in staffList %}
<div class="form-group" id="formset">
{% if list.instance.pk %}{{ list.DELETE }}{% endif %}
{{ list.staff }}
{% if list.staff.errors %}
{% for error in list.staff.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
</div>
{% endfor %}
{{ staffList.management_form }}
</div>
<div class="box-footer">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
You are not including the primary key field in the template, as required by the docs. Add
{% for list in staffList %}
{{ list.pk }}
...
{% endfor %}

django - getting the requested user object in the template through models method

Please have a look at this code:
models:
class Activity(models.Model):
actor = models.ForeignKey(User)
action = models.CharField(max_length=100)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
pub_date = models.DateTimeField(auto_now_add=True, auto_now=False)
class Meta:
verbose_name = 'Activity'
verbose_name_plural = 'Activities'
ordering = ['-pub_date']
def __unicode__(self):
return ("%s %s") % (self.actor.username, self.action)
def get_rendered_html(self):
template_name = '%s_activity.html' %(self.content_type.name)
return render_to_string(template_name, {
'object':self.content_object,
'actor':self.actor,
'action':self.action,
})
template:
<div class="user_activity">
<p>{{ actor.username }} {{ action }} {{ object.content_object.user.username }} status</p>
<p>{{ object.content_object.body }}</p>
<p>{{ object.content_object.pub_date }}</p>
{% if object.content_object.image %}
<div class="activity_img_wrapper">
<p><img src="/media/{{ object.content_object.image }}"/></p>
</div>
{% endif %}
</div>
Question
How do I get the requested user's username for the above template (request.user). I did like this, but it didn't help :
<div class="user_activity">
<p>
{% if user.username == actor.username %}
You
{% else %}
{{ actor.username }}
{% endif %}
{{ action }}
{% if user.username == object.content_object.user.username %}
Your
{% else %}
{{ object.content_object.user.username }}
{% endif %}
status
</p>
<p>{{ object.content_object.body }}</p>
<p>{{ object.content_object.pub_date }}</p>
{% if object.content_object.image %}
<div class="activity_img_wrapper">
<p><img src="/media/{{ object.content_object.image }}"/></p>
</div>
{% endif %}
</div>
Please help me how to do it. I would really be grateful for your help. Thank you.
There is no RequestContext object available in the get_rendered_html() method so you can't pass it as a context_instance argument of the render_to_string(). This is why the user variable is not available in the template.
You should pass the User instance to get_rendered_html() method and propagate it to the template:
def get_rendered_html(self, user=None):
template_name = '%s_activity.html' %(self.content_type.name)
return render_to_string(template_name, {
'object':self.content_object,
'actor':self.actor,
'action':self.action,
'user':user,
})
If you want to call this method from other template then the best option is to use custom template tag:
# app/templatetags/activity_tags.py
# and don't forget to create empty app/templatetags/__init__.py :-)
from django import template
from django.utils.safestring import mark_safe
register = template.Library()
#register.simple_tag(takes_context=True)
def render_activity(context, activity):
user = context['user']
html = activity.get_rendered_html(user)
return mark_safe(html)
And then load and use this tag library in your template:
{% load activity_tags %}
...
{% render_activity activity %}