I am developing a task management system using the django framework where supervisors can log in and assign tasks to multiple users using Django many to many field. When I log in to the admin portal, I can select multiple users at the same time which saves to the database well. But when I use the front end template, I am able to select multiple users but the selected options never get saved in the database and instead the field will be blank when viewing from the database table.
Here is my Model:
from django.contrib.auth.models import User
class Task(models.Model):
task_title = models.CharField(max_length=30, blank=True, null=True)
unit = models.ForeignKey(Unit, blank=True, null=True)
audit_phase_choice = (
('Pre Engagement', 'Pre Engagement'),
('Understanding Entity', 'Understanding Entity'),
('Risk Assessment', 'Risk Assessment'),
('Performing Audit', 'Performing Audit'),
('Report', 'Report'),
)
audit_phase = models.CharField(max_length=30, blank=True, null=True, choices=audit_phase_choice)
assigned_by = models.CharField(max_length=30, blank=True, null=True)
assigned_to = models.ManyToManyField(User, blank=True)
date_assigned = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
status = models.CharField(max_length=30, blank=True, null=True)
completed = models.BooleanField('Task Completed', default=False)
date_completed = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
start_date = models.DateTimeField(auto_now_add=False, auto_now=False, blank=True, null=True)
due_date = models.DateField(auto_now_add=False, auto_now=False, blank=True, null=True)
comment = models.TextField('comments', max_length=3000, default='', blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False, blank=True)
def __unicode__(self):
return self.task_title
def get_absolute_url(self):
return reverse("taskmis:user_task_edit", kwargs={"id": self.id})
Here is the form.py content
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ['task_title',
'unit',
'assigned_to',
'start_date',
'due_date',
'comment']
Here is the view.py content:
def user_task_entry(request):
title = 'Assign Task'
form = TaskForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.assigned_by = request.user
instance.save()
return redirect('taskmis:user_task_list')
context = {
"title": title,
"form": form,
}
return render(request, "task_entry.html",context)
You need to call save_m2m() manually because you set the commit=False when you call the save method
Django Ref
To work around this problem, every time you save a form using
commit=False, Django adds a save_m2m() method to your ModelForm
subclass. After you’ve manually saved the instance produced by the
form, you can invoke save_m2m() to save the many-to-many form data.
For example:
Related
In my create order view, I am trying to automatically assign the respective route based on the location the user inputs. Basically, every location in the system has a FK to a route. There are many locations within a route. If you select a location to send products to, the route should automatically be tied to.
Currently I am able to see the route for an order in my order_list.html page, but when I view the order in the Django admin, the route is not assigned to the order but the location is.
I want it to work similarly to how you would assign the current logged in user to an order:
form.instance.user = request.user
I tried using:
form.instance.company = request.user.company
But I am getting an attribute error:
'WSGIRequest' object has no attribute 'location'
Here is my full order_create function:
orders/views.py:
#login_required(login_url='account_login')
def order_create(request):
"""
A function that takes the users cart with products, then converts the cart into an
OrderForm. Then saves the form/order to the database.
"""
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.instance.company = request.user.company
form.instance.route = request.location.route
order = form.save()
for item in cart:
OrderItem.objects.create(order=order,
product=item['product'],
price=item['price'],
quantity=item['quantity'])
# clear the cart
cart.clear()
return render(request,
'orders/order/created.html',
{'order': order,
})
else:
form = OrderCreateForm()
return render(request,
'orders/order/create.html',
{'cart': cart, 'form': form})
Here are the Location, Route and Order models:
orders/models.py:
class Route(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Locations(models.Model):
"""
A model to represent a location or locations a company has.
"""
name = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
route = models.ForeignKey(Route, on_delete=models.DO_NOTHING)
store_number = models.CharField(max_length=15, blank=True, null=True)
address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, blank=True, null=True)
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
route = models.ForeignKey(Route, on_delete=models.DO_NOTHING, blank=True, null=True)
location = models.ForeignKey(Locations, on_delete=models.DO_NOTHING, blank=True, null=True)
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING, blank=True, null=True)
delivery_date = models.DateField()
address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
delivered = models.BooleanField(default=False)
and then finally the company and user model in my accounts app that are used as foreign keys in the orders app.
accounts/models.py:
class Company(models.Model):
"""
A model to represent companies that can operate within the system, which multiple users are apart of.
"""
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
city = models.CharField(max_length=25)
state = USStateField()
zip = models.CharField(max_length=5)
admin = models.ForeignKey("accounts.User", on_delete=models.DO_NOTHING, related_name="company_admin", blank=True, null=True)
class User(AbstractBaseUser, PermissionsMixin):
"""
A model to represent a User of the system.
"""
ROLE_CHOICES = (
('ADMIN', "Admin"),
('MANAGER', "Manager"),
('DRIVER', "Driver"),
('PRODUCTION', "Production")
)
email = models.EmailField(max_length=254, unique=True)
phone = models.CharField(max_length=15, help_text="(123)-123-1234", blank=True, null=True)
first_name = models.CharField(max_length=254, null=True, blank=True)
last_name = models.CharField(max_length=254, null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True)
role = models.CharField(max_length=10, choices=ROLE_CHOICES, default=None, blank=True, null=True)
is_employee = models.BooleanField(default=False, blank=True, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
I have a model and I am trying to save the user to the models database when the user submits the form. I had a site that did this but now my editor says "Use of super on an old style class"
I am using django 1.8 and i get
IntegrityError at /auction/createview/ NOT NULL constraint failed:
auction_auction.user_id
which is the nicest error I have been able to get. with all the tinkering i have done
class AuctionCreateView(LoginRequiredMixin,CreateView):
model = Auction
action = "created"
form_class = AuctionForm
auction_form = AuctionForm(initial={'user':request.user})
class AuctionForm(forms.ModelForm):
class Meta:
model = Auction
fields = (
"user",
"item_name",
"reserve",
"start_date",
"end_date",
"description",
"tags",
)
class Auction(models.Model):
user = models.ForeignKey(User)
item_id = models.CharField(max_length=255, blank=True, null=True)
item_name = models.CharField(max_length=255, blank=True, null=True)
winner = models.ForeignKey(User, related_name='Auction_Winner', blank=True, null=True)
reserve = MoneyField(max_digits=10, decimal_places=2, default_currency='USD')
created = models.DateTimeField(editable=False, null=True)
slug = AutoSlugField(('slug'), max_length=128, unique=True, populate_from=('item_name',))
start_date = models.DateTimeField(verbose_name="Start date")
end_date = models.DateTimeField(verbose_name="End date")
active = models.BooleanField(default=False, verbose_name='Active')
total_bids = models.IntegerField(default=0, verbose_name='Total bids')
date_added = models.DateTimeField(auto_now_add=True, verbose_name='Date added')
last_modified = models.DateTimeField(auto_now=True, verbose_name='Last modified')
description = models.TextField(max_length=3000)
tags = tagging.fields.TagField()
# bid_set = models.IntegerField(default= 0, verbose_name = "Bid set")
starting_amount = MoneyField(max_digits=10, decimal_places=2, default_currency='USD')
def __unicode__(self):
return '%s selling %s' % (self.user, self.item_name)
def _get_increment(self):
""" add some logic to base incrementing amount on starting price """
def get_absolute_url(self):
return reverse('auction_detail',
kwargs={'slug': self.slug})
when i saw this post I thought i'd be able to figure it out. thanks ★ ✩
You need insert user_id before form save.
AuctionForm - need update request.user value. Added this fields from form initial.
You have to include 'user' on the fields of the Auction form class to solve that error and just put an initial parameter on the form instance in the views.py like
auction_form = AuctionForm(initial={'user':request.user})
because request.user on the form_valid method will not work at all
I'm trying to save an existing instance of a customer record. Its model has a M2M to the vehicle model (since a customer can multiple vehicles). After reading several questions/answer here, I still do not know how to solve this.
Customer model:
class Customer(models.Model):
vehicle_id = models.ManyToManyField(VehicleSale)
name = models.CharField(max_length=40, blank=True, db_index=True, null=True,
verbose_name='name')
lic = models.CharField(max_length=20, blank=True, db_index=True, null=True,
verbose_name='license')
addr = models.CharField(max_length=40, blank=True, null=True, verbose_name='address')
city = models.CharField(max_length=15, blank=True, null=True, verbose_name='city')
state = models.CharField(max_length=2, blank=True, null=True, verbose_name='state')
zip = models.CharField(max_length=10, blank=True, null=True, verbose_name='zipcode')
email = models.EmailField(blank=True, null=True, verbose_name='email')
tel1 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 1', null=True)
tel2 = models.CharField(max_length=15, blank=True, verbose_name='Tel. 2', null=True)
ssn = models.CharField(max_length=12, blank=True, db_index=True, null=True,verbose_name='SSN')
class Meta:
db_table = 'customer'
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
self.name = self.name.upper()
self.addr = self.addr.upper()
self.city = self.city.upper()
self.state = self.state.upper()
return super(Customer, self).save(*args, **kwargs)
In the view, after defining customer as
customer = current_vehicle.customer_set.all()
I tried the following:
if 'customer' in request.POST:
if customer:
customer_form = CustomerForm(request.POST, instance=customer[0])
if customer_form.is_valid():
customer_form.save()
Also tried adding before customer_form is defined:
customer.vehicle_id = current_vehicle.id
And then this after the form:
customer_form.vehicle_id = current_vehicle.id
Form is not valid so it's not saved. Upon checking {{ form.errors}}, it always reports vehicle_id is required.
Finally, after the answer in this, I adjusted it to my scenario by adding:
obj = customer_form.save(commit=False)
and hoping to assign vehicle_id, but it fails immediately.
What am I missing?
Thanks.
1st EDIT:
The section on the view now looks as:
customer_form = CustomerForm(request.POST, instance=customer[0])
customer_form.save()
customer_form.vehicle_id.add(current_vehicle)
You are misunderstanding what a ManyToMany field is here:
customer_form.vehicle_id = current_vehicle.id
vehicle_id is defined as a ManyToMany field on your Customer model, therefore you can't just assign a single id to it. You have to add an instance of VehicleSale model, eg:
customer_form.vehicle_id.add(current_vehicle)
See docs here:
https://docs.djangoproject.com/en/dev/topics/db/examples/many_to_many/
See also this answer for why you can't save until you populate the vehicle_id relation:
https://stackoverflow.com/a/2529875/202168
I'm trying to create a view with a formset of forms for the "Link" model. The problem is that in each form I would like the user to have the possibility of not just choosing from the already created TargetLink objects, but to edit them inline.
class ClientUrl(models.Model):
client = models.ForeignKey(UpstreamClientModel, null=True)
url = models.URLField(unique=True, null=False)
active = models.BooleanField(default=True)
def __unicode__(self):
return self.url
class Meta:
verbose_name = 'url'
ordering = ['url']
KEYWORD_TYPES = (
('PN', 'Pending'),
('MN', 'Money'),
('BR', 'Brand'),
('LT', 'Long Tail'),
)
class ClientKeyword(models.Model):
client = models.ForeignKey(UpstreamClientModel, null=True)
kw_type = models.CharField('keyword type', max_length=2,
choices=KEYWORD_TYPES, default='LT')
keyword = models.CharField(max_length=150, unique=False)
directions = models.CharField(max_length=200, blank=True,
help_text='e.g: 25 chars, use "affordable rental cars"')
def __unicode__(self):
return self.keyword
class Meta:
ordering = ['keyword', ]
unique_together = ('client', 'keyword')
class TargetLink(models.Model):
keyword = models.ForeignKey(ClientKeyword, related_name='target_links')
url = models.ForeignKey(ClientUrl, related_name='target_links')
def __unicode__(self):
return '{0}:{1}'.format(self.keyword, self.url)
class Link(models.Model):
client = models.ForeignKey(UpstreamClientModel, related_name='links')
target = models.ForeignKey(Target, related_name='links')
user = models.ForeignKey(User, blank=True, null=True, related_name='links')
link_type = models.ForeignKey(LinkType, related_name='links')
site = models.ForeignKey(Site, blank=True, null=True,
related_name='links')
site_url = models.URLField(blank=True,
help_text='leave blank until url is live')
month = models.DateField(blank=True, null=True)
target_links = models.ManyToManyField(TargetLink, related_name='links')
How could I accomplish this?
One way might be to have a form that is outside of your formset for the TargetLinks and use Knockout.js or another client-side framework to push the updated choices for TargetLinks to the target_links field in the formsets.
I installed django profiles/registration and everything seems to be fine. When a user registers their profile is created also. Now what i want to do is query another Model which is Company based on the user id of User. I dont want to change django-profiles view but add the extra field on urls to match and query Company model. When i hardcode the url (ex:put the id number of the userprofile like so userprofile=1, it works.). So when a user is logged in and goes to profile detail page Company assigned to them is queried based on their user.id.
class UserProfile(models.Model):
user = models.OneToOneField(User)
#email = models.CharField(max_length=200, blank=True, null=True)
# Other fields here
#company = models.ForeignKey(Company,blank=True,null=True)
#office = models.CharField(max_length=200, blank=True, null=True)
def __unicode__(self):
return self.user.username
class Company(models.Model):
userprofile = models.ForeignKey(UserProfile, null=True, blank=True)
comp_name = models.CharField(max_length=200,blank=True,null=True)
comp_address = models.CharField(max_length=200,blank=True, null=True)
comp_email = models.CharField(max_length=200,blank=True, null=True)
comp_zip = models.IntegerField(blank=True, null=True)
comp_phone = models.IntegerField(blank=True, null=True)
comp_city = models.CharField(max_length=200,blank=True, null=True)
#comp_state = models.USStateField(blank=True, null=True
comp_state = models.CharField(blank=True, max_length=2)
compwebsite = models.URLField(max_length=200, blank=True, null=True)
twitterurl = models.URLField(max_length=200, blank=True, null=True)
facebookurl = models.URLField(max_length=200, blank=True, null=True)
def __unicode__(self):
return self.comp_name
url(r'^profiles/(?P<username>\w+)/$', 'profiles.views.profile_detail', {'extra_context':{'queryset':Company.objects.filter(userprofile=request.user.id)}},),
You might want to call it from inside a view
from *** import profile_detail
def my_view(request, username):
extra_context = {}
return profile_detail(request, queryset=Company.objects.filter(userprofile=request.user.id),
template_name="my_template.html",
paginate_by=20,
extra_context=extra_context)